// 两侧共享相同的 wire 库和预算,隔离 Dever 生成代码开销,不代替独立 JSON 引擎对比。 use dever_runtime::wire::{json::Json, serde::{Serialize, Serializer, ser::SerializeStruct}}; fn json_fault(_: impl std::fmt::Display) -> Fault { &FaultInfo { message: "JSON failure", source: "json-reference", line: 1, column: 1 } } struct Payload<'value> { values: &'value [i64] } impl Serialize for Payload<'_> { fn serialize(&self, encoder: Encoder) -> Result { let mut record = encoder.serialize_struct("Payload", 1)?; record.serialize_field("values", self.values)?; record.end() } } fn generated_encode(values: &[i64]) -> Result { GENERATED_ENCODE(values).map_err(json_fault) } fn reference_encode(values: &[i64]) -> Result { Json::encode(&Payload { values }).map(|value| value.as_str().to_owned()).map_err(json_fault) } // 独立 serde 输出不执行 Dever 的三个预算,只作为额外编码成本的下界。 fn reference_serde_encode(values: &[i64]) -> Result { dever_runtime::wire::serde_json::to_string(&Payload { values }).map_err(json_fault) } // 独立 Rust 的同合同实现:两层容器,根和数组占两个值,i64 最长 20 字节。 // 值数合格时,含分隔符的最大输出不足 16 MiB,无须逐片段再次检查。 fn reference_bounded_encode(values: &[i64]) -> Result { if values.len() > dever_runtime::wire::document::MAX_VALUES - 2 { return Err(json_fault("JSON value budget")); } reference_serde_encode(values) } fn generated_lookup(values: &[String]) -> Result { values.first().map_or(Ok(-1), |value| GENERATED_LOOKUP(value).map_err(json_fault)) } fn reference_lookup(values: &[String]) -> Result { let Some(source) = values.first() else { return Ok(-1); }; let json = Json::parse(source).map_err(json_fault)?; json.property("count").map_err(json_fault)?.map_or(Ok(-1), |value| value.as_integer().map_err(json_fault)) } fn generated_update(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |value| GENERATED_UPDATE(value).map_err(json_fault)) } fn reference_update(values: &[String]) -> Result { let Some(source) = values.first() else { return Ok(String::new()); }; let value = Json::parse(source).map_err(json_fault)?; let child = Json::integer(43).map_err(json_fault)?; value.set_property("count", &child).map(|value| value.as_str().to_owned()).map_err(json_fault) } fn generated_scalar_text(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |value| GENERATED_SCALAR_TEXT(value).map_err(json_fault)) } fn reference_scalar_text(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |value| Json::string(value).map(|value| value.as_str().to_owned()).map_err(json_fault)) } fn generated_scalar_float(values: &[f64]) -> Result { values.first().map_or(Ok(String::new()), |value| GENERATED_SCALAR_FLOAT(*value).map_err(json_fault)) } fn reference_scalar_float(values: &[f64]) -> Result { values.first().map_or(Ok(String::new()), |value| Json::float(*value).map(|value| value.as_str().to_owned()).map_err(json_fault)) } #[derive(Serialize)] #[serde(crate = "dever_runtime::wire::serde")] struct Fixed<'value> { text: &'value str, amount: i64, ratio: f64, } fn reference_fixed_value(text: &str, ratio: f64) -> Result { if !ratio.is_finite() { return Err(json_fault("non-finite Float")); } Json::encode(&Fixed { text, amount: 7, ratio }) .map(Json::into_text).map_err(json_fault) } fn generated_fixed(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |value| GENERATED_FIXED_RECORD(value, 4.25).map_err(json_fault)) } fn reference_fixed(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |value| reference_fixed_value(value, 4.25)) } fn main() { println!("workload,sample,implementation,nanos,checksum"); for count in [0, 8, 256] { let input = [Json::parse(&serde_json::to_string(&vec!["雪山 "; count]).unwrap()).unwrap()]; compare(&format!("json_typed_decode_{count}"), &input, 2000, generated_decode, reference_decode, |values| values.iter().map(|value| value.len() as u64).sum()); compare(&format!("json_captured_decode_{count}"), &input, 2000, generated_captured_decode, reference_captured_decode, |value| *value as u64); } let invalid = [Json::parse("[1]").unwrap()]; compare("json_captured_decode_invalid", &invalid, 2000, generated_captured_decode, reference_captured_decode, |value| *value as u64); for state in ["Ready", "Busy"] { let input = [Json::parse(&format!("\"{state}\"")).unwrap()]; compare(&format!("json_enum_decode_{state}"), &input, 100_000, generated_enum_decode, reference_enum_decode, |value| u64::from(*value)); } property_costs(); raw_output_costs(); let values = (0..256).collect::>(); compare("json_record", &values, 2000, generated_encode, reference_encode, |value| value.len() as u64); for count in [16, 256, 4096] { let input = (0..count).collect::>(); compare_named(&format!("json_record_serde_{count}"), &input, 2000, generated_encode, reference_serde_encode, |value| value.len() as u64, "rust_serde"); compare_named(&format!("json_record_bounded_{count}"), &input, 2000, generated_encode, reference_bounded_encode, |value| value.len() as u64, "rust_bounded"); } let maximum = vec![0; dever_runtime::wire::document::MAX_VALUES - 2]; assert_eq!(generated_encode(&maximum).unwrap(), reference_bounded_encode(&maximum).unwrap()); let excessive = vec![0; dever_runtime::wire::document::MAX_VALUES - 1]; assert!(generated_encode(&excessive).is_err()); assert!(reference_bounded_encode(&excessive).is_err()); let source = format!(r#"{{"count":42,"ratio":1e9999,"text":"雪","values":{values:?}}}"#); compare("json_lookup", std::slice::from_ref(&source), 2000, generated_lookup, reference_lookup, |value| *value as u64); compare("json_update", &[source], 2000, generated_update, reference_update, |value| value.len() as u64); compare("json_scalar_text", &["雪\"\\".repeat(512)], 2000, generated_scalar_text, reference_scalar_text, |value| value.len() as u64); compare("json_scalar_float", &[12345.6789], 2000, generated_scalar_float, reference_scalar_float, |value| value.len() as u64); for bytes in [64, 4096, 65536] { let input = ["a".repeat(bytes)]; assert_eq!(generated_fixed(&input).unwrap(), reference_fixed(&input).unwrap()); compare(&format!("json_fixed_record_{bytes}"), &input, 2000, generated_fixed, reference_fixed, |value| value.len() as u64); } for ratio in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { assert!(GENERATED_FIXED_RECORD("", ratio).is_err()); assert!(reference_fixed_value("", ratio).is_err()); } let overhead = reference_fixed_value("", 4.25).unwrap().len(); let maximum = "a".repeat(dever_runtime::wire::document::MAX_BYTES - overhead); assert_eq!(GENERATED_FIXED_RECORD(&maximum, 4.25).unwrap().len(), dever_runtime::wire::document::MAX_BYTES); assert!(GENERATED_FIXED_RECORD(&(maximum + "a"), 4.25).is_err()); } fn generated_decode(values: &[Json]) -> Result, Fault> { values.first().map_or(Ok(Vec::new()), |value| GENERATED_DECODE(value).map_err(json_fault)) } fn reference_decode(values: &[Json]) -> Result, Fault> { // Dever 保留解码失败文本;两侧构造错误后再统一映射为基准 Fault。 values.first().map_or(Ok(Vec::new()), |value| serde_json::from_str(value.as_str()).map_err(|error| json_fault(error.to_string()))) } fn generated_captured_decode(values: &[Json]) -> Result { values.first().map_or(Ok(0), |value| GENERATED_CAPTURED_DECODE(value).map_err(json_fault)) } fn reference_captured_decode(values: &[Json]) -> Result { values.first().map_or(Ok(0), |value| { Ok(match serde_json::from_str::>(value.as_str()) { Ok(values) => values.len() as i64, Err(error) => { let _message = error.to_string(); -1 } }) }) } #[derive(dever_runtime::wire::serde::Deserialize)] #[serde(crate = "dever_runtime::wire::serde")] enum WireState { Ready, Busy } fn generated_enum_decode(values: &[Json]) -> Result { values.first().map_or(Ok(false), |value| GENERATED_ENUM_DECODE(value).map_err(json_fault)) } fn reference_enum_decode(values: &[Json]) -> Result { values.first().map_or(Ok(false), |value| { serde_json::from_str::(value.as_str()) .map(|state| matches!(state, WireState::Ready)) .map_err(|error| json_fault(error.to_string())) }) }