Files
core/test/rust/performance/json/property.rs
T
2026-11-03 03:32:07 +00:00

131 lines
4.0 KiB
Rust

// 两侧都接收已验证的 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<Decoder: Deserializer<'input>>(
self,
decoder: Decoder,
) -> Result<bool, Decoder::Error> {
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<Failure: dever_runtime::wire::serde::de::Error>(
self,
value: &str,
) -> Result<bool, Failure> {
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<Access: MapAccess<'input>>(
self,
mut fields: Access,
) -> Result<Self::Value, Access::Error> {
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::<IgnoredAny>()?;
}
}
Ok(result)
}
}
fn runtime_property(values: &[PropertyCase]) -> Result<Option<String>, 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<Option<String>, 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::<Vec<_>>();
let fields = names
.iter()
.map(|name| {
format!(
"{}: [ 1e9999, -0, \"\\u96ea\" ]",
serde_json::to_string(name).unwrap()
)
})
.collect::<Vec<_>>();
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",
);
}
}
}