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
opaqueAn 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)
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
-
InvalidValue(path: String, problem: ValueProblem) -
InvalidField(name: String, problem: FieldProblem) -
Admission(path: String, error: gargamelle.AdmissionError) -
Contract(gargamelle.ContractError)
A rejected record field declaration. Construction has no containing JSON path.
pub type FieldProblem {
DuplicateKey
NonScalarKey
}
Constructors
-
DuplicateKey -
NonScalarKey
OutputBoundary
opaqueA 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
opaqueAn 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
opaqueA record encoder under construction, with explicit field getters.
pub opaque type Record(a, r)
Recursive
opaqueOpaque 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 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 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 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.