Dextrin.Schema.TypeExpr (Dextrin v0.1.0)

Copy Markdown View Source

Internal, compiled representation of a .dxns type expression — the 13-form vocabulary (any, primitive, reference, list-of, set-of, tuple-of, map-of, enum, one-of, all-of, nilable, refine, struct) Dextrin.Schema.Compiler turns a parsed .dxns value into, and what matches?/2 below checks a decoded value against. This vocabulary is fixed, not extensible from outside an actual library change — what schema authors extend instead is composing these forms into a reusable named type (see Dextrin.Schema.Compiler's own moduledoc), which needs no new form at all.

Summary

Functions

Whether value matches type — shared by both decode (Dextrin.Schema.Validator.materialize/4) and encode-time validation (Dextrin.Schema.Validator.validate_for_encode/3): the same recursive check, the same function, for both directions.

Types

t()

@type t() ::
  :any
  | {:primitive, String.t()}
  | {:reference, String.t()}
  | {:list_of, t()}
  | {:set_of, t()}
  | {:tuple_of, [t()]}
  | {:map_of, t(), t()}
  | {:enum, [term()]}
  | {:one_of, [t()]}
  | {:all_of, [t()]}
  | {:nilable, t()}
  | {:refine, t(), %{optional(String.t()) => term()}}

Functions

matches?(type, value, registry \\ nil)

@spec matches?(t(), term(), Dextrin.Registry.t() | nil) :: boolean()

Whether value matches type — shared by both decode (Dextrin.Schema.Validator.materialize/4) and encode-time validation (Dextrin.Schema.Validator.validate_for_encode/3): the same recursive check, the same function, for both directions.

{:reference, name} checks the originating schema's name, not the value's own shape — which is how it correctly rejects a materialized value that satisfies its own schema but is the wrong one for this field. Three sources carry that name: an opaque, unregistered Dextrin.Struct carries its own wire name directly; a value that went through a registered schema (decode or encode -time validation alike) carries it via Validatedmaterialize/4 wraps every result in one regardless of materializer shape, and encode-time validation wraps every recognized struct the same way before checking it (Dextrin.Schema.Validator's internal wrap_and_check helper), specifically so this one function can check both without needing two implementations. The third, encode-only source: registry (nil for decode, which never needs it) lets a real, unwrapped application struct's __struct__ be checked against whatever module was registered for name (Dextrin.Registry.put_struct_module/3) — needed only for a struct that turned out to have no schema of its own to be wrapped by. A plain map (no name, no __struct__) or an unregistered name has nothing to check and is trusted, either way.