gargamelle/encoding

Explicit typed JSON encoding, independently of structural definitions.

encode_json produces admitted JSON. encode additionally checks a stored Contract, while send encodes through an authoritative JSON receiving 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

A typed producer path through an existing JSON receiving boundary. Its receiving Contract is authoritative; no second definition is stored.

pub opaque type OutputBoundary(a, response)

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 output_boundary(
  encoder: Plan(a, Nil),
  receiver: gargamelle.JsonBoundary(a, response),
) -> OutputBoundary(a, response)

Pair an encoder with an existing receiving boundary. Construction executes no callbacks. The receiver’s Contract is the sole acceptance authority.

pub fn output_contract(
  output: OutputBoundary(a, response),
) -> gargamelle.Contract(a)

Inspect the exact receiving Contract without exposing its private handler.

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 send(
  output: OutputBoundary(a, response),
  value: a,
) -> Result(response, EncodingError)

Encode once to unverified admitted JSON, then forward through the receiving boundary once. No checked encode is performed before forwarding. Invalid output invokes no handler; accepted output invokes it once. Handler Results remain nested, and callback exceptions remain operational failures.

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

Encode a Gleam string. Admission rejects unpaired Unicode surrogates.

✨ Search Document