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.
6.0 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |||
|---|---|---|---|---|---|---|---|---|---|---|
| typedef/tunion | Implement TUnion discriminator dispatch for byte-offset and field-name discriminators | pending |
|
narrow | medium | component | implementation |
Description
Implement TUnion discriminator dispatch in crates/alknet-typedef/src/tunion.rs.
TUnion supports two discriminator kinds (ADR-097 §4): byte-offset (protocol dispatch,
e.g., SFTP type bytes) and field-name (typedef.ts string pattern).
Per data-access.md §"TUnion Dispatch" and schema-layer.md §"TUnion discriminators".
Target shape
/// The result of reading a TUnion discriminator.
#[derive(Debug, Clone)]
pub struct UnionDispatch {
/// The mapping key (stringified discriminator value).
pub key: String,
/// The byte offset where the variant struct starts.
pub variant_offset: usize,
/// The size of the discriminator in bytes.
pub discriminator_size: usize,
}
/// Read the discriminator value from a byte-offset TUnion.
/// The discriminator is a fixed-size integer at a known byte offset.
/// Returns the mapping key (as a string) and the variant struct offset.
///
/// This is the SFTP `Packet` enum pattern — byte 0 is the type byte,
/// bytes 1..N are the variant struct. The call protocol's event type
/// dispatch uses the same pattern.
pub fn read_byte_discriminator(
buffer: &[u8],
union_schema: &serde_json::Value,
endian: Endian,
) -> Result<UnionDispatch, TypedefError>;
/// Read the discriminator value from a field-name TUnion.
/// The discriminator is a named field within the struct — its offset
/// is computed like any other field. The consumer provides the
/// discriminator field's offset (from the OffsetMap or LayoutBuilder).
///
/// This is the typedef.ts `TUnion` pattern — the discriminator is a
/// field like any other, and the mapping keys are string values.
pub fn read_field_discriminator(
buffer: &[u8],
union_schema: &serde_json::Value,
disc_field_offset: usize,
endian: Endian,
) -> Result<UnionDispatch, TypedefError>;
/// Look up a variant schema from the union's mapping.
/// Returns the variant schema (resolving `$ref` if needed).
pub fn resolve_variant<'a>(
union_schema: &'a serde_json::Value,
key: &str,
) -> Result<&'a serde_json::Value, TypedefError>;
/// Get the discriminator size in bytes for a byte-offset discriminator.
pub fn discriminator_size(union_schema: &serde_json::Value) -> Result<usize, TypedefError>;
Byte-offset discriminator
The discriminator is a fixed-size integer at a known byte offset. The mapping keys
are stringified integers ("5", "6", "101").
Supported discriminator types: TypeDef:Uint8 (1 byte), TypeDef:Uint16 (2 bytes),
TypeDef:Uint32 (4 bytes). The discriminator value is read using the appropriate
endian-aware read function from data_access.
The variant struct starts at offset + discriminator_size.
Field-name discriminator
The discriminator is a named field within the struct. Its offset is computed like any
other field (by the OffsetMap or LayoutBuilder). The mapping keys are string
values matching the discriminator field's value.
The discriminator field's TypeDef:* kind determines how to read it:
TypeDef:String→ read a length-prefixed stringTypeDef:Uint8→ read a u8, stringifyTypeDef:Enum→ read a u32 index, map to string value from"enum"array
Variant resolution
resolve_variant() looks up the mapping key in the union's "mapping" object.
Mapping values may be inline schemas or $ref pointers. $ref pointers are resolved
against the schema's $defs (the $ref normalization in schema.rs ensures they
are full JSON Pointer paths).
What this does NOT include
- The offset computation for TUnion (that's in
offset_map.rsandlayout_builder.rs) - The
TypedefEnginestruct (that'sengine.rs)
Acceptance Criteria
read_byte_discriminator()reads discriminator at known byte offset- Supports
TypeDef:Uint8,TypeDef:Uint16,TypeDef:Uint32discriminator types - Discriminator value read with correct endianness
- Returns mapping key as string (e.g.,
"5"for SFTP Read packet) - Returns correct
variant_offset(offset + discriminator_size) read_field_discriminator()reads discriminator from named field at given offset- Supports
TypeDef:String,TypeDef:Uint8,TypeDef:Enumdiscriminator field types resolve_variant()looks up mapping key and returns variant schemaresolve_variant()resolves$refpointers to$defsresolve_variant()returnsTypedefError::Schemafor unknown mapping keysdiscriminator_size()returns correct size for each discriminator type- Returns
TypedefError::Accessfor buffer-too-short - Returns
TypedefError::Schemafor malformed discriminator annotations - No
unwrap()orexpect()on error paths - All public functions have doc comments
cargo check -p alknet-typedefsucceedscargo clippy -p alknet-typedefsucceeds with no warningscargo build --workspacestill succeeds
References
- docs/architecture/crates/typedef/data-access.md — TUnion dispatch section
- docs/architecture/crates/typedef/schema-layer.md — TUnion discriminators section
- docs/architecture/decisions/097-schema-annotations.md — ADR-097 §4 (TUnion discriminators)
- /workspace/alknet-typedef-poc/src/lib.rs — POC reference (parse_union_discriminator, read_union_discriminator)
Notes
This is a focused module for TUnion discriminator dispatch. The two discriminator kinds cover both protocol dispatch (SFTP type bytes, call protocol event types) and the typedef.ts string pattern. The mapping keys are always strings — integer discriminator values are stringified. The POC 2's
parse_union_discriminatorandread_union_discriminatorfunctions are good references.
Summary
To be filled on completion