Changelog

View Source

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

0.2.1 - 2026-05-02

Changed

  • Performance: scalar parser options are now extracted at parser construction time rather than folded over the options map on every parse call. map/0 short-circuits to a plain is_map check. Median speedups (1M iter, OTP 28 / ARM macOS): binary/1, integer/1, float/1 with options ~5x; map/0 ~6x; list/1,2 over 100 elements ~2x; map/1,2 schemas 1.2-1.4x; map_of/2 1.4x. See test/zz_bench.erl.

Fixed

  • Doc type cross-references in README and CHANGELOG now use module-qualified syntax (zz:parser/1, zz:issues/0), eliminating ex_doc warnings on publish.

Tooling

  • Added mise format-check task (parity with CI's rebar3 fmt --check).
  • Added mise bench task and test/zz_bench.erl micro-benchmark harness.
  • Added CODE_OF_CONDUCT.md.
  • Split integer_typed_tests into pos_integer_tests, non_neg_integer_tests, neg_integer_tests for consistency with the one-file-per-function project convention.

0.2.0 - 2026-05-02

Added

  • zz:issues/1 flattens nested errors() into a flat list of issue maps with path and code. unknown_keys issues carry keys; no_match issues carry branches (one nested issue list per union branch).
  • New exported types: issue/0, issues/0, path/0.
  • parser/1 and optional_parser/1 types are now parameterized over the parsed value type, so zz:parse/2 reports the precise output type (e.g. parse(zz:integer(), X) -> result(integer())). parser/0 and optional_parser/0 remain as parser(term()) / optional_parser(term()) aliases for back-compat.
  • zz:lazy/1 defers parser construction so schemas can reference themselves (recursive shapes like trees and JSON-like values).
  • zz:map_of/2 validates a homogeneous map: every key parsed by the first parser, every value by the second. Key errors surface as {map_key, OriginalKey, InnerErrors}; value errors as {map_value, OriginalKey, InnerErrors}. zz:issues/1 flattens key errors as code => invalid_key issues with key and errors fields.
  • zz:char/0 validates a single Unicode codepoint (integer in 0..16#10FFFF). zz:char_list/0 validates a [char()], the old-style Erlang string representation.
  • zz:pid/0 validates a process identifier. zz:reference/0 validates a reference (e.g. from make_ref/0).
  • zz:iodata/0 validates iodata() (a binary or iolist()). zz:iolist/0 validates an iolist() only (binary input rejected).
  • zz:number/0 validates an integer or float.
  • zz:enum/1 validates that input equals (=:=) one of a list of values; fails with not_in_enum.
  • zz:nullable/1 accepts undefined alongside the wrapped parser's values. Sugar for union([literal(undefined), Z]).
  • zz:any/0 accepts any input, output equals input. Useful as a placeholder.
  • zz:bitstring/0,1 validates a bitstring, with optional min/max bit_size/1 constraints.
  • zz:function/0 validates any function. zz:function/1 validates a function with the given arity.
  • zz:pos_integer/0, zz:non_neg_integer/0, zz:neg_integer/0 validate the corresponding integer subtypes.
  • zz:format_issues/1 formats zz:issues/0 as a human-readable binary, one issue per line.

Changed

  • zz:tuple/1 now takes a tuple of parsers instead of a list, so the schema mirrors the shape it validates: zz:tuple({zz:integer(), zz:binary()}) instead of zz:tuple([...]).
  • Map errors are now tagged symmetrically: {map_value, K, [errs]} for value-parser failures (was {map, K, [errs]}) and {map_missing, K} for required-key absences (was {map, K, missing_key}). Pattern matches on the old shapes need to update.

Removed

  • zz:list/1 no longer accepts a list of parsers (the heterogeneous fixed-length form). Use zz:tuple/1 for fixed-length heterogeneous data. The length_mismatch error code is gone.

0.1.0 - 2026-05-02

Initial public release.

Added

  • Parser combinators: atom/0, binary/0,1, boolean/0, integer/0,1, float/0,1, list/0,1,2, literal/1, map/0,1,2, optional/1, tuple/0,1, union/1.
  • parse/2 entry point.
  • Map unknown_keys modes: strip, passthrough, strict.
  • Property-based tests via PropEr.
  • Public exported types: parser/0, optional_parser/0, result/1, errors/0, binary_options/0, integer_options/0, float_options/0, list_options/0, map_options/0, schema/0.
  • eqwalizer-clean: elp eqwalize-all reports no errors.