Files
2026-05-27 23:29:53 +01:00

6.4 KiB

Capability Spec Delta: bitpacker-streaming (bitpacker-stub-completion)

Package: @suaveplan/bitpacker-streaming Status: PROPOSED

Every requirement below carries a **Verified by:** line at authoring time.

ADDED Requirements

Requirement: StreamingBitPacker class

The package SHALL export StreamingBitPacker<T extends BitPackerSchema> extends EventEmitter matching upstream streaming.ts (L14-L406). The class SHALL expose packStream(data, options) and unpackStream(packed, options), both returning Promise<Uint8Array> (pack) / Promise<SchemaTypeToDataType<T>> (unpack). Both methods SHALL emit progress events as chunks complete and chunk events with the bytes of each completed chunk; chunk size SHALL come from options.chunkSize (default 1024).

Scenario: packStream round-trips through unpackStream

  • WHEN a 100 KiB object is packStream-ed and the result is unpackStream-ed under the same schema
  • THEN the unpacked value deep-equals the input

Scenario: progress events fire in chunk order

  • WHEN packStream is called on data that produces 8 chunks
  • THEN 8 progress events fire with { index, total: 8, percent } in monotonically increasing order; the final event has percent === 1

Scenario: chunk events carry chunk bytes

  • WHEN packStream runs with emitProgress: true
  • THEN each chunk event's payload is a Uint8Array whose concatenation equals the final return value byte-for-byte

Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"packStream / unpackStream round-trip preserves the value" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"emits progress events in monotonic chunk order" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"chunk events concatenate to the final byte output"


Requirement: chunkProcessor invoked per chunk

If options.chunkProcessor is supplied, the streaming bit-packer SHALL invoke it on each chunk before emitting / returning, awaiting the result. If the processor throws, packStream / unpackStream SHALL throw BitpackerError with code BITPACKER.STREAM_CHUNK_PROCESSOR_FAILED, chaining the original error.

Scenario: chunkProcessor mutates chunks before delivery

  • WHEN chunkProcessor is (chunk) => xor(chunk, 0xff) and the produced bytes are XOR'd back before unpack
  • THEN the round-trip succeeds

Scenario: chunkProcessor failure surfaces as coded error

  • WHEN chunkProcessor throws on chunk 3
  • THEN packStream rejects with BitpackerError code BITPACKER.STREAM_CHUNK_PROCESSOR_FAILED whose cause is the original error and context.chunkIndex === 3

Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"chunkProcessor mutates chunks before delivery" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"chunkProcessor failure surfaces as STREAM_CHUNK_PROCESSOR_FAILED"


Requirement: validateChunks gates pack/unpack on validation

When options.validateChunks is true, the streaming bit-packer SHALL run the underlying BitPacker.validate over the input (pack) or unpacked output (unpack) and reject before emitting if validation fails, throwing BitpackerError with code BITPACKER.STREAM_VALIDATION_FAILED.

Scenario: validation gate rejects malformed input

  • WHEN validateChunks: true and the input violates the schema (e.g. value out of u8 range)
  • THEN packStream rejects with BitpackerError code BITPACKER.STREAM_VALIDATION_FAILED AND no chunk events fire

Scenario: validation gate disabled by default

  • WHEN validateChunks is omitted
  • THEN packing proceeds without validation; encoder errors surface natively

Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"validateChunks: true rejects malformed input with STREAM_VALIDATION_FAILED" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"validateChunks default is false"


Requirement: AbortSignal propagation

packStream and unpackStream SHALL accept options.signal: AbortSignal. When the signal is already aborted at call time, the call SHALL reject immediately with BitpackerError code BITPACKER.STREAM_ABORTED. When abort fires mid-stream, the in-flight chunk SHALL complete and then the call SHALL reject with the same code; no subsequent chunks SHALL be processed or emitted.

Scenario: pre-aborted signal rejects immediately

  • WHEN signal.aborted === true at call time
  • THEN packStream rejects synchronously with BitpackerError code BITPACKER.STREAM_ABORTED

Scenario: mid-stream abort halts further chunks

  • WHEN abort() fires after the 2nd of 8 chunks completes
  • THEN chunks 3..8 do NOT emit chunk events and the promise rejects with BITPACKER.STREAM_ABORTED

Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"pre-aborted signal rejects immediately with STREAM_ABORTED" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"mid-stream abort halts further chunk emission"

MODIFIED Requirements

Requirement: Synchronous chunked helpers delegate to StreamingBitPacker

The existing packToChunks, unpackFromChunks, and unpackFromChunksAsync functions SHALL be preserved with their current signatures, but their implementation SHALL delegate to StreamingBitPacker so behavior stays synchronized. The async helper SHALL honour AbortSignal (already true today; pin behavior in test).

Scenario: packToChunks output equals StreamingBitPacker.packStream concatenation

  • WHEN the same data + schema is run through packToChunks and through packStream and the chunks of each are concatenated
  • THEN the byte-arrays are equal

Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"packToChunks delegates to packStream" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"unpackFromChunksAsync honours AbortSignal"