use dever_runtime::wire::{self, document}; #[test] #[ignore = "explicit strict-Unicode versus syntax-only performance diagnostic"] fn escaped_string_validation_cost() { use serde::{Deserializer, de::IgnoredAny}; use std::{hint::black_box, time::Instant}; let source = serde_json::to_string(&"雪\"\\\n".repeat(1024)).unwrap(); println!("case,sample,implementation,iterations,nanoseconds,checksum"); for sample in 0..15 { for strict in if sample % 2 == 0 { [true, false] } else { [false, true] } { let started = Instant::now(); for _ in 0..1000 { let source = black_box(source.as_str()); if strict { let mut decoder = serde_json::Deserializer::from_str(source); decoder.deserialize_str(IgnoredAny).unwrap(); decoder.end().unwrap(); } else { black_box( serde_json::from_str::<&serde_json::value::RawValue>(source).unwrap(), ); } } let elapsed = started.elapsed().as_nanos(); let label = if strict { "rust_unicode" } else { "rust_syntax_only" }; println!( "escaped_string,{sample},{label},1000,{elapsed},{}", source.len() * 1000 ); } } } #[test] fn from_text_preserves_unicode_validation_and_original_spelling() { use wire::json::Json; for unit in 0..=u16::MAX { let source = format!("\"\\u{unit:04x}\""); assert_eq!( Json::parse(&source).is_ok(), serde_json::from_str::(&source).is_ok(), "{source}" ); } for text in [ "", "雪🙂", "\\u1234", "\\\"\\\\", "\\\\\"\\\"", "\"\"雪\"", "\u{0}\n\t", ] { let source = serde_json::to_string(text).unwrap(); for source in [source.clone(), format!(" \n{source}\t ")] { let parsed = Json::parse(&source).unwrap(); assert_eq!(parsed.as_str(), source); assert_eq!(parsed.as_text().unwrap(), text); assert_eq!( Json::array(&[parsed]).unwrap().into_text(), format!("[{}]", source.trim()) ); } } for source in [ r#"{"雪":0,"\u96ea":1}"#, r#"["\ud800"]"#, r#"{"field":"\udc00"}"#, r#"{"\ud800":0}"#, r#""\ud800\u0061""#, ] { assert!(Json::parse(source).is_err(), "{source}"); } for source in [ r#""\ud83d\ude42""#, r#"{"value":[true,false,null,-0,1e9999]}"#, ] { assert_eq!(Json::parse(source).unwrap().as_str(), source); } } #[test] fn shaped_input_keeps_array_syntax_and_limits() { for count in [0, 16, document::MAX_VALUES - 1] { let source = format!("[{}]", vec!["0"; count].join(",")); assert_eq!( wire::decode_shaped::>(&source), wire::decode(&source) ); assert_eq!( wire::decode_shaped::>(&source).unwrap().len(), count ); } for source in [ "[1,]", "[null]", "[true]", "[{}]", "[[1]]", "[1.5]", "[1] null", "[9223372036854775808]", "[1e9999]", ] { assert!(wire::decode_shaped::>(source).is_err(), "{source}"); } let source = format!("[{}]", vec!["0"; document::MAX_VALUES].join(",")); assert!( wire::decode_shaped::>(&source) .unwrap_err() .contains("value") ); } #[test] fn shaped_input_has_identical_acceptance_across_the_proven_byte_budget() { for size in [ document::MAX_VALUES - 1, document::MAX_VALUES, document::MAX_VALUES + 1, ] { let source = format!("[\"{}\"]", "x".repeat(size - 4)); assert_eq!(source.len(), size); assert_eq!( wire::decode_shaped::>(&source), wire::decode(&source) ); let source = format!("[\"{}\\ud800\"]", "x".repeat(size - 10)); assert!(wire::decode_shaped::>(&source).is_err()); } let source = format!("[\"{}\"]", "x".repeat(document::MAX_BYTES - 4)); assert!(wire::decode_shaped::>(&source).is_ok()); assert!(wire::decode_shaped::>(&(source + " ")).is_err()); } #[test] fn single_pass_budget_counts_nested_containers_and_optional_values_once() { use serde::Deserialize; #[derive(Debug, Deserialize, PartialEq)] #[serde(deny_unknown_fields)] struct Fields { first: Vec>, second: Option>>, } for extra in [0, 1] { let source = format!( "{{\"first\":[{}],\"second\":[null]}}", vec!["null"; document::MAX_VALUES - 4 + extra].join(",") ); assert_eq!(wire::decode::(&source).is_ok(), extra == 0); assert_eq!(wire::decode_shaped::(&source).is_ok(), extra == 0); } let padding = " ".repeat(document::MAX_VALUES); for source in [ r#"{"first":[],"second":null}"#, r#"{"first":[null,1],"second":[2,null]}"#, r#"{"first":[],"second":null,"second":[]}"#, r#"{"first":[],"fi\u0072st":[]}"#, r#"{"first":[],"unknown":{}}"#, ] { let source = format!("{padding}{source}"); let normal = wire::decode::(&source); let shaped = wire::decode_shaped::(&source); assert_eq!(normal.is_ok(), shaped.is_ok()); assert_eq!(normal.ok(), shaped.ok()); } } #[test] fn single_pass_budget_preserves_serde_numeric_decoding() { let padding = " ".repeat(document::MAX_VALUES); for source in [ "[0,-0,-0.0,1,9223372036854775807,18446744073709551615]", "[0.1,1.2345678901234567,1e-308,5e-324,1.7976931348623157e308]", ] { let source = format!("{padding}{source}"); let normal = wire::decode::>(&source).unwrap(); let shaped = wire::decode_shaped::>(&source).unwrap(); assert_eq!( normal .iter() .map(|value| value.to_bits()) .collect::>(), shaped .iter() .map(|value| value.to_bits()) .collect::>() ); } for source in ["[1e9999]", "[null]", "[\"1\"]", "[NaN]"] { assert!(wire::decode_shaped::>(&format!("{padding}{source}")).is_err()); } let source = format!("{padding}[\"1.2300\",null,\"-1E-6176\"]"); assert_eq!( wire::decode_shaped::>>(&source), wire::decode(&source) ); } #[derive(Debug, serde::Deserialize, PartialEq)] #[serde(deny_unknown_fields)] struct JsonFields { payload: wire::json::Json, note: Option, nested: Option, } #[derive(Debug, serde::Deserialize, PartialEq)] #[serde(deny_unknown_fields)] struct JsonRecord { payload: Option, count: i64, } fn decode_json_fields(source: &str) -> Result { wire::decode_json(source, |value: &JsonFields, budget| { budget.open()?; budget.value(3)?; budget.json(&value.payload)?; if let Some(nested) = &value.nested { budget.open()?; budget.value(2)?; if let Some(payload) = &nested.payload { budget.json(payload)?; } budget.close(); } budget.close(); Ok(()) }) } #[test] fn json_input_budget_distinguishes_omitted_fields_from_explicit_null_at_limit() { for count in [document::MAX_VALUES - 4, document::MAX_VALUES - 2] { let payload = vec!["0"; count].join(","); for suffix in ["", ",\"note\":null", ",\"note\":null,\"nested\":null"] { let source = format!("{{\"payload\":[{payload}]{suffix}}}"); let expected = wire::decode::(&source); let actual = decode_json_fields(&source); assert_eq!(actual.is_ok(), expected.is_ok(), "{count}/{suffix}"); assert_eq!(actual.ok(), expected.ok()); } } let payload = vec!["0"; document::MAX_VALUES - 2].join(","); assert!(decode_json_fields(&format!("{{\"payload\":[{payload}]}}")).is_ok()); assert!(decode_json_fields(&format!("{{\"payload\":[{payload}],\"note\":null}}")).is_err()); } #[test] fn json_input_budget_combines_fixed_records_and_multiple_json_subtrees() { for extra in [0, 1] { let payload = vec!["0"; document::MAX_VALUES - 6 + extra].join(","); let source = format!("{{\"payload\":[{payload}],\"nested\":{{\"payload\":[0],\"count\":0}}}}"); let actual = decode_json_fields(&source); assert_eq!(actual.is_ok(), extra == 0); assert_eq!(actual.ok(), wire::decode::(&source).ok()); } let payload = vec!["0"; document::MAX_VALUES - 4].join(","); for (field, accepted) in [("", true), (",\"payload\":null", false)] { let source = format!("{{\"payload\":[{payload}],\"nested\":{{\"count\":0{field}}}}}"); assert_eq!(decode_json_fields(&source).is_ok(), accepted); assert_eq!(wire::decode::(&source).is_ok(), accepted); } } #[test] fn json_input_budget_counts_empty_containers_and_relative_subtree_depth() { for (nested, parent_depth) in [(false, 1), (true, 2)] { for extra in [0, 1] { let depth = document::MAX_DEPTH - parent_depth + extra; let payload = "[".repeat(depth) + &"]".repeat(depth); let source = if nested { format!("{{\"payload\":null,\"nested\":{{\"payload\":{payload},\"count\":0}}}}") } else { format!("{{\"payload\":{payload}}}") }; assert_eq!(decode_json_fields(&source).is_ok(), extra == 0); assert_eq!(wire::decode::(&source).is_ok(), extra == 0); } } for source in [ r#"{"payload":null,"nested":null}"#, r#"{"payload":{},"nested":{"count":0}}"#, r#"{"payload":[],"nested":{"payload":null,"count":0}}"#, ] { assert_eq!( decode_json_fields(source).unwrap(), wire::decode(source).unwrap() ); } } #[test] fn json_input_keeps_raw_spelling_duplicate_keys_and_strict_unicode() { let payload = r#"{ "value": [1e9999,-0,1.00e+2,"\u96ea","\ud83d\ude42"] }"#; let source = format!("{{\"payload\":{payload}}}"); let decoded = decode_json_fields(&source).unwrap(); assert_eq!(decoded.payload.as_str(), payload); assert_eq!( wire::json::Json::array(&[decoded.payload]) .unwrap() .as_str(), format!("[{payload}]") ); for source in [ r#"{"payload":null,"payl\u006fad":0}"#, r#"{"payload":null,"note":null,"note":null}"#, r#"{"payload":{"雪":0,"\u96ea":1}}"#, r#"{"payload":"\ud800"}"#, r#"{"payload":null,"note":"\udc00"}"#, r#"{"payload":null,"nested":{"count":0,"count":1}}"#, r#"{"payload":null,"extra":0}"#, r#"{"payload":null} {}"#, r#"{"payload":null,}"#, ] { assert!(decode_json_fields(source).is_err(), "{source}"); assert!(wire::decode::(source).is_err(), "{source}"); } } #[test] fn json_input_limits_original_bytes_before_deserializing() { let prefix = r#"{"payload":null,"note":""#; let source = format!( "{prefix}雪{}\"}}", " ".repeat(document::MAX_BYTES - prefix.len() - 5) ); assert_eq!(source.len(), document::MAX_BYTES); assert!(decode_json_fields(&source).is_ok()); let oversized = source + " "; let mut checked = false; let result = wire::decode_json::(&oversized, |_, _| { checked = true; Ok(()) }); assert!(result.unwrap_err().contains("16 MiB")); assert!(!checked); }