v0.7.0 - 2026-10-26
Removed
- The
:decoder_sourcesoption. Generated helpers are typed against the referenceDecoder, whose method signatures a crate's own keeps. - The
:sparse_messagesoption. Sparse message decoders always use one table of their fields, shared with skip decoders when both are generated, which is what:descriptordid;:matchgenerated 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
KiwiDecodeFnreplacesKiwiSparseDecodeFnandKiwiFullDecodeFn. The skip helpers are one module,KiwiCodec.RustlerGenerator.Skip.Helpers, which RustQ code calling them names instead ofSkip.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 thekiwi_record_definitionsandkiwi_recordsconstants 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_PAINTSandRecords.Definitions.NODE_CHANGE, in a module that aliases it, with nodefrustmodof its own. This needs RustQ 1.0.0-rc.17.
v0.5.1 - 2026-10-25
Changed
KiwiCodec.RustlerGenerator.Recordsprovides the record runtime to RustQ. RustQ code that works with records names the module throughaliasand writesRecords.kiwi_record()in its specs, instead of reading the runtime's Rust file from the dependency's directory. The runtime istemplates/records.rs. This needs RustQ 1.0.0-rc.16.
v0.5.0 - 2026-10-24
Added
KiwiCodec.RustlerGenerator.Decoderdocuments theDecodergenerated decoders read with, and shipsdecoder.rs, a complete one. The generator reads its method signatures unless:decoder_sourcesnames anotherDecoder, so every feature knows which reads return aNifResult.- 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.Tokenhas akind::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
Decodermetadata. 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 missedgen,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/1andindent/2, andRustlerGenerator.Skip.field_expr/2.RustExpr.primitive/1returns RustQ AST rather than Rust source.
Fixed
- The
:fullfeature, the default, generates Rust that compiles and decodes asKiwiCodec.decode/2does. 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 withoutenv, and a float that is infinite or NaN raised instead of decoding to an atom. - Generating both sparse and skip decoders without
:decoder_sourcesdefinedkiwi_skip_descriptor_kindtwice, and skip decoders alone with:decoder_sourcescalled 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_fieldsRustler generator option.:runtime_schemamakes generated message decoders skip fields the compiled schema does not define, using aKiwiRuntimeSchemaread from the schema that accompanies the data, so data written with a newer, compatible schema decodes instead of failing withBadArg. The default,:error, keeps rejecting such fields. - Route every generated message decoder's unknown fields through one
kiwi_unknown_fieldhelper, and pass full message decoders their definition name. - Accept a
:schemaoption inKiwiCodec.decode/3to 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
:recordsRustler 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. SeeKiwiCodec.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, andSkipDescriptorareRustlerGenerator.Skip.Helpers,Skip.ValueHelpers, andSkip.Descriptor;SparseHelpersisSparse.Helpers; andFullDecoderHelpersisFull.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
SchemaInterpretercalls. - 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_sourcesmetadata 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/@typesupport. - Author the sparse message descriptor macro with item-generating
defrustmacroand compactrepeatmacro-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
defrusthelpers and item-generatingdefrustmacro. - 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
defrusthelpers and item-generatingdefrustmacro. - 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
defrusthelpers 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
onedescriptor 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
varintpackage while keeping Kiwi-specific range and error handling. - Replace vague
FieldProps/MessagePropsmodules withKiwiCodec.MetadataandKiwiCodec.Metadata.Field. - Rename the Kiwi variable-length float wire module to
KiwiCodec.Wire.VarFloat. - Rename generated module metadata API from
__kiwi_props__/0to__kiwi_metadata__/0. - Split Rustler generator naming, selection, helper splice, and decoder macro concerns into dedicated modules.
- Rename generated Elixir source rendering from
KiwiCodec.GeneratortoKiwiCodec.ModuleGenerator. - Clarify generated-codec and runtime helper names around definitions, wire fields, and wire types.
- Replace caller-owned Rustler templates with
KiwiCodec.RustlerGenerator.source/2for complete generated Rust source. - Centralize Kiwi primitive type metadata in
KiwiCodec.PrimitiveType. - Rename schema runtime interpretation to
KiwiCodec.SchemaInterpreter. - Split vague
KiwiCodec.Compilerresponsibilities intoKiwiCodec.ModuleCompilerandKiwiCodec.FileGenerator. - Split parsed schema members into
KiwiCodec.Schema.FieldwithidandKiwiCodec.Schema.EnumVariantwithvalue. - Replace overloaded parsed schema definitions with
KiwiCodec.Schema.Enum,KiwiCodec.Schema.Struct, andKiwiCodec.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
.kiwischema 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.