fix(tvix/value): add ident_str representation of strings

When printing strings as identifiers (in attribute sets), the string
should only be quoted and escaped if it contains escape characters.

Change-Id: If2bcfa1e93dc8f00be4d7a57ec1d82fc679103c3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6127
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Autosubmit: tazjin <tazjin@tvl.su>
This commit is contained in:
Vincent Ambo 2022-08-10 19:09:27 +03:00 committed by tazjin
parent 92c53fe982
commit 5685f7c594
2 changed files with 25 additions and 8 deletions

View file

@ -37,7 +37,7 @@ impl Display for NixAttrs {
NixAttrs::Map(map) => { NixAttrs::Map(map) => {
for (name, value) in map { for (name, value) in map {
f.write_fmt(format_args!("{} = {}; ", name, value))?; f.write_fmt(format_args!("{} = {}; ", name.ident_str(), value))?;
} }
} }

View file

@ -43,6 +43,26 @@ impl NixString {
NixString::Heap(s) => s, NixString::Heap(s) => s,
} }
} }
// Return a displayable representation of the string as an
// identifier.
//
// This is used when printing out strings used as e.g. attribute
// set keys, as those are only escaped in the presence of special
// characters.
pub fn ident_str(&self) -> Cow<str> {
let escaped = nix_escape_string(self.as_str());
match escaped {
// A borrowed string is unchanged and can be returned as
// is.
Cow::Borrowed(_) => escaped,
// An owned string has escapes, and needs the outer quotes
// for display.
Cow::Owned(s) => Cow::Owned(format!("\"{}\"", s)),
}
}
} }
fn nix_escape_char(ch: char) -> Option<&'static str> { fn nix_escape_char(ch: char) -> Option<&'static str> {
@ -54,11 +74,11 @@ fn nix_escape_char(ch: char) -> Option<&'static str> {
} }
} }
// Escape a Nix string for display, as the user-visible representation // Escape a Nix string for display, as most user-visible representation
// is always an escaped string (except for traces). // are escaped strings.
// //
// Note that this does not add the outer pair of surrounding quotes. // Note that this does not add the outer pair of surrounding quotes.
fn escape_string(input: &str) -> Cow<str> { fn nix_escape_string(input: &str) -> Cow<str> {
for (i, c) in input.chars().enumerate() { for (i, c) in input.chars().enumerate() {
if let Some(esc) = nix_escape_char(c) { if let Some(esc) = nix_escape_char(c) {
let mut escaped = String::with_capacity(input.len()); let mut escaped = String::with_capacity(input.len());
@ -82,10 +102,7 @@ fn escape_string(input: &str) -> Cow<str> {
impl Display for NixString { impl Display for NixString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("\"")?; f.write_str("\"")?;
match self { f.write_str(&nix_escape_string(self.as_str()))?;
NixString::Static(s) => f.write_str(&escape_string(s))?,
NixString::Heap(s) => f.write_str(&escape_string(s))?,
};
f.write_str("\"") f.write_str("\"")
} }
} }