joetjen.net
EN DE
Data format

Conformance

DXN has four implementations and one specification. Two parts of the specification exist so that they can be compared exactly: a canonical text form for every value, and a category for every error. A shared suite of cases holds each implementation to both.

Format 1.0

The canonical form

Every value has exactly one canonical form: a .dxn rendering fixed down to the byte. Every implementation must be able to produce it, and parsing it gives back an equal value. It is also what defines when two map keys are the same.

  • No header, no comments, no @_; one space between items or entries, none inside the brackets, no commas, no newlines.
  • Maps and sets are written in canonical order: their entries’ or items’ canonical forms compared by Unicode code point. Ordered maps and structs keep their own order.
  • Nothing is normalised: 1.50M stays 1.50M, 2/4 stays 2/4.
  • Floats are written as the shortest digits that read back as the same double, with ECMAScript’s thresholds for when to use an exponent, .0 on whole numbers and no + in exponents.
  • Strings escape ", \, newline, tab and carriage return as \", \\, \n, \t, \r, every other control character as \x{…} in lowercase hex, and nothing else.
  • Times drop trailing zeros from their fraction; UUIDs are lowercase; bytes are standard base64 with padding; a duration that is all zero is PT0S; a struct carries (N) when its version is known.
%{b: 2, a: 1, "z" => 3}
%{"z" => 3 a: 1 b: 2}
[1e3 1e21 1.5e-7 0.000001 -0.0 1.50M 2/4 ~T[12:30:00.500] @duration "P0D"]
[1000.0 1.0e21 1.5e-7 0.000001 -0.0 1.50M 2/4 ~T[12:30:00.5] @duration "PT0S"]

Error categories

Implementations report errors in their own way, but every error a reader, writer or schema compiler raises belongs to exactly one category, and the implementation must expose it on the error value. Categories are compared exactly; messages are not part of the specification.

CategoryRaised when
syntaxtext does not parse
binarya .dxnb document is malformed: magic, version, a tag’s payload
key/not-alloweda map or extra-field key has a type that may not be a key
encode/unsupporteda host value has no DXN meaning, or no form in the text being written
schema/compilea .dxns document is not a valid schema
schema/duplicate-versiona name and version are loaded twice
schema/not-loadeda replace names a version that is not loaded
schema/unknown-versiona struct’s version is older than the latest loaded and not loaded itself
schema/no-materializeran older version arrives and no materializer is registered
schema/field-counta positional struct has the wrong number of items for its version
schema/missing-fielda required field is absent, or a positional form has no value for an optional field without a default
schema/type-mismatcha field’s value does not match its declared type
schema/undeclared-fielda strict decode meets a field the schema does not declare
schema/shadowed-fieldan extra field has the name of a declared field
schema/materializera materializer refuses, or returns a value the latest schema rejects
schema/version-disciplinethe compatibility check finds changed content under the same version, or a version going down

The conformance suite

The Dextrin Conformance Suite is a set of cases, each naming an operation, its input and the one outcome it expects: a canonical form, exact bytes, a document’s text or an error category. Its cases cover scalars, floats, map keys, structs, extra fields, schemas, binary and documents. Each implementation ships an adapter that answers a batch of cases — in dextrin, mix dextrin.conformance REQUEST ANSWER — and every answer is compared exactly.

Requests and answers are JSON, and values under test stay DXN text or .dxnb bytes, so the suite depends on no implementation of DXN — not even one of the four. It lives in the Praxis workspace for now and is meant to move to a repository of its own.