refactor: drop alktype dependency; add BAST doc for chunk header
- Remove alktype from Cargo.toml (its only usage was a thin wrapper over jsonschema::options().build()) - Replace alktype::validation::build_validator with direct jsonschema in dispatch.rs - Add docs/architecture/chunk-header.bast.json — the chunk header's BAST (Binary Abstract Syntax Tree) machine-readable wire spec - Embed as channels::wire::CHUNK_HEADER_BAST via include_str! so downstream Rust crates can consume it without a file lookup - Add test asserting the embedded BAST doc is valid JSON and matches the wire format - Update AGENTS.md §10 and implementation-specialist.md: BAST docs are the contract; trivial/hot-path formats stay hand-rolled, complex formats use the alktype engine or codegen Verification: - cargo test: 543 passed, 0 failed - cargo clippy --all-targets -- -D warnings: clean - cargo fmt --check: clean - cargo doc --no-deps: clean - BAST doc compiles + round-trips against alktype v0.2.0 engine
This commit is contained in:
1 parent
08e7df2aa0
commit
44d4b496e8
10 files changed
+95
-42
No files matched your search
@@ -34,6 +34,17 @@ pub const MAX_CHUNK_LEN: u32 = 16 * 1024 * 1024;
|
||||
/// without an explicit open op exchange.
|
||||
pub const CHANNEL_ID_ZERO: u32 = 0;
|
||||
|
||||
/// The chunk header's BAST (Binary Abstract Syntax Tree) document —
|
||||
/// the machine-readable wire-format spec. The canonical copy is
|
||||
/// `docs/architecture/chunk-header.bast.json`; this const embeds it so
|
||||
/// downstream Rust crates can consume it without a file lookup. BAST is
|
||||
/// plain JSON consumable by any language; the `alktype` crate compiles
|
||||
/// it into readers/writers/validators, and future codegen derives
|
||||
/// language-specific implementations from it. The hand-rolled
|
||||
/// [`parse_header`]/[`write_header`] functions are the hot path; the
|
||||
/// BAST document is the contract.
|
||||
pub const CHUNK_HEADER_BAST: &str = include_str!("../../docs/architecture/chunk-header.bast.json");
|
||||
|
||||
/// The parsed 8-byte chunk header.
|
||||
///
|
||||
/// `length = 0` is the EOF sentinel — the reassembled stream interprets
|
||||
@@ -251,6 +262,39 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chunk_header_bast_is_valid_json_and_describes_the_wire_format() {
|
||||
let doc: serde_json::Value =
|
||||
serde_json::from_str(CHUNK_HEADER_BAST).expect("BAST doc is valid JSON");
|
||||
let def = doc
|
||||
.get("$defs")
|
||||
.and_then(|d| d.get("ChunkHeader"))
|
||||
.expect("ChunkHeader def present");
|
||||
assert_eq!(def.get("kind").and_then(|v| v.as_str()), Some("struct"));
|
||||
assert_eq!(def.get("endian").and_then(|v| v.as_str()), Some("big"));
|
||||
let fields = def
|
||||
.get("fields")
|
||||
.and_then(|v| v.as_array())
|
||||
.expect("fields");
|
||||
assert_eq!(fields.len(), 2);
|
||||
assert_eq!(
|
||||
fields[0].get("name").and_then(|v| v.as_str()),
|
||||
Some("channel_id")
|
||||
);
|
||||
assert_eq!(
|
||||
fields[0].get("kind").and_then(|v| v.as_str()),
|
||||
Some("uint32")
|
||||
);
|
||||
assert_eq!(
|
||||
fields[1].get("name").and_then(|v| v.as_str()),
|
||||
Some("length")
|
||||
);
|
||||
assert_eq!(
|
||||
fields[1].get("kind").and_then(|v| v.as_str()),
|
||||
Some("uint32")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn read_header_round_trips_through_duplex() {
|
||||
let (mut reader, mut writer) = tokio::io::duplex(64);
|
||||
|
||||
Reference in new issue
Block a user