Files
alknet/tasks/typedef/schema-types.md
T
deepseek-v4-pro db100f9849 feat(typedef): add implementation task decomposition (12 tasks, 7 generations)
Break the alknet-typedef architecture specs into atomic, dependency-ordered
implementation tasks covering crate init, error types, schema layer, data
access, both layout modes (aligned static + packed sequential), TUnion
dispatch, jsonschema custom keyword validators, TypedefEngine integration,
comprehensive tests, and a final review checkpoint.

Validated: 12 tasks, 0 cycles, 7 parallel generations.
2026-07-21 09:36:30 +00:00

7.0 KiB
Raw Blame History

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
typedef/schema-types Implement TypeDef kind detection, schema annotation parsing, $ref normalization, and Endian enum pending
typedef/crate-init
moderate medium component implementation

Description

Implement the schema layer in crates/alknet-typedef/src/schema.rs. This module provides the foundational types and functions that every other module depends on: TypeDef kind detection, type size constants, schema annotation parsing, $ref normalization, and the Endian enum.

Per schema-layer.md and ADR-097.

TypeDef kind detection

The engine needs to identify which TypeDef:* kind a schema node declares. The 17 kinds (16 from TypeBox's typedef.ts + TypeDef:Bytes added by alknet-typedef):

Kind Keyword Category Byte size
Float32 TypeDef:Float32 fixed 4
Float64 TypeDef:Float64 fixed 8
Int8 TypeDef:Int8 fixed 1
Int16 TypeDef:Int16 fixed 2
Int32 TypeDef:Int32 fixed 4
Uint8 TypeDef:Uint8 fixed 1
Uint16 TypeDef:Uint16 fixed 2
Uint32 TypeDef:Uint32 fixed 4
Boolean TypeDef:Boolean fixed 1
Enum TypeDef:Enum fixed 4 (u32 index)
String TypeDef:String variable —
Bytes TypeDef:Bytes variable —
Struct TypeDef:Struct composite sum of fields
Union TypeDef:Union composite discriminator + variant
Array TypeDef:Array composite count × element
Record TypeDef:Record variable —
Timestamp TypeDef:Timestamp variable —

Implement:

/// Returns the `TypeDef:*` kind string if the schema node declares one.
/// Returns `None` if the node has no `TypeDef:*` keyword.
pub fn get_typedef_kind(node: &serde_json::Value) -> Option<&str>;

/// Returns the fixed byte size for a TypeDef kind, or `None` if variable-size.
pub fn type_size(kind: &str) -> Option<usize>;

/// Returns the natural alignment for a TypeDef kind.
pub fn natural_alignment(kind: &str) -> usize;

/// Returns true if the kind is a fixed-size type.
pub fn is_fixed_size(kind: &str) -> bool;

Endian enum

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Endian {
    Little,
    Big,
}

impl Endian {
    /// Parse from the schema's "endian" annotation. Defaults to Little.
    pub fn from_schema(schema: &serde_json::Value) -> Self;
}

Schema annotation parsing

Parse the annotations decided in ADR-097:

/// Parse the "encoding" annotation from a variable-length type's keyword value.
/// The keyword value may be `true` (shorthand for length-prefixed) or an object
/// with an "encoding" field.
pub fn parse_encoding(keyword_value: &serde_json::Value) -> VariableEncoding;

pub enum VariableEncoding {
    LengthPrefixed,
    OffsetIndirect,
}

/// Parse the "align" annotation from a schema node. Returns None if not specified.
pub fn parse_align(node: &serde_json::Value) -> Option<usize>;

/// Parse the "maxLength" annotation (standard JSON Schema keyword).
pub fn parse_max_length(node: &serde_json::Value) -> Option<usize>;

/// Parse the "endian" annotation. Defaults to Little if absent or unrecognized.
pub fn parse_endian(node: &serde_json::Value) -> Endian;

TUnion discriminator parsing

Parse the discriminator shape from a TypeDef:Union schema node:

pub enum DiscriminatorKind {
    Byte { offset: usize, disc_type: String },
    Field { name: String },
}

/// Parse the "discriminator" annotation from a TUnion schema node.
pub fn parse_discriminator(node: &serde_json::Value) -> Result<DiscriminatorKind, TypedefError>;

$ref normalization

TypeBox generates bare-name $ref values (e.g., "$ref": "Read"). The jsonschema crate requires full JSON Pointer paths (e.g., "$ref": "#/$defs/Read"). Normalize at schema load time:

/// Walk the schema tree. For every "$ref" whose value is a bare name
/// (no "#" prefix), rewrite it to "#/$defs/<name>".
/// Full JSON Pointer refs pass through unchanged. Idempotent.
pub fn normalize_refs(schema: &mut serde_json::Value);

This is a ~20-line recursive walk. It runs once at load time, before the schema is passed to jsonschema::validator_for or the offset computation.

What this does NOT include

  • The actual offset computation (that's offset_map.rs and layout_builder.rs)
  • The read/write functions (that's data_access.rs)
  • The custom keyword validators (that's validation.rs)
  • The TypedefEngine struct (that's engine.rs)

Acceptance Criteria

  • get_typedef_kind() correctly identifies all 17 TypeDef:* kinds
  • type_size() returns correct byte sizes for all fixed-size types
  • type_size() returns None for variable-length and composite types
  • natural_alignment() returns correct alignment for each kind
  • Endian enum with Little and Big variants
  • Endian::from_schema() defaults to Little when annotation is absent
  • Endian::from_schema() returns Big when "endian": "big"
  • parse_encoding() handles both true (shorthand) and { "encoding": "..." } (object)
  • parse_encoding() defaults to LengthPrefixed when annotation is absent
  • parse_align() returns None when no "align" annotation
  • parse_max_length() returns None when no "maxLength" annotation
  • parse_discriminator() handles byte-offset (kind: "byte") and field-name (kind: "field")
  • parse_discriminator() returns Err(TypedefError::Schema(...)) for malformed discriminators
  • normalize_refs() rewrites "$ref": "Read" → "$ref": "#/$defs/Read"
  • normalize_refs() leaves "$ref": "#/$defs/Read" unchanged (idempotent)
  • normalize_refs() handles nested objects and arrays recursively
  • All public functions have doc comments
  • cargo check -p alknet-typedef succeeds
  • cargo clippy -p alknet-typedef succeeds with no warnings
  • cargo build --workspace still succeeds

References

  • docs/architecture/crates/typedef/schema-layer.md — the 17 TypeDef kinds, annotations, $ref normalization
  • docs/architecture/decisions/097-schema-annotations.md — ADR-097 (concrete JSON shapes)
  • docs/architecture/decisions/095-alknet-typedef-purpose-scope-jsonschema-engine.md — ADR-095
  • docs/research/alknet-typedef/findings.md — POC results, open questions
  • /workspace/alknet-typedef-poc/src/offset.rs — POC reference for kind detection

Notes

This is the foundational types module. Every other module depends on it for TypeDef kind identification, size lookups, and annotation parsing. The $ref normalization bridges TypeBox output to jsonschema input — without it, bare-name refs from TypeBox would fail to resolve. The TEnum kind uses a u32 index (not a variable-length string) — a deliberate deviation from TypeBox fidelity for binary efficiency, per the schema-layer spec.

Summary

To be filled on completion