112 lines
3.1 KiB
Rust
112 lines
3.1 KiB
Rust
// JSON 参照独立实现 Serde 的 Decimal 字符串合同,复用同一个 serde_json 解析器。
|
|
impl serde::Serialize for NativeDisplay {
|
|
fn serialize<Encoder: serde::Serializer>(
|
|
&self,
|
|
encoder: Encoder,
|
|
) -> Result<Encoder::Ok, Encoder::Error> {
|
|
encoder.collect_str(self)
|
|
}
|
|
}
|
|
|
|
impl<'input> serde::Deserialize<'input> for NativeDisplay {
|
|
fn deserialize<Decoder: serde::Deserializer<'input>>(
|
|
decoder: Decoder,
|
|
) -> Result<Self, Decoder::Error> {
|
|
struct Visitor;
|
|
impl<'input> serde::de::Visitor<'input> for Visitor {
|
|
type Value = NativeDisplay;
|
|
fn expecting(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
output.write_str("an exact Decimal string")
|
|
}
|
|
fn visit_str<Error: serde::de::Error>(self, text: &str) -> Result<Self::Value, Error> {
|
|
native_parse(text)
|
|
.map(NativeDisplay)
|
|
.ok_or_else(|| Error::custom("invalid Decimal"))
|
|
}
|
|
}
|
|
decoder.deserialize_str(Visitor)
|
|
}
|
|
}
|
|
|
|
fn json_encoded<const NATIVE: bool>(values: &[DecimalInput]) -> Result<Vec<String>, Fault> {
|
|
Ok(values
|
|
.iter()
|
|
.map(|input| {
|
|
if NATIVE {
|
|
serde_json::to_string(&NativeDisplay(input.native)).unwrap()
|
|
} else {
|
|
serde_json::to_string(&input.value).unwrap()
|
|
}
|
|
})
|
|
.collect())
|
|
}
|
|
|
|
fn json_decoded<const NATIVE: bool>(values: &[String]) -> Result<Vec<Option<[u8; 16]>>, Fault> {
|
|
Ok(values
|
|
.iter()
|
|
.map(|text| {
|
|
if NATIVE {
|
|
serde_json::from_str::<NativeDisplay>(text)
|
|
.ok()
|
|
.map(|value| value.0.to_be_bytes())
|
|
} else {
|
|
serde_json::from_str::<Decimal>(text)
|
|
.ok()
|
|
.map(Decimal::to_be_bytes)
|
|
}
|
|
})
|
|
.collect())
|
|
}
|
|
|
|
fn wire_cases(inputs: &[DecimalInput]) {
|
|
let texts = inputs
|
|
.iter()
|
|
.map(|input| serde_json::to_string(&input.text).unwrap())
|
|
.collect::<Vec<_>>();
|
|
compare(
|
|
"decimal_json_encode",
|
|
inputs,
|
|
1000,
|
|
json_encoded::<false>,
|
|
json_encoded::<true>,
|
|
|value| text_score(value),
|
|
);
|
|
compare(
|
|
"decimal_json_decode",
|
|
&texts,
|
|
1000,
|
|
json_decoded::<false>,
|
|
json_decoded::<true>,
|
|
|value| byte_score(value),
|
|
);
|
|
let invalid = [
|
|
"1.25",
|
|
"null",
|
|
"[]",
|
|
"\"NaN\"",
|
|
"\"1e9999\"",
|
|
"\" 1\"",
|
|
"\"1\\u0000\"",
|
|
"\"1\" true",
|
|
]
|
|
.iter()
|
|
.cycle()
|
|
.take(112)
|
|
.map(|value| (*value).to_owned())
|
|
.collect::<Vec<_>>();
|
|
assert!(
|
|
json_decoded::<false>(&invalid)
|
|
.unwrap()
|
|
.iter()
|
|
.all(Option::is_none)
|
|
);
|
|
compare(
|
|
"decimal_json_invalid",
|
|
&invalid,
|
|
1000,
|
|
json_decoded::<false>,
|
|
json_decoded::<true>,
|
|
|value| byte_score(value),
|
|
);
|
|
}
|