use dever_runtime::wire::document; fn document_fault(_: impl std::fmt::Display) -> Fault { &FaultInfo { message: "JSON failure", source: "document-reference", line: 1, column: 1 } } fn generated_document(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |source| GENERATED_DOCUMENT(source).map_err(document_fault)) } fn reference_document(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |source| { let value = document::parse_with_depth(source, document::DOCUMENT_MAX_DEPTH).map_err(document_fault)?; document::stringify_with_depth(&value, document::DOCUMENT_MAX_DEPTH).map_err(document_fault) }) } // 独立手写 Map 适配,解析/写出引擎仍共用;只衡量表示转换与生成层。 type ReferenceNode = reference_writer::Node, Map>; fn reference_map_document(values: &[String]) -> Result { let Some(source) = values.first() else { return Ok(String::new()); }; let parsed = document::parse_with_depth(source, document::DOCUMENT_MAX_DEPTH).map_err(document_fault)?; let mut nodes = indexmap::IndexMap::with_capacity(parsed.nodes.len()); for (index, value) in parsed.nodes.into_iter().enumerate() { let value = match value { document::Value::Null => ReferenceNode::Null, document::Value::Boolean(value) => ReferenceNode::Boolean(value), document::Value::Number(value) => ReferenceNode::Number(value), document::Value::String(value) => ReferenceNode::String(value), document::Value::Array(values) => ReferenceNode::Array(values), document::Value::Object(values) => ReferenceNode::Object(values.map_or_else(|| Map::with_capacity(0), |values| *values)), }; nodes.insert(index as i64, value); } reference_map_write(parsed.root as i64, &nodes) } fn reference_map_write(root: i64, nodes: &indexmap::IndexMap) -> Result { let root = usize::try_from(root).map_err(document_fault)?; if nodes.len() > document::MAX_VALUES { return Err(document_fault("too many nodes")); } let mut ordered = vec![None; nodes.len()]; for (id, value) in nodes { if let Ok(index) = usize::try_from(*id) && let Some(slot) = ordered.get_mut(index) { *slot = Some(value); } } let ordered = ordered.into_iter().map(|value| value.ok_or_else(|| document_fault("missing node"))).collect::, _>>()?; reference_writer::stringify_nodes(root, ordered.len(), |index| { match ordered[index] { ReferenceNode::Null => reference_writer::Node::Null, ReferenceNode::Boolean(value) => reference_writer::Node::Boolean(*value), ReferenceNode::Number(value) => reference_writer::Node::Number(value.as_str()), ReferenceNode::String(value) => reference_writer::Node::String(value.as_str()), ReferenceNode::Array(values) => reference_writer::Node::Array(values.iter().copied()), ReferenceNode::Object(values) => reference_writer::Node::Object(values.iter().map(|(name, id)| (name.as_str(), *id))), } }, document::DOCUMENT_MAX_DEPTH).map_err(document_fault) } #[derive(Debug)] enum ReferenceFailure { Fault(Fault), Parse(i64, String, Fault), Write(i64, String, Fault), } impl std::fmt::Display for ReferenceFailure { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Fault(fault) | Self::Parse(_, _, fault) | Self::Write(_, _, fault) => fault.fmt(formatter), } } } fn reference_map_faults(values: &[String]) -> Result { values.first().map_or(Ok(String::new()), |source| reference_map_contract(source).map_err(document_fault)) } // 原参照继续保留;这里独立保留解析/输出错误的载荷与静态源位置。 fn reference_map_contract(source: &str) -> Result { let parse_fault = &FaultInfo { message: "ParseResult.Failed", source: "document-reference", line: 1, column: 1 }; let write_fault = &FaultInfo { message: "StringifyResult.Failed", source: "document-reference", line: 2, column: 1 }; let fail = |node, message: &str| ReferenceFailure::Write(node, message.into(), write_fault); let parsed = document::parse_with_depth(source, document::DOCUMENT_MAX_DEPTH) .map_err(|error| ReferenceFailure::Parse(error.position as i64, error.message, parse_fault))?; let mut nodes = indexmap::IndexMap::with_capacity(parsed.nodes.len()); for (index, value) in parsed.nodes.into_iter().enumerate() { let value = match value { document::Value::Null => ReferenceNode::Null, document::Value::Boolean(value) => ReferenceNode::Boolean(value), document::Value::Number(value) => ReferenceNode::Number(value), document::Value::String(value) => ReferenceNode::String(value), document::Value::Array(values) => ReferenceNode::Array(values), document::Value::Object(values) => ReferenceNode::Object(values.map_or_else(|| Map::with_capacity(0), |values| *values)), }; nodes.insert(index as i64, value); } let root = parsed.root as i64; let root_index = usize::try_from(root).map_err(|_| fail(root, "negative JSON root"))?; if nodes.len() > document::MAX_VALUES { return Err(fail(root, "JSON node count exceeds 65536 values")); } let mut ordered = vec![None; nodes.len()]; for (id, value) in &nodes { if let Ok(index) = usize::try_from(*id) && let Some(slot) = ordered.get_mut(index) { *slot = Some(value); } } let ordered = ordered.into_iter().enumerate().map(|(index, value)| value.ok_or_else(|| fail(index as i64, "JSON node IDs must be consecutive"))).collect::, _>>()?; reference_writer::stringify_nodes(root_index, ordered.len(), |index| { match ordered[index] { ReferenceNode::Null => reference_writer::Node::Null, ReferenceNode::Boolean(value) => reference_writer::Node::Boolean(*value), ReferenceNode::Number(value) => reference_writer::Node::Number(value.as_str()), ReferenceNode::String(value) => reference_writer::Node::String(value.as_str()), ReferenceNode::Array(values) => reference_writer::Node::Array(values.iter().copied()), ReferenceNode::Object(values) => reference_writer::Node::Object(values.iter().map(|(name, id)| (name.as_str(), *id))), } }, document::DOCUMENT_MAX_DEPTH).map_err(|error| ReferenceFailure::Write(error.node as i64, error.message, write_fault)) } fn main() { println!("case,sample,implementation,elapsed_ns,checksum"); let text = "雪\\\"\n".repeat(256); let strings = dever_runtime::wire::json::Json::encode(&vec![text; 32]).unwrap().as_str().to_owned(); let numbers = format!("[{}]", vec!["1234567890123456789012345678901234e-12"; 256].join(",")); let mut nested = "1e9999".to_owned(); for _ in 0..48 { nested = format!("{{\"value\":{nested}}}"); } let empty_objects = format!("[{}]", vec!["{}"; 128].join(",")); let wide = format!("{{{}}}", (0..256).map(|index| format!("\"key{index}\":1e9999")).collect::>().join(",")); for (name, source) in [("document_text", strings), ("document_numbers", numbers), ("document_nested", nested), ("document_empty", "{}".into()), ("document_empty_objects", empty_objects), ("document_wide", wide)] { compare(name, std::slice::from_ref(&source), 100, generated_document, reference_document, |value| value.bytes().map(u64::from).sum()); compare(&format!("{name}_map"), std::slice::from_ref(&source), 100, generated_document, reference_map_document, |value| value.bytes().map(u64::from).sum()); compare(&format!("{name}_map_faults"), &[source], 100, generated_document, reference_map_faults, |value| value.bytes().map(u64::from).sum()); } }