Reef schemas

reef is the fixed-width schema vocabulary — the structural barrier between your data and the raw buffer. Every helper mints a schema that is both the validator and the binary layout spec: one declaration, no second place for the layout to drift.

row.schema.ts
import { reef } from '@atolljs/core';

const incidentRow = reef.object({
  id:         reef.u32(),          // 4 bytes — uint32 domain
  severity:   reef.int(0, 3),      // 1 byte  — domain 0..3, narrowest covering kind
  alarms:     reef.u16(),          // 2 bytes
  open:       reef.boolean(),      // flag byte
  site:       reef.string(10),     // 10 inline UTF-8 bytes — budget IS the schema
  openedAt:   reef.u64(),          // 8-byte bigint
});

// The schema validates AND lays out — a million of these become a flat
// array of structs under field.list:
field.list({ schema: incidentRow, count: 1_000_000 });

The vocabulary

Only helpers whose schemas can promise a byte width exist — there is no reef.number() because an unbounded width can't compile to a fixed layout. Ten scalar kinds, one spelling each; the format-based kinds are tagged directly and bounded ints cover the rest.

HelperStorageDomain
reef.i8() · reef.u8()1 byte−128..127 · 0..255
reef.i16() · reef.u16()2 bytes−32768..32767 · 0..65535
reef.i32() · reef.u32()4 bytesint32 · uint32
reef.i64() · reef.u64()8 bytesint64 · uint64 (bigint)
reef.f32() · reef.f64()4 / 8 bytesfloat
reef.int(min, max)narrowest covering kindmin..max
reef.boolean()flag byte—
reef.string(bytes)bytes inline UTF-8byte length ≤ bytes
reef.object(shape)fixed record — member widths summed + alignedper member
reef.array(el)bounded via .max(n) / .length(n)per element

reef.int(0, 3) declares a domain — the compiler picks the narrowest covering width (u8 → i8 → u16 → i16 → u32 → i32). Writes of 9 still reject: bounds can be stricter than storage, never looser.

Where schemas plug in

Field factorySchema it takesLayout it derives
field.list({ schema, count })reef.object(...)record array — readAt(i)/writeAt(i) are pointer arithmetic
field.object({ schema })reef.object(...)one inline record — byteLength derived, no maxBytes
field.array({ schema })reef.array(el).max(n)count header + n inline elements
field.string({ schema })reef.string(n)length header + n inline UTF-8 bytes

Your own zod works too

Classic zod and zod/mini schemas are accepted anywhere reef schemas are — the compiler duck-types on the zod-style _zod.def, so z.uint32(), z.number().int().min(0).max(3), and z.string().meta({ bytes: n }) compile identically:

import { z } from 'zod';

reef.object({
  id:    z.uint32(),                          // classic format → 'u32'
  level: z.number().int().min(0).max(3),      // bounds → narrowest kind ('u8')
  tag:   z.string().meta({ bytes: 8 }),       // meta → 8 inline bytes
  ref:   reef.u16(),                          // reef members mix the other way too
});

Reef schemas are minted by a vendored engine — no zod dependency ships, and the classic chain spellings stay attached: .refine(), .meta(), .min()/.max(), .length(), .int()all work, and the compiler reads the final schema. Two honest limits: they aren't instanceof z.ZodType (check s._zod.def + .parse instead), and they can't be members of a real z.object/z.array — zod dispatches member parsing through its own internals; when a wire schema needs a reef value, compose with reef.object/reef.array.

What the reef rejects

Compile fails loudly rather than guessing a width — unbounded strings (no bytes meta), unbounded arrays, nested objects inside a record, and types with no fixed encoding (z.date(), z.enum(), unions) all throw at defineSharedMemory/field.* declaration time. Dynamic payloads aren't banned — they go through the codec escape hatch: field.object({ maxBytes }) encodes arbitrary JSON-shaped values with the contract's codec, schema optional.

Bundle note: reef runs on a vendored schema engine — zod isn't an @atolljs/core dependency at all, and it's fully opt-in — no reef/listSchema import, no schema code in your bundle. See Bundle size & load and Shared memory.