Dextrin.Schema.Validator (Dextrin v0.1.0)

Copy Markdown View Source

Checks a value's fields against a Dextrin.Schema.Compiled schema (required/closed/forbidden/refine) — shared by decode (materialize/4, which also produces a materialized result) and encode-time validation (validate_for_encode/3/validate_tree_for_encode/2, which never transforms value). Both directions reuse the exact same resolve_fields/3/TypeExpr.matches?/3 field-checking — encode's own values are wrapped in the same internal Dextrin.Schema. Validated marker decode already uses, via wrap_and_check/2, so there's one type-checking implementation, not two that could drift.

Enforcement is decode-time and fail-fast, with no lenient escape hatch to get the materialized value anyway — a violation is always an error, on the same channel an ordinary syntax error already uses.

Summary

Functions

Validates and materializes fields against compiled, using materializer if given. On success, the result is wrapped in a Validated (name: compiled.name) — internal bookkeeping so an outer schema's {:reference, name} field can verify this value's origin even after materialization; callers that aren't another schema check (the true top of decoding) must call Validated.strip/1 on the final result.

Checks value — ordinary Elixir data you're about to encode — against compiled. Never materializes; value itself is never transformed.

Walks value looking for every Dextrin.Struct or registered application struct anywhere in the tree and checks each one against its own schema, if the registry has one — regardless of what any enclosing field's declared type is, and recursing fully into whatever it finds (not just confirming type identity). Dextrin.encode/2/encode_binary/2 call this automatically (opt out with validate: false).

Types

fields()

@type fields() :: {:keyed, [{String.t(), term()}]} | {:positional, [term()]}

Functions

materialize(compiled, fields, materializer, registry)

Validates and materializes fields against compiled, using materializer if given. On success, the result is wrapped in a Validated (name: compiled.name) — internal bookkeeping so an outer schema's {:reference, name} field can verify this value's origin even after materialization; callers that aren't another schema check (the true top of decoding) must call Validated.strip/1 on the final result.

validate_for_encode(compiled, value, registry)

@spec validate_for_encode(Dextrin.Schema.Compiled.t(), term(), Dextrin.Registry.t()) ::
  :ok | {:error, String.t()}

Checks value — ordinary Elixir data you're about to encode — against compiled. Never materializes; value itself is never transformed.

validate_tree_for_encode(value, registry)

@spec validate_tree_for_encode(term(), Dextrin.Registry.t()) ::
  :ok | {:error, String.t()}

Walks value looking for every Dextrin.Struct or registered application struct anywhere in the tree and checks each one against its own schema, if the registry has one — regardless of what any enclosing field's declared type is, and recursing fully into whatever it finds (not just confirming type identity). Dextrin.encode/2/encode_binary/2 call this automatically (opt out with validate: false).