git.delta.rocks / jrsonnet / refs/commits / 52a24f69aae7

difftreelog

fix(nixlike) string roundtrips

Yaroslav Bolyukin2021-10-01parent: #a9e03a3.patch.diff
in: trunk

6 files changed

addedcrates/nixlike/fuzz/.gitignorediffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/.gitignore
@@ -0,0 +1,4 @@
+
+target
+corpus
+artifacts
addedcrates/nixlike/fuzz/Cargo.lockdiffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/Cargo.lock
@@ -0,0 +1,182 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "arbitrary"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "577b08a4acd7b99869f863c50011b01eb73424ccc798ecd996f2e24817adfca7"
+
+[[package]]
+name = "bumpalo"
+version = "3.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
+
+[[package]]
+name = "cc"
+version = "1.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
+
+[[package]]
+name = "dprint-core"
+version = "0.46.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df98b7d98583d9d57311b9df81f571f35a6ca3e8675d0128333b2e923dc85bcd"
+dependencies = [
+ "bumpalo",
+ "rustc-hash",
+ "serde",
+]
+
+[[package]]
+name = "libfuzzer-sys"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36a9a84a6e8b55dfefb04235e55edb2b9a2a18488fcae777a6bdaa6f06f1deb3"
+dependencies = [
+ "arbitrary",
+ "cc",
+ "once_cell",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+
+[[package]]
+name = "nixlike"
+version = "0.1.0"
+dependencies = [
+ "dprint-core",
+ "linked-hash-map",
+ "peg",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "nixlike-fuzz"
+version = "0.0.0"
+dependencies = [
+ "libfuzzer-sys",
+ "nixlike",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
+
+[[package]]
+name = "peg"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a"
+dependencies = [
+ "peg-macros",
+ "peg-runtime",
+]
+
+[[package]]
+name = "peg-macros"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c"
+dependencies = [
+ "peg-runtime",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "peg-runtime"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "serde"
+version = "1.0.130"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.130"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
addedcrates/nixlike/fuzz/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/Cargo.toml
@@ -0,0 +1,26 @@
+
+[package]
+name = "nixlike-fuzz"
+version = "0.0.0"
+authors = ["Automatically generated"]
+publish = false
+edition = "2018"
+
+[package.metadata]
+cargo-fuzz = true
+
+[dependencies]
+libfuzzer-sys = "0.4"
+
+[dependencies.nixlike]
+path = ".."
+
+# Prevent this from interfering with workspaces
+[workspace]
+members = ["."]
+
+[[bin]]
+name = "fuzz_target_1"
+path = "fuzz_targets/fuzz_target_1.rs"
+test = false
+doc = false
addedcrates/nixlike/fuzz/fuzz_targets/fuzz_target_1.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/fuzz_targets/fuzz_target_1.rs
@@ -0,0 +1,9 @@
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+
+fuzz_target!(|data: String| {
+    let serialized = nixlike::serialize(data.clone()).unwrap();
+    let deserialized: String = nixlike::parse_str(&serialized).unwrap();
+    
+    assert_eq!(data, deserialized);
+});
modifiedcrates/nixlike/src/lib.rsdiffbeforeafterboth
before · crates/nixlike/src/lib.rs
1use linked_hash_map::LinkedHashMap;2use peg::str::LineCol;3use se_impl::MySerialize;4use serde::{Deserialize, Serialize};56mod de_impl;7mod se_impl;8mod to_string;910#[derive(thiserror::Error, Debug)]11pub enum Error {12	#[error("bad number")]13	BadNumber,14	#[error("expected {0}")]15	Expected(&'static str),16	#[error("parse error")]17	ParseError(#[from] peg::error::ParseError<LineCol>),18	#[error("{0}")]19	Custom(String),20	#[error("io: {0}")]21	Io(#[from] std::io::Error),22	#[error("fmt: {0}")]23	Fmt(#[from] std::fmt::Error),24}2526#[derive(Debug)]27pub enum Value {28	Number(i64),29	String(String),30	Boolean(bool),31	Object(LinkedHashMap<String, Value>),32	Array(Vec<Value>),33	Null,34}3536peg::parser! {37pub grammar nixlike() for str {38	rule number() -> i6439		= quiet! { v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")} } / expected!("<number>")40	rule string_char() -> &'input str41		= "\\\"" { "\"" }42		/ "\\\\" { "\\" }43		/ c:$([_]) { c }44	rule string() -> String45		= quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")46	rule boolean() -> bool47		= quiet! { "true" {true}48		/ "false" {false} } / expected!("<boolean>")49	rule indent() -> String50		= quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")51	rule object() -> LinkedHashMap<String, Value>52		= "{" _53			e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*54		"}" {?55			let mut out = LinkedHashMap::new();56			for (k, v) in e {57				let mut map = &mut out;58				for v in k.iter().take(k.len() - 1) {59					map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {60						Value::Object(v) => v,61						_ => return Err("expected object"),62					}63				}6465				let key = k.into_iter().last().unwrap();66				if map.contains_key(&key) {67					return Err("can't override object");68				}69				map.insert(key, v);70			}71			Ok(out)72		}7374	rule array() -> Vec<Value>75		= "[" _ v:value()**_ _ "]" {v}7677	rule value() -> Value78		= o:object() { Value::Object(o) }79		/ a:array() { Value::Array(a) }80		/ s:string() { Value::String(s) }81		/ "null" { Value::Null }82		/ b:boolean() { Value::Boolean(b) }83		/ n:number() { Value::Number(n) }8485	pub rule root() -> Value86		= _ v:value() _ { v }8788	rule _()89		= ( quiet!{ [' ' | '\t' | '\n']+ }90		/ "#" (!['\n'] [_])* "\n" )*91}92}9394pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {95	let value = nixlike::root(s)?;96	D::deserialize(value)97}9899pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {100	D::deserialize(value)101}102103pub fn serialize_value_pretty(value: Value) -> String {104	to_string::write_nix(&value)105}106107pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {108	let value: Value = value.serialize(MySerialize)?;109	Ok(serialize_value_pretty(value))110}111112#[test]113fn test() {114	let v: serde_json::Value = parse_str(115		r#"116			{117				b.c = 2;118				b.d = "hello";119				c = {120					k = 123;121					p = 231;122					ll = [1 2 3 [] [[4 5 6]] ];123				};124			}125		"#,126	)127	.unwrap();128	let s: String = serialize(v).unwrap();129	println!("{}", s);130}
modifiedcrates/nixlike/src/to_string.rsdiffbeforeafterboth
--- a/crates/nixlike/src/to_string.rs
+++ b/crates/nixlike/src/to_string.rs
@@ -5,7 +5,13 @@
 };
 
 fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut PrintItems) {
-	out.push_str(k);
+	if k.contains(".") {
+		out.push_str("\"");
+		out.push_str(k);
+		out.push_str("\"");
+	} else {
+		out.push_str(k);
+	}
 	match v {
 		Value::Object(o) if o.len() == 1 => {
 			let (k, v) = o.iter().next().unwrap();
@@ -26,7 +32,15 @@
 		Value::Null => out.push_str("null"),
 		Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),
 		Value::Number(n) => out.push_str(&format!("{}", n)),
-		Value::String(s) => out.push_str(&format!("{:?}", s)),
+		Value::String(s) => out.push_str(&format!(
+			"\"{}\"",
+			s.replace('\\', "\\\\")
+				.replace('"', "\\\"")
+				.replace('\n', "\\n")
+				.replace('\t', "\\t")
+				.replace('\r', "\\r")
+				.replace("$", "''$")
+		)),
 		Value::Array(a) => {
 			if a.is_empty() {
 				out.push_str("[ ]");