git.delta.rocks / jrsonnet / refs/commits / b118a83916a3

difftreelog

feat quote_keys option for Yaml

Yaroslav Bolyukin2021-11-27parent: #df9bc99.patch.diff
in: master

5 files changed

modifiedCargo.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"
modifiedcrates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth
173 /// ## <- this173 /// ## <- this
174 /// ```174 /// ```
175 pub arr_element_padding: &'s str,175 pub arr_element_padding: &'s str,
176 /// Should yaml keys appear unescaped, when possible
177 /// ```yaml
178 /// "safe_key": 1
179 /// # vs
180 /// safe_key: 1
181 /// ```
182 pub quote_keys: bool,
176}183}
184
185/// From https://github.com/chyh1990/yaml-rust/blob/da52a68615f2ecdd6b7e4567019f280c433c1521/src/emitter.rs#L289
186/// With added date check
187fn yaml_needs_quotes(string: &str) -> bool {
188 fn need_quotes_spaces(string: &str) -> bool {
189 string.starts_with(' ') || string.ends_with(' ')
190 }
191
192 string == ""
193 || need_quotes_spaces(string)
194 || string.starts_with(|character: char| match character {
195 '&' | '*' | '?' | '|' | '-' | '<' | '>' | '=' | '!' | '%' | '@' => true,
196 _ => false,
197 }) || string.contains(|character: char| match character {
198 ':'
199 | '{'
200 | '}'
201 | '['
202 | ']'
203 | ','
204 | '#'
205 | '`'
206 | '\"'
207 | '\''
208 | '\\'
209 | '\0'..='\x06'
210 | '\t'
211 | '\n'
212 | '\r'
213 | '\x0e'..='\x1a'
214 | '\x1c'..='\x1f' => true,
215 _ => false,
216 }) || [
217 // http://yaml.org/type/bool.html
218 // Note: 'y', 'Y', 'n', 'N', is not quoted deliberately, as in libyaml. PyYAML also parse
219 // them as string, not booleans, although it is violating the YAML 1.1 specification.
220 // See https://github.com/dtolnay/serde-yaml/pull/83#discussion_r152628088.
221 "yes", "Yes", "YES", "no", "No", "NO", "True", "TRUE", "true", "False", "FALSE", "false",
222 "on", "On", "ON", "off", "Off", "OFF", // http://yaml.org/type/null.html
223 "null", "Null", "NULL", "~",
224 ]
225 .contains(&string)
226 || (string.chars().all(|c| matches!(c, '0'..='9' | '-'))
227 && string.chars().filter(|c| *c == '-').count() == 2)
228 || string.starts_with('.')
229 || string.starts_with("0x")
230 || string.parse::<i64>().is_ok()
231 || string.parse::<f64>().is_ok()
232}
177233
178pub fn manifest_yaml_ex(val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {234pub fn manifest_yaml_ex(val: &Val, options: &ManifestYamlOptions<'_>) -> Result<String> {
179 let mut out = String::new();235 let mut out = String::new();
206 buf.push_str(options.padding);262 buf.push_str(options.padding);
207 buf.push_str(line);263 buf.push_str(line);
208 }264 }
209 } else {265 } else if !options.quote_keys && !yaml_needs_quotes(&s) {
266 buf.push_str(&s);
267 } else {
210 escape_string_json_buf(s, buf)268 escape_string_json_buf(s, buf);
211 }269 }
212 }270 }
213 Val::Num(n) => write!(buf, "{}", *n).unwrap(),271 Val::Num(n) => write!(buf, "{}", *n).unwrap(),
253 buf.push('\n');311 buf.push('\n');
254 buf.push_str(cur_padding);312 buf.push_str(cur_padding);
255 }313 }
314 if !options.quote_keys && !yaml_needs_quotes(&key) {
315 buf.push_str(&key);
316 } else {
256 escape_string_json_buf(key, buf);317 escape_string_json_buf(key, buf);
318 }
257 buf.push(':');319 buf.push(':');
258 let prev_len = cur_padding.len();320 let prev_len = cur_padding.len();
259 let item = o.get(key.clone())?.expect("field exists");321 let item = o.get(key.clone())?.expect("field exists");
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -753,13 +753,15 @@
 	_loc: &ExprLocation,
 	args: &ArgsDesc,
 ) -> Result<Val> {
-	parse_args!(context, "manifestYamlDoc", args, 2, [
+	parse_args!(context, "manifestYamlDoc", args, 3, [
 		0, value: ty!(any);
 		1, indent_array_in_object: ty!(boolean) => Val::Bool;
+		2, quote_keys: ty!(boolean) => Val::Bool;
 	], {
 		Ok(Val::Str(manifest_yaml_ex(&value, &ManifestYamlOptions {
 			padding: "  ",
 			arr_element_padding: if indent_array_in_object { "  " } else { "" },
+			quote_keys,
 		})?.into()))
 	})
 }
modifiedcrates/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())
modifiedcrates/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