Tay.Storage.Record (tay v0.7.0)

Copy Markdown View Source

Pure Tay v1 physical framing and integrity codec.

The public contract is docs/storage.md: a 24-byte header, 28-byte overhead, big-endian integers, CRC32C over header bytes 0..19 and over those bytes followed by the opaque payload, and a 16 MiB hard limit.

Every type in 1..254 and schema in 1..255 is physically valid. Success does not establish sequence continuity, semantic acceptance, or an applied event. A physical cursor is not an applied replay checkpoint. Those checks belong to later layers, not this codec.

Decoding examines one record at offset zero and returns the exact remainder only on success. Every other result consumes nothing. Incomplete data is only a parse classification, never permission or a recommendation to repair. No payload interpretation, I/O, processes, or sequence allocation occurs.

Summary

Functions

Decodes one physical record, leaving all trailing bytes unchanged.

Encodes a physical record; all primitive fields are checked before domain rules.

Types

corrupt_reason()

@type corrupt_reason() ::
  domain_reason() | :invalid_magic | :header_checksum | :record_checksum

decode_result()

@type decode_result() ::
  {:ok, t(), binary()}
  | {:incomplete, :header}
  | {:incomplete, :payload | :checksum, metadata()}
  | {:error, {:corrupt, corrupt_reason()}}
  | {:error, {:unsupported, unsupported_reason()}}
  | {:error, {:resource_limit, non_neg_integer(), non_neg_integer()}}
  | {:error, {:invalid_argument, :input}}
  | {:error, {:invalid_options, option_error()}}

domain_reason()

@type domain_reason() ::
  {:invalid_format, 0}
  | {:reserved_type, 0 | 255}
  | {:invalid_schema, 0}
  | {:invalid_sequence, 0}
  | {:payload_length_exceeds_format, non_neg_integer(), 16_777_216}

encode_result()

@type encode_result() ::
  {:ok, binary()}
  | {:error, {:invalid_argument, :record}}
  | {:error, {:invalid_record, domain_reason() | {:field, primitive_field()}}}
  | {:error, {:unsupported, unsupported_reason()}}

metadata()

@type metadata() :: %{
  format_version: 1,
  record_type: 1..254,
  flags: 0,
  payload_schema_version: 1..255,
  sequence: 1..18_446_744_073_709_551_615,
  payload_length: 0..16_777_216,
  record_bytes: 28..16_777_244,
  available_bytes: non_neg_integer(),
  missing_bytes: pos_integer()
}

option_error()

@type option_error() ::
  :not_keyword
  | :duplicate_keys
  | :unknown_keys
  | :invalid_max_decode_payload_bytes

primitive_field()

@type primitive_field() ::
  :format_version
  | :record_type
  | :flags
  | :payload_schema_version
  | :sequence
  | :payload

t()

@type t() :: %Tay.Storage.Record{
  flags: 0,
  format_version: 1,
  payload: binary(),
  payload_schema_version: 1..255,
  record_type: 1..254,
  sequence: 1..18_446_744_073_709_551_615
}

unsupported_reason()

@type unsupported_reason() :: {:format, 2..255} | {:flags, 1..255}

Functions

decode(input, options \\ [])

@spec decode(term(), term()) :: decode_result()

Decodes one physical record, leaving all trailing bytes unchanged.

The only option is :max_decode_payload_bytes (0..16_777_216, default 16_777_216). This is a resource budget, not an insertion or format limit. A resource error permits retry with adequate resources at the same position.

encode(record)

@spec encode(term()) :: encode_result()

Encodes a physical record; all primitive fields are checked before domain rules.