// 两侧都接收已验证的 JSON,返回独立拥有的原始子树;不在计时内重复验证输入。 // 独立参照只使用 Serde,不调用 Dever 的键比较或字段读取实现。 use dever_runtime::wire::serde::{ Deserializer, de::{DeserializeSeed, IgnoredAny, MapAccess, Visitor}, }; use dever_runtime::wire::serde_json::{self, value::RawValue}; struct PropertyCase { source: Json, name: String, } struct MatchingKey<'name>(&'name str); impl<'input> DeserializeSeed<'input> for MatchingKey<'_> { type Value = bool; fn deserialize>( self, decoder: Decoder, ) -> Result { decoder.deserialize_str(self) } } impl<'input> Visitor<'input> for MatchingKey<'_> { type Value = bool; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.write_str("an object key") } fn visit_str( self, value: &str, ) -> Result { Ok(value == self.0) } } struct MatchingProperty<'name>(&'name str); impl<'input> Visitor<'input> for MatchingProperty<'_> { type Value = Option<&'input RawValue>; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.write_str("an object") } fn visit_map>( self, mut fields: Access, ) -> Result { let mut result = None; while let Some(matches) = fields.next_key_seed(MatchingKey(self.0))? { if matches { result = Some(fields.next_value()?); } else { fields.next_value::()?; } } Ok(result) } } fn runtime_property(values: &[PropertyCase]) -> Result, Fault> { let Some(value) = values.first() else { return Ok(None); }; value .source .property(&value.name) .map(|found| found.map(Json::into_text)) .map_err(json_fault) } fn native_property(values: &[PropertyCase]) -> Result, Fault> { let Some(value) = values.first() else { return Ok(None); }; let mut decoder = dever_runtime::wire::serde_json::Deserializer::from_str(value.source.as_str()); decoder .deserialize_map(MatchingProperty(&value.name)) .map(|found| found.map(|raw| raw.get().to_owned())) .map_err(json_fault) } fn property_costs() { for (kind, suffix) in [("plain", ""), ("escaped", "雪\\\"\n")] { let names = (0..256) .map(|index| format!("key_{index:03}_{suffix}")) .collect::>(); let fields = names .iter() .map(|name| { format!( "{}: [ 1e9999, -0, \"\\u96ea\" ]", serde_json::to_string(name).unwrap() ) }) .collect::>(); let source = format!("{{{}}}", fields.join(",")); for (position, name) in [ ("first", names[0].as_str()), ("middle", names[128].as_str()), ("last", names[255].as_str()), ("missing", "absent"), ] { let values = [PropertyCase { source: Json::parse(&source).unwrap(), name: name.into(), }]; let expected = (position != "missing").then(|| r#"[ 1e9999, -0, "\u96ea" ]"#.to_owned()); assert_eq!(runtime_property(&values).unwrap(), expected); assert_eq!(native_property(&values).unwrap(), expected); compare_named( &format!("json_property_{kind}_{position}"), &values, 1000, runtime_property, native_property, |value| value.as_ref().map_or(0, |text| text.len() as u64), "rust_serde", ); } } }