Resolve v0.1.0 open questions and fix production-readiness issues
POC: /workspace/alktype-builder-poc/ (18/18 tests pass, findings in
docs/research/alktype-builder-poc/findings.md). Round 2 adds the SFTP
Packet validate_bytes tests (7 new: valid Init/Read/Write/Status,
short buffer, unknown discriminator, over-maxLength Bytes).
Open questions resolved (OQ-004 through OQ-008):
- OQ-004: Discriminator::Field name is String (already implemented;
docs updated to mark resolved)
- OQ-005: Both union discriminator kinds return the same shape:
{__discriminator, ...variant-fields}. Field-name path also had a
real offset bug (returned start, not end) - fixed.
- OQ-006: builder.md Example 3 now wraps the Union in a
Schema::struct_().field("payload", ...) and merges $defs via
Definitions::merge_into (matches the engine's AlkType:Struct-at-root
constraint and the SFTP wire shape)
- OQ-007: Bytes materialization is array-of-u8 (Value::Array of
Value::Number, one entry per byte 0..=255). BytesValidator accepts
both Value::String (validate_json) and Value::Array (validate_bytes).
maxLength = max byte count. Replaces the lossy from_utf8_lossy path
that corrupted non-UTF-8 bytes and broke maxLength semantics.
- OQ-008 (new): UnionValidator now dispatches to variant schemas via
sub-validators built at factory time. AlkTypeEngine::compile calls
schema::inline_union_variant_refs before build_validator to inline
$refs in union mapping entries (necessary because union_factory
receives the union node, but $defs live at the schema root).
Production-readiness fixes in src/ (no stubs/hedges in a published crate):
- materialize.rs: Record stub -> full count-prefixed key/value pair
implementation per schema-layer.md TRecord
- materialize.rs: root_of() was broken (returned the current node, not
the schema root) -> root schema threaded through every recursive call
so resolve_ref_or_inline can resolve $refs for nested composites
- builder.rs: LengthPrefixed encoding setter was a no-op when the
keyword was already in object form -> complete the branch (updates
the encoding entry in place for both LengthPrefixed and OffsetIndirect)
- builder.rs, engine.rs: POC-referencing comments cleaned up; the
round-trip test's or_else fallback (papering over write_field being
aligned-only) replaced with direct byte writes
Documentation:
- builder.md: Example 3 updated; Discriminator::Field spec shows String;
Open Questions section updated (OQ-004 resolved)
- validation.md: AlkType:Bytes and AlkType:Union validator descriptions
updated for array-of-u8 form and variant dispatch
- open-questions.md: OQ-004/005/006/007/008 marked resolved; new
Validation theme entries
- questions/004-008: individual OQ files updated with resolutions
- findings.md: round 2 results documented
Verification:
- cargo test: 369 -> 391 tests pass (22 new: 14 materialize, 5
inline_union_variant_refs, 3 validation/builder)
- cargo clippy --all-targets: clean
- POC: 11 -> 18 tests (7 new SFTP Packet tests); all pass
This commit is contained in:
1 parent
c6893eece8
commit
c0217d91a8
15 files changed
+1553
-493
No files matched your search
+8
-15
@@ -86,6 +86,7 @@ impl AlkTypeEngine {
|
||||
/// [`OffsetMap::compute`], or [`validation::build_validator`].
|
||||
pub fn compile(schema: &mut Value, mode: LayoutMode) -> Result<Self, AlkTypeError> {
|
||||
schema::normalize_refs(schema);
|
||||
schema::inline_union_variant_refs(schema);
|
||||
let endian = Endian::from_schema(schema);
|
||||
let layout = match mode {
|
||||
LayoutMode::Packed => {
|
||||
@@ -865,9 +866,8 @@ mod tests {
|
||||
// ----- validate_bytes tests (ADR-010) -----
|
||||
|
||||
fn chunk_header_schema() -> Value {
|
||||
// The POC's primary use case: channels' 8-byte chunk header,
|
||||
// big-endian, packed mode. Built via the builder to also
|
||||
// exercise ADR-009.
|
||||
// channels' 8-byte chunk header: big-endian, packed mode. Built
|
||||
// via the builder to also exercise ADR-009.
|
||||
crate::builder::Schema::struct_()
|
||||
.endian(Endian::Big)
|
||||
.field("channel_id", crate::builder::Schema::uint32())
|
||||
@@ -955,7 +955,9 @@ mod tests {
|
||||
#[test]
|
||||
fn validate_bytes_with_builder_schema_round_trips() {
|
||||
// Full round-trip: build schema via builder, compile, write bytes
|
||||
// via the engine, then validate via validate_bytes.
|
||||
// directly (packed-mode writes go through `LayoutBuilder`; for
|
||||
// this test we write the two u32s directly since the schema is
|
||||
// a simple flat struct), then validate via `validate_bytes`.
|
||||
let mut schema = crate::builder::Schema::struct_()
|
||||
.endian(Endian::Little)
|
||||
.field("channel_id", crate::builder::Schema::uint32())
|
||||
@@ -963,17 +965,8 @@ mod tests {
|
||||
.build();
|
||||
let engine = AlkTypeEngine::compile(&mut schema, LayoutMode::Packed).expect("compile");
|
||||
let mut buf = vec![0u8; 8];
|
||||
engine
|
||||
.write_field(&mut buf, "channel_id", &FieldValue::U32(42))
|
||||
.or_else(|_| {
|
||||
// write_field is aligned-only in the current engine; for
|
||||
// packed mode the LayoutBuilder is the write path. Fall
|
||||
// back to manual byte layout for the POC round-trip test.
|
||||
buf[0..4].copy_from_slice(&42u32.to_le_bytes());
|
||||
buf[4..8].copy_from_slice(&7u32.to_le_bytes());
|
||||
Ok::<(), AlkTypeError>(())
|
||||
})
|
||||
.unwrap();
|
||||
buf[0..4].copy_from_slice(&42u32.to_le_bytes());
|
||||
buf[4..8].copy_from_slice(&7u32.to_le_bytes());
|
||||
assert!(engine.validate_bytes(&buf).is_ok());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user