# Changelog

## v0.7.0 - 2026-10-26

### Removed

- The `:decoder_sources` option. Generated helpers are typed against the
  reference `Decoder`, whose method signatures a crate's own keeps.
- The `:sparse_messages` option. Sparse message decoders always use one table
  of their fields, shared with skip decoders when both are generated, which is
  what `:descriptor` did; `:match` generated the same Rust another way.
- Unknown options raise instead of being ignored.

### Changed

- The generator's helper Rust comes from ordinary RustQ modules, included whole
  per feature, instead of modules built at generation time and lists of the
  functions to take from them. Full and sparse decoders share their primitive
  readers, enum decoding, and field reading, and `KiwiDecodeFn` replaces
  `KiwiSparseDecodeFn` and `KiwiFullDecodeFn`. The skip helpers are one module,
  `KiwiCodec.RustlerGenerator.Skip.Helpers`, which RustQ code calling them names
  instead of `Skip.ValueHelpers`. This needs RustQ 1.0.0-rc.19.

- The record feature writes each definition once, as a row of one
  `kiwi_records!` call: its fields and enum values one per line. The macro,
  in the record runtime, expands to the definition table and the
  `kiwi_record_definitions` and `kiwi_records` constants as before, which
  the generator used to write out separately, one table field per line.
  Figma's schema generates about 630 KB less Rust.

## v0.6.0 - 2026-10-25

### Changed

- The constants naming each definition's fields and enum values are associated
  constants of a type per definition, `kiwi_records::NodeChange::FILL_PAINTS`,
  instead of a module per definition, `kiwi_records::node_change::FILL_PAINTS`.
  Rust code naming them changes accordingly.
- RustQ code reaches them through `KiwiCodec.RustlerGenerator.Records`:
  `Records.NodeChange.FILL_PAINTS` and `Records.Definitions.NODE_CHANGE`, in a
  module that aliases it, with no `defrustmod` of its own. This needs RustQ
  1.0.0-rc.17.

## v0.5.1 - 2026-10-25

### Changed

- `KiwiCodec.RustlerGenerator.Records` provides the record runtime to RustQ.
  RustQ code that works with records names the module through `alias` and
  writes `Records.kiwi_record()` in its specs, instead of reading the runtime's
  Rust file from the dependency's directory. The runtime is `templates/records.rs`. This needs RustQ 1.0.0-rc.16.

## v0.5.0 - 2026-10-24

### Added

- `KiwiCodec.RustlerGenerator.Decoder` documents the `Decoder` generated
  decoders read with, and ships `decoder.rs`, a complete one. The generator
  reads its method signatures unless `:decoder_sources` names another
  `Decoder`, so every feature knows which reads return a `NifResult`.
- Projects that depend on KiwiCodec can use `KiwiCodec.RustlerGenerator`.
  RustQ is an optional dependency, and the generator compiles wherever it is
  available, such as a project's development and test builds; it used to
  compile only in KiwiCodec's own, so projects loaded its sources themselves.
- `KiwiCodec.Schema.Token` has a `kind`: `:identifier`, `:integer`,
  `:symbol`, or `:eof`.

### Changed

- The docs have a Native decoders guide covering each generator feature,
  entrypoints, and the `Decoder`. The generator architecture guide is now
  Internals, for people changing KiwiCodec, and the module groups separate the
  public API from internals.
- The schema tokenizer reads with binary patterns rather than a regular
  expression, and is about 14 times faster on Figma's schema. Tokens,
  positions, and errors are unchanged.
- Skip and sparse helpers are always built from `Decoder` metadata. Without
  `:decoder_sources`, they used to come from a separate set of helpers that
  did not know which reads could fail.
- Item macro rows in generated Rust separate their values with commas, as
  RustQ 1.0.0-rc.14 writes them.
- Records name a definition whose name is a Rust keyword with a raw
  identifier, such as `kiwi_records::r#type`, rather than appending `_` from a
  list of keywords that missed `gen`, `try`, and others.
- Generated Rust builds on rustler 0.37 to 0.39. It used to call
  `rustler::wrapper`, which rustler 0.39 removed.
- Require RustQ 1.0.0-rc.14 for code generation.

### Removed

