Skip to content

Add optional fields and variable-length field support#7

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-optional-variably-sized-fields
Draft

Add optional fields and variable-length field support#7
Copilot wants to merge 3 commits intomainfrom
copilot/add-optional-variably-sized-fields

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 2, 2026

The library had no way to express fields that are conditionally absent or whose size is determined at runtime. This adds three composable, declarative primitives that fit naturally alongside the existing field factories.

optional(descriptor, presence) — new in fields.ts

Wraps any field descriptor to return T | null when the field is absent. Two strategies:

  • Sentinel: optional(u16(0), { sentinel: 0xffff })null when stored value equals sentinel (Object.is); writing null stores the sentinel.
  • Predicate: optional(u32(4), (dv) => (dv.getUint8(0) & 0x01) !== 0)null when predicate returns false; writing null is a no-op.

Writability of the result mirrors the wrapped descriptor: writable ↔ input has a setter, read-only ↔ input is read-only (e.g. substruct, typedArray). Enforced via TypeScript overloads.

const Packet = defineStruct({
  flags:   u8(0),
  // present only when bit 0 of flags is set
  payload: optional(u32(4), (dv) => (dv.getUint8(0) & 0x01) !== 0),
  // absent when value is 0xFFFF
  tag:     optional(u16(8), { sentinel: 0xffff }),
})

Dynamic-length string() overload — fields.ts

string(offset, { length: propertyName | (dv) => number }) — read-only string whose byte length is resolved at access time from another field or an arbitrary DataView function.

const Frame = defineStruct({
  name_len: u8(0),
  name:     string(1, { length: "name_len" }),          // via property
  // or:
  data:     string(1, { length: (dv) => dv.getUint8(0) }), // via function
})

Write support is intentionally omitted: writing a variable-length string requires coordinating the length field, which is better expressed with fromDataView.

Function-based length in typedArray()fields.ts

The length option now additionally accepts (dv: DataView) => number, complementing the existing number | string | undefined forms. Fully backward compatible.

const Blob = defineStruct({
  count:  u8(0),
  values: typedArray(4, { species: Float32Array, length: (dv) => dv.getUint8(0) }),
})

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.deno.land
    • Triggering command: /usr/bin/curl curl -s REDACTED (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] Propose design for optional and variably sized fields in API Add optional fields and variable-length field support Apr 2, 2026
Copilot finished work on behalf of rotu April 2, 2026 22:39
Copilot AI requested a review from rotu April 2, 2026 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants