fix(tvix/eval): quote keys which are not valid identifiers

The impl Display for NixAttrs needs to wrap double quotes around any
keys which are not valid Nix identifiers.  This commit does that,
and adds a test (which fails prior to this commit and passes after
this commit).

Change-Id: Ie31ce91e8637cb27073f23f115db81feefdc6424
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7084
Autosubmit: Adam Joseph <adam@westernsemico.com>
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
This commit is contained in:
Adam Joseph 2022-10-25 01:56:42 -07:00 committed by clbot
parent d8841376e7
commit 4ec43bed5e
3 changed files with 26 additions and 1 deletions

View file

@ -0,0 +1 @@
{ "3" = 3; }

View file

@ -0,0 +1 @@
{ "3" = 3; }

View file

@ -118,7 +118,13 @@ impl NixString {
match escaped { match escaped {
// A borrowed string is unchanged and can be returned as // A borrowed string is unchanged and can be returned as
// is. // is.
Cow::Borrowed(_) => escaped, Cow::Borrowed(_) => {
if is_valid_nix_identifier(&escaped) {
escaped
} else {
Cow::Owned(format!("\"{}\"", escaped))
}
}
// An owned string has escapes, and needs the outer quotes // An owned string has escapes, and needs the outer quotes
// for display. // for display.
@ -152,6 +158,23 @@ fn nix_escape_char(ch: char, next: Option<&char>) -> Option<&'static str> {
} }
} }
/// Return true if this string can be used as an identifier in Nix.
fn is_valid_nix_identifier(s: &str) -> bool {
// adapted from rnix-parser's tokenizer.rs
let mut chars = s.chars();
match chars.next() {
Some('a'..='z' | 'A'..='Z' | '_') => (),
_ => return false,
}
for c in chars {
match c {
'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-' => (),
_ => return false,
}
}
return true;
}
/// Escape a Nix string for display, as most user-visible representation /// Escape a Nix string for display, as most user-visible representation
/// are escaped strings. /// are escaped strings.
/// ///