difftreelog
feat quote_keys option for Yaml
in: master
5 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -115,6 +115,12 @@
]
[[package]]
+name = "dtoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
+
+[[package]]
name = "gcmodule"
version = "0.3.3"
source = "git+https://github.com/CertainLach/gcmodule?branch=jrsonnet#f72713c24c2b1bf5a78f1d01bee5a0f52bc2a094"
@@ -216,6 +222,7 @@
"rustc-hash",
"serde",
"serde_json",
+ "serde_yaml",
"thiserror",
]
@@ -273,6 +280,12 @@
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
[[package]]
+name = "linked-hash-map"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+
+[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -467,6 +480,17 @@
]
[[package]]
+name = "serde_yaml"
+version = "0.8.21"
+source = "git+https://github.com/CertainLach/serde-yaml?branch=feature/old-octals-quirk#4bf0e325243539fdeb419e8d727ed1c161cbe445"
+dependencies = [
+ "dtoa",
+ "indexmap",
+ "serde",
+ "yaml-rust",
+]
+
+[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -601,6 +625,15 @@
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
name = "yansi-term"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
crates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/manifest.rs
@@ -173,6 +173,62 @@
/// ## <- this
/// ```
pub arr_element_padding: &'s str,
+ /// Should yaml keys appear unescaped, when possible
+ /// ```yaml
+ /// "safe_key": 1
+ /// # vs
+ /// safe_key: 1
+ /// ```
+ pub quote_keys: bool,
+}
+
+/// From https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289
+/// With added date check
+fn yaml_needs_quotes(string: &str) -> bool {
+ fn need_quotes_spaces(string: &str) -> bool {
+ string.starts_with(' ') || string.ends_with(' ')
+ }
+
+ string == ""
+ || need_quotes_spaces(string)
+ || string.starts_with(|character: char| match character {
+ '&' | '*' | '?' | '|' | '-' | '<' | '>' | '=' | '!' | '%' | '@' => true,
+ _ => false,
+ }) || string.contains(|character: char| match character {
+ ':'
+ | '{'
+ | '}'
+ | '['
+ | ']'
+ | ','
+ | '#'
+ | '`'
+ | '\"'
+ | '\''
+ | '\\'
+ | '\0'..='\x06'
+ | '\t'
+ | '\n'
+ | '\r'
+ | '\x0e'..='\x1a'
+ | '\x1c'..='\x1f' => true,
+ _ => false,
+ }) || [
+ // http://yaml.org/type/bool.html
+ // Note: 'y', 'Y', 'n', 'N', is not quoted deliberately, as in libyaml. PyYAML also parse
+ // them as string, not booleans, although it is violating the YAML 1.1 specification.
+ // See https://github.com/dtolnay/serde-yaml/pull/83#discussion_r152628088.
+ "yes", "Yes", "YES", "no", "No", "NO", "True", "TRUE", "true", "False", "FALSE", "false",
+ "on", "On", "ON", "off", "Off", "OFF", // http://yaml.org/type/null.html
+ "null", "Null", "NULL", "~",
+ ]
+ .contains(&string)
+ || (string.chars().all(|c| matches!(c, '0'..='9' | '-'))
+ && string.chars().filter(|c| *c == '-').count() == 2)
+ || string.starts_with('.')
+ || string.starts_with("0x")
+ || string.parse::<i64>().is_ok()
+ || string.parse::<f64>().is_ok()
}
pub fn manifest_yaml_ex(val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {
@@ -206,8 +262,10 @@
buf.push_str(options.padding);
buf.push_str(line);
}
+ } else if !options.quote_keys && !yaml_needs_quotes(&s) {
+ buf.push_str(&s);
} else {
- escape_string_json_buf(s, buf)
+ escape_string_json_buf(s, buf);
}
}
Val::Num(n) => write!(buf, "{}", *n).unwrap(),
@@ -253,7 +311,11 @@
buf.push('\n');
buf.push_str(cur_padding);
}
- escape_string_json_buf(key, buf);
+ if !options.quote_keys && !yaml_needs_quotes(&key) {
+ buf.push_str(&key);
+ } else {
+ escape_string_json_buf(key, buf);
+ }
buf.push(':');
let prev_len = cur_padding.len();
let item = o.get(key.clone())?.expect("field exists");
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth753 _loc: &ExprLocation,753 _loc: &ExprLocation,754 args: &ArgsDesc,754 args: &ArgsDesc,755) -> Result<Val> {755) -> Result<Val> {756 parse_args!(context, "manifestYamlDoc", args, 2, [756 parse_args!(context, "manifestYamlDoc", args, 3, [757 0, value: ty!(any);757 0, value: ty!(any);758 1, indent_array_in_object: ty!(boolean) => Val::Bool;758 1, indent_array_in_object: ty!(boolean) => Val::Bool;759 2, quote_keys: ty!(boolean) => Val::Bool;759 ], {760 ], {760 Ok(Val::Str(manifest_yaml_ex(&value, &ManifestYamlOptions {761 Ok(Val::Str(manifest_yaml_ex(&value, &ManifestYamlOptions {761 padding: " ",762 padding: " ",762 arr_element_padding: if indent_array_in_object { " " } else { "" },763 arr_element_padding: if indent_array_in_object { " " } else { "" },764 quote_keys,763 })?.into()))765 })?.into()))764 })766 })765}767}crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -556,6 +556,7 @@
&ManifestYamlOptions {
padding,
arr_element_padding: padding,
+ quote_keys: false,
},
)
.map(|s| s.into())
crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -377,7 +377,7 @@
manifestYamlDocImpl:: $intrinsic(manifestYamlDocImpl),
- manifestYamlDoc(value, indent_array_in_object=false):: std.manifestYamlDocImpl(value, indent_array_in_object),
+ manifestYamlDoc(value, indent_array_in_object=false, quote_keys=true):: std.manifestYamlDocImpl(value, indent_array_in_object, quote_keys),
manifestYamlStream(value, indent_array_in_object=false, c_document_end=true)::
if !std.isArray(value) then