Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+482
View File
@@ -0,0 +1,482 @@
use dever_runtime::wire::{document, json::Json};
#[path = "json/encode.rs"]
mod encode;
#[path = "json/input.rs"]
mod input;
#[test]
fn fixed_wire_keeps_syntax_and_byte_limits_without_a_second_parse() {
use dever_runtime::wire;
for source in [r#""\ud800""#, r#""\udc00""#, r#""x" null"#] {
assert!(wire::decode_fixed::<String>(source).is_err(), "{source}");
}
let source = format!("\"{}\"", "x".repeat(document::MAX_BYTES - 2));
assert_eq!(
wire::decode_fixed::<String>(&source).unwrap().len(),
document::MAX_BYTES - 2
);
assert!(wire::decode_fixed::<String>(&(source + " ")).is_err());
let overhead = wire::response_fixed(&"").unwrap().len();
let value = "x".repeat(document::MAX_BYTES - overhead);
assert_eq!(
wire::response_fixed(&value).unwrap().len(),
document::MAX_BYTES
);
assert_eq!(
wire::response_fixed_bytes(&value).unwrap().len(),
document::MAX_BYTES
);
let oversized = value + "x";
assert!(wire::response_fixed(&oversized).is_err());
assert!(wire::response_fixed_bytes(&oversized).is_err());
let value = "雪\"\\\n";
assert_eq!(wire::response_fixed(&value), wire::response(&value));
assert_eq!(
wire::response_fixed_bytes(&value).unwrap(),
wire::response(&value).unwrap().into_bytes()
);
}
#[test]
fn parser_keeps_numbers_order_and_node_ids() {
let source = r#"{"b":1e+03,"a":[null,"雪",-0]}"#;
let document = document::parse(source).unwrap();
assert_eq!(document.root, 5);
assert_eq!(document::stringify(&document).unwrap(), source);
assert_eq!(document::property(&document, document.root, "b"), Some(0));
assert_eq!(document::element(&document, 4, 1), Some(2));
for source in ["{}", "[{},[]]", r#"{"":{}}"#] {
let parsed = document::parse(source).unwrap();
assert_eq!(document::stringify(&parsed).unwrap(), source);
assert_eq!(document::property(&parsed, parsed.root, "missing"), None);
}
}
#[test]
fn parser_rejects_duplicates_surrogates_and_trailing_content() {
for source in [
r#"{"name":1,"name":2}"#,
r#""\ud800""#,
r#"[1,]"#,
"null false",
r#""\udc00""#,
r#""\ud800\u0061""#,
r#""\u00""#,
"\"雪\n\"",
] {
assert!(document::parse(source).is_err(), "{source}");
}
let duplicate = r#"{"雪":0,"\u96ea":[}"#;
let error = document::parse(duplicate).unwrap_err();
assert_eq!(error.message, "duplicate JSON object key");
assert_eq!(
error.position,
duplicate[..duplicate.rfind(':').unwrap()].chars().count()
);
assert!(
Json::parse(duplicate)
.unwrap_err()
.to_string()
.contains("duplicate JSON object key")
);
assert_eq!(
document::parse(r#""\ud83d\ude42""#).unwrap().nodes,
vec![document::Value::String("🙂".into())]
);
for text in ["", "plain text", "雪🙂", "雪\"\\\n\0🙂", "\u{08}\u{0c}\r\t"] {
let source = serde_json::to_string(text).unwrap();
let parsed = document::parse(&source).unwrap();
assert_eq!(parsed.nodes, vec![document::Value::String(text.into())]);
assert_eq!(document::stringify(&parsed).unwrap(), source);
assert_eq!(Json::parse(&source).unwrap().as_text().unwrap(), text);
}
}
#[test]
fn document_string_escaping_matches_serde_for_unicode_and_control_boundaries() {
let encode = |text: String| {
let expected = serde_json::to_string(&text).unwrap();
let value = document::Document {
root: 0,
nodes: vec![document::Value::String(text)],
};
assert_eq!(document::stringify(&value).unwrap(), expected);
assert_eq!(document::parse(&expected).unwrap().nodes, value.nodes);
};
encode(
(0..=u32::from(char::MAX))
.filter_map(char::from_u32)
.collect(),
);
encode(
(128..=u32::from(char::MAX))
.filter_map(char::from_u32)
.collect(),
);
for character in (0..32).map(char::from).chain(['"', '\\']) {
for text in [
format!("雪🙂{character}𐀀a{character}"),
format!("{character}{character}雪🙂"),
] {
encode(text);
}
}
encode(String::new());
}
#[test]
fn json_property_update_and_scalar_reads_preserve_wire_text() {
let value = Json::parse(r#"{"a":1,"b":[true]}"#).unwrap();
assert_eq!(value.property("a").unwrap().unwrap().as_integer(), Ok(1));
assert_eq!(value.property("missing").unwrap(), None);
let updated = value
.set_property("a", &Json::parse("1.000e2").unwrap())
.unwrap();
assert_eq!(updated.as_str(), r#"{"a":1.000e2,"b":[true]}"#);
assert_eq!(
Json::parse(r#""hello""#).unwrap().as_text(),
Ok("hello".into())
);
}
#[test]
fn parser_enforces_depth_and_value_budgets() {
let nested = "[".repeat(document::MAX_DEPTH) + &"]".repeat(document::MAX_DEPTH);
assert!(document::parse(&nested).is_ok());
let too_deep = "[".repeat(document::MAX_DEPTH + 1) + &"]".repeat(document::MAX_DEPTH + 1);
assert!(document::parse(&too_deep).is_err());
let allowed = format!("[{}0]", "0,".repeat(document::MAX_VALUES - 2));
assert!(document::parse(&allowed).is_ok());
let many = format!("[{}0]", "0,".repeat(document::MAX_VALUES - 1));
assert!(document::parse(&many).is_err());
}
#[test]
fn invalid_utf8_escape_reports_a_codepoint_position_without_panicking() {
for source in [r#""\雪""#, r#""\u0雪雪""#] {
assert!(document::parse(source).is_err());
}
assert_eq!(document::parse("[\"雪\",]").unwrap_err().position, 5);
for source in ["\"plain", "\"雪🙂", "{\"雪🙂"] {
let error = document::parse(source).unwrap_err();
assert_eq!(error.message, "unterminated JSON string");
assert_eq!(error.position, source.chars().count());
}
}
#[test]
fn manual_documents_reject_forward_references() {
let document = document::Document {
root: 1,
nodes: vec![document::Value::Null, document::Value::Array(vec![1])],
};
assert!(document::stringify(&document).is_err());
}
#[test]
fn manual_document_numbers_preserve_json_lexical_rules() {
let encode = |raw: &str| {
document::stringify(&document::Document {
root: 0,
nodes: vec![document::Value::Number(raw.into())],
})
};
for raw in [
"0",
"-0",
"1.00",
"-0.125E+03",
"1e9999",
"1234567890123456789012345678901234e-12",
] {
assert_eq!(encode(raw).unwrap(), raw);
}
for raw in [
"",
"-",
"+1",
"01",
"-01",
"0x1",
"NaN",
"1.",
".1",
"1e",
"1e+",
"1_0",
" 1",
"1 ",
"1\n",
"null",
"[]",
"1true",
"1雪",
"0],\"x\":true",
] {
let error = encode(raw).unwrap_err();
assert_eq!(error.node, 0, "{raw}");
assert_eq!(error.message, "invalid JSON number", "{raw}");
}
}
#[test]
fn scalar_and_array_encoding_reuses_the_same_budgeted_parser() {
assert_eq!(Json::boolean(true).unwrap().as_str(), "true");
assert_eq!(Json::integer(42).unwrap().as_str(), "42");
assert_eq!(Json::string("雪").unwrap().as_str(), "\"雪\"");
assert!(Json::float(f64::NAN).is_err());
let array = Json::array(&[Json::integer(1).unwrap(), Json::boolean(false).unwrap()]).unwrap();
assert_eq!(array.as_str(), "[1,false]");
}
#[test]
fn source_document_keeps_the_256_container_contract() {
let nested = "[".repeat(256) + &"]".repeat(256);
let parsed = document::parse_with_depth(&nested, document::DOCUMENT_MAX_DEPTH).unwrap();
assert_eq!(
document::stringify_with_depth(&parsed, document::DOCUMENT_MAX_DEPTH).unwrap(),
nested
);
assert!(document::stringify_with_depth(&parsed, 255).is_err());
let too_deep = "[".repeat(257) + &"]".repeat(257);
assert!(document::parse_with_depth(&too_deep, document::DOCUMENT_MAX_DEPTH).is_err());
}
#[test]
fn raw_properties_preserve_subtree_bytes_and_distinguish_null_from_missing() {
let value = Json::parse(r#"{"payload": [ 1e9999, -0, "\u96ea" ], "empty": null}"#).unwrap();
assert_eq!(
value.property("payload").unwrap().unwrap().as_str(),
r#"[ 1e9999, -0, "\u96ea" ]"#
);
assert_eq!(value.property("empty").unwrap().unwrap().as_str(), "null");
assert_eq!(value.property("missing").unwrap(), None);
assert!(Json::integer(1).unwrap().property("key").is_err());
assert!(
Json::parse("[]")
.unwrap()
.set_property("key", &value)
.is_err()
);
let updated = value
.set_property("empty", &Json::boolean(true).unwrap())
.unwrap();
assert!(updated.as_str().contains(r#"[ 1e9999, -0, "\u96ea" ]"#));
assert_eq!(value.property("empty").unwrap().unwrap().as_str(), "null");
}
#[test]
fn property_keys_compare_decoded_text_without_changing_subtree_spelling() {
let source =
r#" {"\u0061": [ 1e9999, -0 ], "雪\"\\\n": "\u96ea", "\ud83d\ude42": null, "last": true} "#;
let value = Json::parse(source).unwrap();
for (key, expected) in [
("a", Some("[ 1e9999, -0 ]")),
("雪\"\\\n", Some(r#""\u96ea""#)),
("🙂", Some("null")),
("last", Some("true")),
(r"\u0061", None),
("missing", None),
] {
assert_eq!(
value.property(key).unwrap().as_ref().map(Json::as_str),
expected,
"{key}"
);
}
assert_eq!(value.as_str(), source);
for source in [r#"{"a":1,"\u0061":2}"#, r#"{"a":1,"tail":[}"#] {
assert!(Json::parse(source).is_err());
}
}
#[test]
fn shared_wire_checks_duplicate_names_and_all_three_budgets() {
use dever_runtime::wire;
for source in [r#"{"a":1,"\u0061":2}"#, r#"[{"a":1,"a":2}]"#, r#""\ud800""#] {
assert!(Json::parse(source).is_err(), "{source}");
assert!(
wire::decode::<serde_json::Value>(source).is_err(),
"{source}"
);
}
let maximum = format!("[{}0]", "0,".repeat(document::MAX_VALUES - 2));
assert!(Json::parse(&maximum).is_ok());
assert!(wire::decode::<Vec<i64>>(&maximum).is_ok());
let excessive = format!("[{}0]", "0,".repeat(document::MAX_VALUES - 1));
assert!(Json::parse(&excessive).is_err());
assert!(wire::decode::<Vec<i64>>(&excessive).is_err());
let nested = "[".repeat(document::MAX_DEPTH) + &"]".repeat(document::MAX_DEPTH);
assert!(Json::parse(&nested).is_ok());
assert!(Json::parse(&format!("[{nested}]")).is_err());
assert!(wire::response(&serde_json::from_str::<serde_json::Value>(&nested).unwrap()).is_err());
assert!(Json::string(&"x".repeat(document::MAX_BYTES - 2)).is_ok());
assert!(Json::string(&"x".repeat(document::MAX_BYTES - 1)).is_err());
}
#[test]
fn manual_document_shared_subgraphs_are_bounded_before_expansion() {
let mut graph = document::Document {
root: 0,
nodes: vec![document::Value::Null],
};
for index in 1..40 {
graph.nodes.push(document::Value::Array(vec![
index as i64 - 1,
index as i64 - 1,
]));
graph.root = index;
}
let error = document::stringify(&graph).unwrap_err();
assert!(error.node < 20, "{error}");
assert!(error.message.contains("65536"), "{error}");
let oversized = document::Document {
root: 1,
nodes: vec![
document::Value::String("x".repeat(document::MAX_BYTES / 2)),
document::Value::Array(vec![0, 0]),
],
};
assert!(
document::stringify(&oversized)
.unwrap_err()
.message
.contains("16 MiB")
);
}
#[test]
fn replacing_a_field_does_not_accumulate_obsolete_document_nodes() {
let source = format!(
r#"{{"count":0,"values":[{}0]}}"#,
"0,".repeat(document::MAX_VALUES - 4)
);
let original = Json::parse(&source).unwrap();
let updated = original
.set_property("count", &Json::integer(1).unwrap())
.unwrap();
assert_eq!(
updated.property("count").unwrap().unwrap().as_integer(),
Ok(1)
);
assert_eq!(
original.property("count").unwrap().unwrap().as_integer(),
Ok(0)
);
assert!(
updated
.set_property("extra", &Json::null().unwrap())
.is_err()
);
}
#[test]
fn fixed_record_encoding_keeps_byte_limits_and_escaping() {
#[derive(serde::Serialize)]
struct Record<'value> {
text: &'value str,
}
for text in ["", "雪\"\\\n"] {
let value = Record { text };
assert_eq!(Json::encode_proven(&value, 2, 1), Json::encode(&value));
}
let text = "x".repeat(document::MAX_BYTES - r#"{"text":""}"#.len());
assert_eq!(
Json::encode(&Record { text: &text })
.unwrap()
.as_str()
.len(),
document::MAX_BYTES
);
assert!(
Json::encode(&Record {
text: &(text + "x")
})
.is_err()
);
}
#[test]
fn decimal_wire_is_an_exact_string_not_a_floating_point_value() {
use dever_runtime::{value::decimal::Decimal, wire};
let value = wire::decode::<Decimal>(r#""1234567890123456789012345678901234""#).unwrap();
assert_eq!(
Json::encode(&value).unwrap().as_str(),
r#""1234567890123456789012345678901234""#
);
assert!(wire::decode::<Decimal>("1.25").is_err());
assert!(wire::decode::<Decimal>(r#""NaN""#).is_err());
assert!(wire::decode::<Decimal>(r#""12345678901234567890123456789012345""#).is_err());
}
#[test]
fn decimal_nullable_lists_preserve_extremes_and_normalized_output() {
use dever_runtime::{value::decimal::Decimal, wire};
let values = [
"-0.00",
"1.2300",
"1E-6176",
"9.999999999999999999999999999999999E6144",
];
let mut numbers = values
.map(|value| Some(Decimal::parse(value).unwrap()))
.to_vec();
numbers.push(None);
let encoded = Json::encode(&numbers).unwrap();
let expected = [
Some("0"),
Some("1.23"),
Some("1E-6176"),
Some("9.999999999999999999999999999999999E+6144"),
None,
];
assert_eq!(encoded.as_str(), serde_json::to_string(&expected).unwrap());
assert_eq!(
wire::decode::<Vec<Option<Decimal>>>(encoded.as_str()).unwrap(),
numbers
);
assert!(wire::decode::<Vec<Decimal>>(encoded.as_str()).is_err());
}
#[test]
fn raw_deserialization_preserves_subtree_text_and_enforces_bounds() {
let source = r#" {"huge": 1e9999, "text": "\u96ea", "array": [ 1, 2 ]} "#;
let value: Json = serde_json::from_str(source).unwrap();
assert_eq!(value.as_str(), source.trim());
assert_eq!(Json::parse(source).unwrap().as_str(), source);
let parsed = Json::parse(source.trim()).unwrap();
assert_eq!(value, parsed);
for value in [value, parsed] {
assert_eq!(format!("{value:?}"), format!("Json({:?})", source.trim()));
assert_eq!(
Json::encode_with(|output| output.json(&value))
.unwrap()
.as_str(),
source.trim()
);
assert_eq!(value.clone().into_text(), source.trim());
let child = value.property("array").unwrap().unwrap();
assert_eq!(
Json::encode_with(|output| output.json(&child))
.unwrap()
.as_str(),
"[ 1, 2 ]"
);
let updated = value.set_property("array", &child).unwrap();
assert_eq!(updated.property("array").unwrap().as_ref(), Some(&child));
assert_eq!(
updated.property("huge").unwrap().unwrap().as_str(),
"1e9999"
);
}
for source in [
r#"{"a":1,"\u0061":2}"#.to_owned(),
r#"["\ud800"]"#.to_owned(),
"[".repeat(65) + &"]".repeat(65),
format!("[{}0]", "0,".repeat(document::MAX_VALUES - 1)),
format!("\"{}\"", "x".repeat(document::MAX_BYTES - 1)),
] {
assert!(serde_json::from_str::<Json>(&source).is_err());
}
}