131 lines
4.0 KiB
Rust
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",
|
|
);
|
|
}
|
|
}
|
|
}
|