Skip to content

[Tangent] Eliminate duplicate WithLength decoder family in CBOR.ts #159

@solidsnakedev

Description

@solidsnakedev

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    explorationInteresting paths and ideas to revisit

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions