gargamelle/encoding

Explicit typed JSON encoding, independently of structural definitions.

encode_json produces admitted JSON. encode additionally checks a stored Contract. Typed output boundaries are provided by gargamelle/boundary. Encoding and decoding need not be inverses. Getters and projections are trusted application functions: exceptions propagate as operational failures.

Types

Codec

opaque

An explicit encoder and its authoritative output Contract. Equal output types do not establish schema agreement; checked encoding enforces the Contract.

pub opaque type Codec(a)

A completed immutable encoding plan.

pub type Encoder(a) =
  Plan(a, Nil)

Encoding stops at its first failure. Runtime paths are JSON Pointers into the would-be encoded JSON, empty at the root. Field declaration errors identify the supplied key separately; their containing location is not yet known. Contract failures retain their own structural and semantic diagnostics. Callback exceptions and resource failures are not caught.

pub type EncodingError {
  InvalidValue(path: String, problem: ValueProblem)
  InvalidField(name: String, problem: FieldProblem)
  Admission(path: String, error: gargamelle.AdmissionError)
  Contract(gargamelle.ContractError)
}

Constructors

A rejected record field declaration. Construction has no containing JSON path.

pub type FieldProblem {
  DuplicateKey
  NonScalarKey
}

Constructors

  • DuplicateKey
  • NonScalarKey

Plan

opaque

An encoding plan under recursion environment r. Only completed encoders, Plan(a, Nil), can be executed. Construction references cannot escape as runnable encoders; recursive builders execute once.

pub opaque type Plan(a, r)

Record

opaque

A record encoder under construction, with explicit field getters.

pub opaque type Record(a, r)

Opaque environment supplied to a self-recursive encoding plan.

pub opaque type Recursive(a)

A rejected primitive encoding value.

pub type ValueProblem {
  NonFiniteNumber
  UnsafeInteger
  NonScalarString
}

Constructors

  • NonFiniteNumber
  • UnsafeInteger
  • NonScalarString

Values

pub fn array(encoder: Plan(a, r)) -> Plan(List(a), r)

Encode list elements in order, stopping at the first encoding failure.

pub fn boolean() -> Plan(Bool, r)

Encode a Boolean.

pub fn choice(
  first: Plan(a, r),
  second: Plan(b, r),
) -> Plan(Result(a, b), r)

Encode the selected Result branch. A projection can adapt an application sum type.

pub fn codec(
  encoder: Plan(a, Nil),
  contract: gargamelle.Contract(a),
) -> Codec(a)

Pair an encoder with a Contract without running either. This is an explicit pair, not encoder derivation or a claim that encoding and decoding are inverses.

pub fn codec_contract(codec: Codec(a)) -> gargamelle.Contract(a)

Inspect the exact Contract used by checked encoding, without callbacks.

pub fn contramap(
  encoder: Plan(a, r),
  get: fn(b) -> a,
) -> Plan(b, r)

Adapt an encoder with a trusted getter or projection. The callback runs once.

pub fn encode(
  codec: Codec(a),
  value: a,
) -> Result(gargamelle.VerifiedJson(a), EncodingError)

Encode once, then verify the stored Contract once. A check-free Contract validates without decoding; semantic requirements cause one decoding pass. Checks inspect that decoded output, which need not equal the original input.

pub fn encode_json(
  encoder: Plan(a, Nil),
  value: a,
) -> Result(gargamelle.Json, EncodingError)

Encode to admitted JSON without checking a definition or Contract. Encoding serializes an intermediate JSON tree and admits its text once. The result contains no certificate and claims no schema conformance.

pub fn field(
  record: Record(a, r),
  name: String,
  encoder: Plan(b, r),
  get: fn(a) -> b,
) -> Result(Record(a, r), EncodingError)

Add a required field with a getter. Duplicate and non-scalar keys fail construction.

pub fn finish(record: Record(a, r)) -> Plan(a, r)

Complete a record encoder. Getters execute in declaration order at encoding time.

pub fn json() -> Plan(gargamelle.Json, r)

Encode an already admitted Gargamelle Json value. This composes arbitrary metadata with typed field encoders; it does not certify a Contract. The usual serialization/admission path applies, preserving canonical JSON rather than original source formatting or object declaration order.

pub fn lift(encoder: Plan(a, Nil)) -> Plan(a, r)

Use a completed encoder inside a plan with any recursion environment.

pub fn null() -> Plan(Nil, r)

Encode Nil as JSON null.

pub fn nullable(encoder: Plan(a, r)) -> Plan(option.Option(a), r)

Encode None as JSON null and Some through the child encoder.

pub fn number() -> Plan(Float, r)

Encode a finite binary64 Float. Reject nonfinite values before serialization.

pub fn optional_field(
  record: Record(a, r),
  name: String,
  encoder: Plan(b, r),
  get: fn(a) -> option.Option(b),
) -> Result(Record(a, r), EncodingError)

Add a field omitted when its getter returns None. Some uses the child encoder.

pub fn record() -> Record(a, r)

Begin a record encoder. Construction invokes no getters.

pub fn recursive(
  build: fn(Plan(a, Recursive(a))) -> Result(
    Plan(a, Recursive(a)),
    EncodingError,
  ),
) -> Result(Plan(a, Nil), EncodingError)

Build a completed self-recursive encoder using an immutable body. The builder runs once. Recursion must descend through the input; immediate self-calls can diverge.

pub fn safe_integer() -> Plan(Int, r)

Encode an Int in the common safe-integer range. Reject out-of-range values.

pub fn text() -> Plan(String, r)

Encode a Gleam string. Admission rejects unpaired Unicode surrogates.

✨ Search Document