IntersectMBO / IntersectMBO/evolution-sdk
[Tangent] Eliminate duplicate WithLength decoder family in CBOR.ts
- Dominant language
- TypeScript
- Stars
- 22
- Forks
- 30
- Avg merge
- 5h 29m
- Merged PRs (30d)
- 12
Description
## What was discovered
CBOR.ts has two complete decoder implementations side-by-side: an offset-based family (\`decodeItemAt\`, \`decodeBytesAt\`, \`decodeArrayAt\`, …) and a slice-based family (\`decodeItemWithLengthSync\`, \`decodeBytesWithLengthSync\`, \`decodeArrayWithLengthSync\`, …). The slice-based family calls \`data.slice(offset)\` at every recursion, allocating a new \`Uint8Array\` for each nested item.
## Surfaced during
CBOR module review while preparing the \`bounded_bytes\` / \`BoundedBytes\` fix (PR for Conway CDDL compliance). Found during full read of CBOR.ts decoder section (~lines 1600–1900).
## Why it's worth exploring
For deeply nested PlutusData (constr with 5 levels, many fields), the slice-based path allocates hundreds of \`Uint8Array\` copies. The offset-based family is strictly better — it threads an integer offset through the call chain with zero allocation overhead. The two families are functionally equivalent. Deleting the \`WithLength\` family and routing its callers to the offset-based one removes ~200 lines and eliminates the O(n²) allocation pattern.
## What would be needed
1. Identify all callers of the \`WithLength\` family inside CBOR.ts
2. Route them to the offset-based equivalents (\`decodeItemAt\` etc.)
3. Delete the \`WithLength\` family
4. Run the full CBOR test suite (968 tests) to confirm no regression
5. Benchmark with a deeply nested PlutusData value to quantify the win (optional but useful)
## Context snapshot
Relevant section: \`packages/evolution/src/CBOR.ts\` ~lines 1600–1900.
The slice-based family:
\`\`\`typescript
const decodeItemWithLengthSync = (data: Uint8Array, options: CodecOptions): { item: CBOR; bytesConsumed: number } => {
// ... dispatches to decodeBytesWithLengthSync, decodeArrayWithLengthSync, etc.
// Each calls data.slice(offset) before recursing — one allocation per node
}
\`\`\`
The offset-based family (keeper):
\`\`\`typescript
const decodeItemAt = (data: Uint8Array, offset: number, options: CodecOptions): DecodeAtResult => {
// ... threads offset integer — zero allocation
}
\`\`\`
Both produce identical decoded values. The \`WithLength\` family exists as a legacy parallel path and has no unique capabilities the offset family lacks.
Contributor guide
Assessment
This issue has not been assessed yet.