docs: typed-output direction set — russh-sftp shape, (a) vs (b) fork
- branch 1 output contract targets typed Rust structs (no Value materialization): the kernel-fusion move, alkminer precedent - russh-sftp protocol-type shape as target (plain structs, field order = decode order, shared cursor codec core) - fork: (a) serde-derive + generic Deserializer (interop) vs (b) generated direct codecs (zero overhead, the 72ns shape) - follow-up #1 sharpened: typed-output POC renders Packet both ways, benchmarks against the raw-decode baseline
This commit is contained in:
1 parent
b86dadcf77
commit
a52c8a6b37
1 file changed
+47
-4
@@ -71,6 +71,47 @@ Interpretation:
|
||||
is where the 20x-scale gains live; that is an output-contract
|
||||
decision for Phase 1 (see §Follow-ups).
|
||||
|
||||
**Typed output direction set 2026-09-08 (POC debrief): branch 1's
|
||||
output contract should be typed Rust structs, in the russh-sftp
|
||||
protocol-type shape.** The decomposition above made the `Value`
|
||||
contract's ceiling visible; the next target is to generate the
|
||||
hand-rolled shape itself — helpers + templates producing direct
|
||||
wire codecs over typed structs, no `Value` anywhere. Conceptually
|
||||
the alkminer-v1 kernel-fusion move: the schema compiles to native
|
||||
code instead of driving a runtime walk.
|
||||
|
||||
Target shape (`/workspace/russh-sftp/src/protocol/*.rs` precedent):
|
||||
per-type plain structs with named fields (`pub struct Close { pub
|
||||
id: u32, pub handle: String }` + macro impls), field order = decode
|
||||
order, one shared cursor-based codec core. BAST kinds map to Rust
|
||||
types cleanly (`uint32`→`u32`, `string`→`String`, struct→struct,
|
||||
TUnion→enum). russh-sftp rides serde derive with a generic wire
|
||||
`Deserializer`; BAST's per-field endianness and TUnion byte-
|
||||
discriminators don't fit serde's derive directly, so the typed path
|
||||
forks:
|
||||
|
||||
- **(a) serde-derive architecture** (russh-sftp's): one generic
|
||||
`Deserializer` + per-type `Deserialize` impls — derived where the
|
||||
wire is homogeneous; generated impls (or endian newtype wrappers)
|
||||
where it isn't; TUnion → generated enum with a custom impl. Pro:
|
||||
ecosystem interop (`serde` consumers, `de::from_bytes::<T>`
|
||||
ergonomics). Con: serde machinery overhead vs direct code; the
|
||||
endian/union cases get wrapper-heavy.
|
||||
- **(b) generated direct codecs**: `fn decode(buf: &mut Cursor)
|
||||
-> Result<Packet, GenError>` per type — literally the hand-rolled
|
||||
72 ns shape, template-generated. Pro: zero overhead, full
|
||||
control; the POC's error-returning cursor helpers carry over
|
||||
directly. Con: serde interop for typed output needs a bridge (or
|
||||
a later feature generating impls).
|
||||
|
||||
Either way, the benchmark target is the raw-decode baseline (72 ns):
|
||||
typed generated decode should land within striking distance,
|
||||
recovering the ~20x claim at the typed contract. This is branch 1's
|
||||
output-contract ADR (Phase 1's biggest), now with a concrete target
|
||||
shape and two implementation strategies. A typed-output POC
|
||||
(follow-up #1) can resolve (a) vs (b) cheaply by rendering the same
|
||||
Packet schema both ways and re-benchmarking.
|
||||
|
||||
## Parity semantics the generated code must reproduce
|
||||
|
||||
Discovered by exercising the interpreter, all pinned in the parity
|
||||
@@ -206,10 +247,12 @@ a design constraint.
|
||||
|
||||
## Follow-ups (Phase 1 input)
|
||||
|
||||
1. **Output contract ADR** — `Value`-materializing vs typed-struct
|
||||
output. The POC + benchmark shows Value-shape is mature (near
|
||||
hand-rolled parity) and typed output is where the 10–20x lives.
|
||||
This is the biggest Phase 1 ADR.
|
||||
1. **Output contract ADR** — typed-struct output (russh-sftp shape,
|
||||
§"Typed output direction") vs `Value`-materializing. The typed
|
||||
direction is set; the ADR decides the serde-derive (a) vs direct
|
||||
codec (b) fork. A typed-output POC resolves it by rendering the
|
||||
Packet schema both ways and re-benchmarking against the 72 ns
|
||||
raw-decode baseline.
|
||||
2. **Typed error shape for generated code** (F-2) — mirror
|
||||
`AlkTypeError` variants without the alktype dep, or a
|
||||
generated-code-local enum.
|
||||
|
||||
Reference in new issue
Block a user