104 lines
4.2 KiB
Rust
104 lines
4.2 KiB
Rust
// 使用 auth 样例实际生成的 RestCreate0;独立 Rust 直接复用 Serde,合同相同。
|
|
// 测量仅包含请求对象解码,不包括字段业务约束、认证、SQL 或网络。
|
|
use dever_runtime::wire::serde::{self, Deserialize};
|
|
use dever_runtime::wire::serde_json;
|
|
|
|
fn fault(_: impl std::fmt::Display) -> Fault {
|
|
&FaultInfo { message: "REST input failure", source: "rest-reference", line: 1, column: 1 }
|
|
}
|
|
|
|
enum Status { Active, Disabled }
|
|
|
|
impl<'input> Deserialize<'input> for Status {
|
|
fn deserialize<Decoder: serde::Deserializer<'input>>(decoder: Decoder) -> Result<Self, Decoder::Error> {
|
|
struct Choice;
|
|
impl<'input> serde::de::Visitor<'input> for Choice {
|
|
type Value = Status;
|
|
fn expecting(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { output.write_str("a status name") }
|
|
fn visit_str<Error: serde::de::Error>(self, value: &str) -> Result<Status, Error> {
|
|
match value {
|
|
"Active" => Ok(Status::Active),
|
|
"Disabled" => Ok(Status::Disabled),
|
|
_ => Err(Error::custom("unknown status")),
|
|
}
|
|
}
|
|
}
|
|
decoder.deserialize_str(Choice)
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(crate = "dever_runtime::wire::serde", deny_unknown_fields)]
|
|
struct Profile {
|
|
name: String,
|
|
bio: Option<String>,
|
|
#[serde(default = "rank")]
|
|
rank: i64,
|
|
#[serde(default = "tag")]
|
|
tag: Option<String>,
|
|
#[serde(default = "status")]
|
|
status: Status,
|
|
}
|
|
|
|
fn rank() -> i64 { 7 }
|
|
fn tag() -> Option<String> { Some("automatic".into()) }
|
|
fn status() -> Status { Status::Active }
|
|
|
|
fn generated(values: &[String]) -> Result<String, Fault> {
|
|
let Some(source) = values.first() else { return Ok(String::new()); };
|
|
let value: RestCreate0 = REST_DECODER(source).map_err(fault)?;
|
|
Ok(value.field0)
|
|
}
|
|
|
|
fn reference(values: &[String]) -> Result<String, Fault> {
|
|
let Some(source) = values.first() else { return Ok(String::new()); };
|
|
if source.len() > 16 * 1024 * 1024 { return Err(fault("byte limit")); }
|
|
struct Object;
|
|
impl<'input> serde::de::Visitor<'input> for Object {
|
|
type Value = Profile;
|
|
fn expecting(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
output.write_str("an object")
|
|
}
|
|
fn visit_map<Access: serde::de::MapAccess<'input>>(self, access: Access) -> Result<Profile, Access::Error> {
|
|
Profile::deserialize(serde::de::value::MapAccessDeserializer::new(access))
|
|
}
|
|
}
|
|
let mut decoder = serde_json::Deserializer::from_str(source);
|
|
let value = serde::Deserializer::deserialize_map(&mut decoder, Object).map_err(fault)?;
|
|
decoder.end().map_err(fault)?;
|
|
// 固定五个标量字段,类型已证明层数和值数;保留其正常构造与释放。
|
|
let Profile { name, bio, rank, tag, status } = value;
|
|
drop((bio, rank, tag, status));
|
|
Ok(name)
|
|
}
|
|
|
|
fn main() {
|
|
println!("workload,sample,implementation,nanos,checksum");
|
|
for source in [
|
|
r#"{"name":"Dever"}"#,
|
|
r#"{"name":"Dever","bio":null,"tag":null,"status":"Disabled"}"#,
|
|
] {
|
|
assert_eq!(generated(&[source.into()]).unwrap(), "Dever");
|
|
assert_eq!(reference(&[source.into()]).unwrap(), "Dever");
|
|
}
|
|
for source in [
|
|
"[]", "null", "{}", r#"{"name":"x","name":"y"}"#,
|
|
r#"{"name":"x","na\u006de":"y"}"#, r#"{"name":"x","extra":1}"#,
|
|
r#"{"name":"x","rank":null}"#, r#"{"name":"x","status":"Other"}"#,
|
|
r#"{"name":"x","status":{"Active":null}}"#,
|
|
r#"{"name":"x","bio":"\ud800"}"#, r#"{"name":"x"} null"#,
|
|
] {
|
|
assert!(generated(&[source.into()]).is_err(), "{source}");
|
|
assert!(reference(&[source.into()]).is_err(), "{source}");
|
|
}
|
|
for (name, bio) in [
|
|
("short", "x".repeat(16)),
|
|
("plain_4096", "x".repeat(4096)),
|
|
("plain_65536", "x".repeat(65536)),
|
|
("escaped", "雪\"\\\n".repeat(1024)),
|
|
] {
|
|
let input = vec![serde_json::json!({"name":"Dever","bio":bio,"rank":7,"tag":"automatic","status":"Active"}).to_string()];
|
|
compare(&format!("rest_input_{name}"), &input, 1000, generated, reference, |name| name.len() as u64);
|
|
}
|
|
}
|