- `RustlerGenerator.RustExpr.ident/1` and `indent/2`, and
  `RustlerGenerator.Skip.field_expr/2`. `RustExpr.primitive/1` returns RustQ
  AST rather than Rust source.

### Fixed

- The `:full` feature, the default, generates Rust that compiles and decodes
  as `KiwiCodec.decode/2` does. Its entrypoints moved the decoder they then
  finished, its message macro called an undefined function, its reads were
  not propagated with `?`, its strings were read without `env`, and a float
  that is infinite or NaN raised instead of decoding to an atom.
- Generating both sparse and skip decoders without `:decoder_sources` defined
  `kiwi_skip_descriptor_kind` twice, and skip decoders alone with
  `:decoder_sources` called it without defining it.
- A schema name that is not a Rust identifier fails where it is rendered,
  rather than having its other characters replaced with `_`, which could give
  two names the same Rust name.

## v0.4.0 - 2026-10-23

- Add the `:unknown_fields` Rustler generator option. `:runtime_schema` makes
  generated message decoders skip fields the compiled schema does not define,
  using a `KiwiRuntimeSchema` read from the schema that accompanies the data, so
  data written with a newer, compatible schema decodes instead of failing with
  `BadArg`. The default, `:error`, keeps rejecting such fields.
- Route every generated message decoder's unknown fields through one
  `kiwi_unknown_field` helper, and pass full message decoders their definition
  name.
- Accept a `:schema` option in `KiwiCodec.decode/3` to skip message fields the
  generated modules do not define, using the schema the data was written with.
- Add `KiwiCodec.SchemaInterpreter.skip_message_field/4`.
- Add the `:records` Rustler generator feature. It decodes Kiwi data into
  native records Rust code can read, change, and share without building Elixir
  terms, then encodes them as the sparse maps generated decoders return,
  optionally only some fields. Generated constants name each definition, field,
  and enum value; records have typed getters and helpers that update nested
  records and scalar, string, enum, and float-array fields. See
  `KiwiCodec.RustlerGenerator.Records`.
- Sparse decoders intern their module and field-name atoms once instead of for
  every map they build, which took two thirds of the time decoding large files.
- Require RustQ 1.0.0-rc.13 for code generation.
- Rename the Rustler generator's skip, sparse, and full decoder helpers by
  family: `RustlerGenerator.SkipHelpers`, `SkipValueHelpers`, and
  `SkipDescriptor` are `RustlerGenerator.Skip.Helpers`, `Skip.ValueHelpers`,
  and `Skip.Descriptor`; `SparseHelpers` is `Sparse.Helpers`; and
  `FullDecoderHelpers` is `Full.Helpers`.

## v0.3.1 - 2026-07-18

- Compile the RustQ-backed Rustler generator only in development and test
  environments, keeping production codec consumers free of RustQ and its
  development-tool dependency graph.
- Continue shipping the Rustler generator source for development-time native
  generation while keeping the production runtime package limited to the Kiwi
  codec and schema APIs.
- Remove the unused Jason dependency from the production package.

## v0.3.0 - 2026-07-17

- Restore the required slice borrow for match-backed sparse field tables when
  decoder source metadata is enabled.
- Hide internal Rust-only helper types from ExDoc type-reference rendering.
- Add reusable prepared runtime schemas with indexed definition, message-field,
  and enum lookup for repeated `SchemaInterpreter` calls.
- Replace the timer-loop codec benchmark with Benchee coverage for small and
  256-field sparse/dense static and interpreted codecs, including allocation
  measurements.
- Clarify Rustler generator architecture docs now that compact decoder macros
  are RustQ-authored rather than raw Rust heredoc escape boundaries.
- Deduplicate Rustler generator skip descriptor selection and remove exact clone
  findings from the generator helper modules.
- Add optional `decoder_sources` metadata for RustQ-authored skip helpers.
- Emit Rustler macro prelude helpers only for requested generator features.
- Add opt-in descriptor-backed sparse message generation with
  `sparse_messages: :descriptor`.
- Move sparse primitive value helpers, descriptor scanning, descriptor dispatch,
  and sparse descriptor declarations into RustQ-authored `defrust` / `@type`
  support.
- Author the sparse message descriptor macro with item-generating
  `defrustmacro` and compact `repeat` macro-template support.
- Share descriptor field inventories between sparse and skip message decoders
  when both descriptor sparse and skip features are generated.
