WorkerLib - Elixir implementation of the cross-language serialization test framework.
FieldMap is a plain Elixir map with string keys. Struct fields are nested maps. list<struct> fields are lists of maps.
Worker setup
Build the worker as an escript:
escript: [main_module: MyWorker]Requires OTP 27 or newer. Older releases read stdin through a device that silently drops control characters, corrupting case data before a worker sees it.
Summary
Functions
Recursively walks a field map and collects a snapshot of every binary value.
Reports which field-map entries alias the input buffer. On the BEAM that is
always none, so this always returns [].
Compares two maps and returns the keys whose values differ.
Look one (type, format) up across both registration spellings, returning the
field-map-level {serialize, deserialize} the run loop calls, or nil. "*"
matches any type/format and backs the single-type run/2 above.
Single-type worker: handles whatever type/format the runner asks for.
Multi-type worker. suite maps a type name to a %WorkerLib.Type{} — which
carries the model its format functions speak — or to the older format name ->
{serialize, deserialize} map, which still works and is what a type with no
natural struct wants. A (type, format) that is not registered is reported to
the runner as SKIPPED rather than failing the run.
Functions
Recursively walks a field map and collects a snapshot of every binary value.
Reports which field-map entries alias the input buffer. On the BEAM that is
always none, so this always returns [].
The other libraries answer this by XOR-flipping the input buffer and seeing which decoded fields change with it. Neither half of that is expressible here: a binary is immutable, so there is nothing to flip, and a decoded value can never alias the buffer it was read from in the first place.
Compares two maps and returns the keys whose values differ.
Look one (type, format) up across both registration spellings, returning the
field-map-level {serialize, deserialize} the run loop calls, or nil. "*"
matches any type/format and backs the single-type run/2 above.
Public, and separate from the run loop, so it can be tested without stdin: an
unresolved (type, format) is reported SKIPPED, so a registration shape this
silently fails to understand produces a green conformance run made entirely
of SKIPs — indistinguishable from a worker that honestly does not implement
the type. In Elixir that is not a hypothetical: a struct is a map, so the
%Type{} clause below has to come before the is_map one or every
model-registered type falls through it into a Map.get(%Type{}, "binary")
that answers nil.
Single-type worker: handles whatever type/format the runner asks for.
Multi-type worker. suite maps a type name to a %WorkerLib.Type{} — which
carries the model its format functions speak — or to the older format name ->
{serialize, deserialize} map, which still works and is what a type with no
natural struct wants. A (type, format) that is not registered is reported to
the runner as SKIPPED rather than failing the run.