9.5 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| typedef/engine | Implement TypedefEngine struct combining layout and validation, with compile() constructor | completed |
|
moderate | medium | component | implementation |
Description
Implement the TypedefEngine struct in crates/alknet-typedef/src/engine.rs. This is
the compiled form of a schema — the main entry point for consumers. It combines the
layout engine (both modes) and the jsonschema validator into a single struct.
Per validation.md §"The TypedefEngine struct" and overview.md.
Target shape
/// The compiled form of a typedef schema. Combines the layout engine
/// (both packed and aligned modes) and the jsonschema validator.
///
/// Built once at schema load time via [`TypedefEngine::compile()`].
/// Used for repeated read/write/validate operations at access time.
pub struct TypedefEngine {
/// The layout strategy — packed sequential or aligned static.
layout: Layout,
/// The compiled jsonschema validator (built once at load time).
validator: jsonschema::Validator,
/// The schema's endianness.
endian: Endian,
/// The original schema (for reference, debugging, and TUnion dispatch).
schema: serde_json::Value,
}
/// The layout strategy selected by the consumer.
enum Layout {
/// Packed sequential layout for protocol wire formats.
Packed {
builder: LayoutBuilder,
reader: SequentialReader,
},
/// Aligned static layout for mmap-friendly formats.
Aligned {
offset_map: OffsetMap,
},
}
/// The layout mode selected at engine construction time.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LayoutMode {
/// Packed sequential — for protocol wire formats (SFTP, channels, TTY).
Packed,
/// Aligned static — for mmap-friendly formats (metatensor, safetensors).
Aligned,
}
impl TypedefEngine {
/// Compile a schema into a TypedefEngine.
///
/// This is the expensive operation — it parses the schema, normalizes
/// `$ref` values, computes the layout, and builds the jsonschema
/// validator. Call once at load time; use the returned engine for
/// repeated operations.
///
/// The `mode` parameter selects the layout strategy. The same schema
/// can be compiled in either mode.
pub fn compile(
schema: &mut serde_json::Value,
mode: LayoutMode,
) -> Result<Self, TypedefError>;
/// The schema's endianness.
pub fn endian(&self) -> Endian;
/// The layout mode this engine was compiled with.
pub fn mode(&self) -> LayoutMode;
/// Access the aligned offset map. Returns `None` if compiled in
/// packed mode.
pub fn offset_map(&self) -> Option<&OffsetMap>;
/// Access the layout builder (write-side of packed mode).
/// Returns `None` if compiled in aligned mode.
pub fn layout_builder(&self) -> Option<&LayoutBuilder>;
/// Access the sequential reader (read-side of packed mode).
/// Returns `None` if compiled in aligned mode.
pub fn sequential_reader(&self) -> Option<&SequentialReader>;
/// Validate a JSON value against the schema. The jsonschema validator
/// is already compiled — this is a fast check.
///
/// Returns `Ok(())` if valid, `Err(TypedefError::Validation(...))` if invalid.
pub fn validate_json(&self, instance: &serde_json::Value) -> Result<(), TypedefError>;
/// Check if a JSON value is valid against the schema.
pub fn is_valid_json(&self, instance: &serde_json::Value) -> bool;
/// Read a field from a buffer at its computed offset (aligned mode).
/// Returns `None` if compiled in packed mode — use `sequential_reader()` instead.
pub fn read_field<'a>(
&self,
buffer: &'a [u8],
field_path: &str,
) -> Result<FieldValue<'a>, TypedefError>;
/// Write a field to a buffer at its computed offset (aligned mode).
/// Returns `None` if compiled in packed mode — use `layout_builder()` instead.
pub fn write_field(
&self,
buffer: &mut [u8],
field_path: &str,
value: &FieldValue<'_>,
) -> Result<(), TypedefError>;
}
compile() constructor
The compile() method performs these steps in order:
- Normalize
$refvalues — callschema::normalize_refs()to rewrite bare-name refs to full JSON Pointer paths. - Parse endianness — extract
"endian"annotation (defaults toLittle). - Build the layout — depending on
mode:Packed: buildLayoutBuilderandSequentialReaderfrom the schema.Aligned: computeOffsetMapfrom the schema.
- Build the validator — call
validation::build_validator()to register all 17 custom keywords and compile the jsonschema validator. - Return the engine — all components ready for repeated use.
Aligned mode convenience methods
When compiled in Aligned mode, read_field() and write_field() provide
convenient access using the OffsetMap:
read_field(buffer, "header.version")→ looks up the field's byte range in theOffsetMap, reads the appropriate type usingdata_accessfunctions.write_field(buffer, "header.version", &FieldValue::U32(1))→ looks up the byte range, writes usingdata_accessfunctions.
What this does NOT include
- A builder API for schema construction (deferred, OQ-071)
- Schema evolution / Value system (out of scope for v1)
- Code generation (out of scope)
Acceptance Criteria
TypedefEnginestruct withlayout,validator,endian,schemafieldsLayoutenum withPacked { builder, reader }andAligned { offset_map }variantsLayoutModeenum withPackedandAlignedvariantsTypedefEngine::compile(&mut schema, mode)performs all load-time workcompile()normalizes$refvalues before buildingcompile()builds the correct layout for the selected modecompile()builds the jsonschema validator with all 17 custom keywordscompile()returnsTypedefError::Schemafor invalid schemasendian()returns the schema's endiannessmode()returns the layout modeoffset_map()returnsSome(&OffsetMap)in aligned mode,Nonein packed modelayout_builder()returnsSome(&LayoutBuilder)in packed mode,Nonein aligned modesequential_reader()returnsSome(&SequentialReader)in packed mode,Nonein aligned modevalidate_json()delegates to the compiled jsonschema validatoris_valid_json()returns true/false without error detailsread_field()works in aligned mode for all fixed-size and variable-length typeswrite_field()works in aligned mode for all fixed-size and variable-length typesread_field()andwrite_field()return errors in packed mode (use layout-specific APIs)- No
unwrap()orexpect()on error paths - All public types and functions have doc comments
cargo check -p alknet-typedefsucceedscargo clippy -p alknet-typedefsucceeds with no warningscargo build --workspacestill succeeds
References
- docs/architecture/crates/typedef/validation.md — TypedefEngine struct, compile() constructor
- docs/architecture/crates/typedef/overview.md — architecture, consumers
- docs/architecture/crates/typedef/layout-engine.md — the two layout modes
- docs/architecture/crates/typedef/data-access.md — read/write functions
- docs/architecture/decisions/095-alknet-typedef-purpose-scope-jsonschema-engine.md — ADR-095
- docs/architecture/decisions/096-two-layout-modes-packed-vs-aligned.md — ADR-096
- docs/architecture/decisions/098-error-handling-validation-strategy.md — ADR-098
Notes
This is the integration task — it wires together all the components built in the preceding tasks. The
TypedefEngineis the main entry point for consumers. Thecompile()constructor does all the expensive work once at load time. The engine supports both layout modes via theLayoutenum — the consumer selects the mode at construction time. The aligned-mode convenience methods (read_field,write_field) provide a simple API for the common mmap use case. Protocol consumers use the layout-specific APIs (layout_builder(),sequential_reader()) directly.
Summary
Implemented TypedefEngine in crates/alknet-typedef/src/engine.rs as the integration layer for all Gen 1-4 components. The compile() constructor normalizes $ref values, parses endianness, builds the mode-appropriate layout (LayoutBuilder+SequentialReader for packed, OffsetMap for aligned), and builds the jsonschema validator with all 17 custom keywords. Mode accessors (offset_map, layout_builder, sequential_reader) return Options gated on the compiled mode, and validate_json/is_valid_json delegate to the compiled validator (using ValidationError::to_owned() to obtain the 'static lifetime). Aligned-mode convenience methods read_field/write_field dispatch over all fixed-size and length-prefixed kinds via data_access, return TypedefError::Access in packed mode and for composite FieldValue variants, and use a lookup_field_schema helper that walks dotted paths through properties. A manual Debug impl formats the layout, endian, and schema while using a placeholder for the jsonschema::Validator. Re-exports TypedefEngine and LayoutMode from lib.rs; 22 new unit tests pass alongside the full crate suite (202 total).