- Author sparse enum and sparse struct descriptor decoding with RustQ-authored
  `defrust` helpers and item-generating `defrustmacro`.
- Avoid emitting raw match-backed sparse/skip message macros when decoder-source
  descriptor sparse generation does not use them.
- Author decoder-source skip struct decoders with RustQ-authored `defrust`
  helpers and item-generating `defrustmacro`.
- Replace active shared sparse/skip descriptor `kiwi_skip_kind!` token macro use
  with explicit descriptor metadata and RustQ-authored enum construction.
- Move descriptor-backed skip message scanning into RustQ-authored `defrust`
  helpers with sorted field lookup.
- Generate skip descriptor function, enum, and field declarations from RustQ
  type metadata when decoder sources are available.
- Collapse the separate sparse bytes descriptor mode into ordinary `one`
  descriptor mode.

## v0.2.2 - 2026-06-28

- Centralize primitive Rustler decoder metadata.
- Compact generated skip decoders.
- Deduplicate sparse enum decoders when full enum decoders are generated.
- Compact generated enum decoders.
- Remove the unused Rustler decoder macro path.
- Update RustQ dependency to `~> 0.8.2`.

## v0.2.1 - 2026-06-26

- Generate Rustler decoders through shared Rust macros to reduce repeated generated source.
- Add generic Rustler sparse and skip decoder families for projection-oriented native backends.

## v0.2.0 - 2026-06-26

- Delegate LEB128/ZigZag integer encoding to the `varint` package while keeping Kiwi-specific range and error handling.
- Replace vague `FieldProps`/`MessageProps` modules with `KiwiCodec.Metadata` and `KiwiCodec.Metadata.Field`.
- Rename the Kiwi variable-length float wire module to `KiwiCodec.Wire.VarFloat`.
- Rename generated module metadata API from `__kiwi_props__/0` to `__kiwi_metadata__/0`.
- Split Rustler generator naming, selection, helper splice, and decoder macro concerns into dedicated modules.
- Rename generated Elixir source rendering from `KiwiCodec.Generator` to `KiwiCodec.ModuleGenerator`.
- Clarify generated-codec and runtime helper names around definitions, wire fields, and wire types.
- Replace caller-owned Rustler templates with `KiwiCodec.RustlerGenerator.source/2` for complete generated Rust source.
- Centralize Kiwi primitive type metadata in `KiwiCodec.PrimitiveType`.
- Rename schema runtime interpretation to `KiwiCodec.SchemaInterpreter`.
- Split vague `KiwiCodec.Compiler` responsibilities into `KiwiCodec.ModuleCompiler` and `KiwiCodec.FileGenerator`.
- Split parsed schema members into `KiwiCodec.Schema.Field` with `id` and `KiwiCodec.Schema.EnumVariant` with `value`.
- Replace overloaded parsed schema definitions with `KiwiCodec.Schema.Enum`, `KiwiCodec.Schema.Struct`, and `KiwiCodec.Schema.Message`.
- Extract compact binary schema type-reference encoding into `KiwiCodec.Schema.Binary.TypeIndex`.
- Split Rustler generator definition emission, field expressions, and entrypoints into dedicated modules.
- Split generated-module metadata, shape, and typespec emission out of `KiwiCodec.DSL`.
- Split schema tokenization and validation out of `KiwiCodec.Schema.Parser`.
- Group published HexDocs modules without hiding source documentation.
- Refresh README installation instructions for the latest released version.
- Infer Rustler generator entrypoint names and selected definitions from requested schema definitions.
- Render Rustler generator source prelude with RustQ AST imports instead of raw Rust strings.
- Infer Rustler generator entrypoints from matching exported NIF stub modules.
- Infer Rustler generator entrypoints from explicit NIF stub metadata modules without loading Rustler modules.
- Document inferred Rustler entrypoints and NIF stub metadata usage.

## v0.1.1 - 2026-06-25

- Reject unexpected characters while parsing `.kiwi` schema text.
- Normalize malformed binary schema failures to `KiwiCodec.DecodeError`.
- Document internal modules and Rustler generator template requirements.
- Reuse RustQ Rustler helper splices for generated native struct term construction.

## v0.1.0 - 2026-06-25

- Initial Kiwi wire codec, schema parser, runtime interpreter, DSL, and code generator.
