Macaw.Layers.Form behaviour (macaw_layers v0.2.2)

Copy Markdown View Source

A document's map form and JSON form, exact inverses for valid values (spec/01 §6).

The value is the document as Elixir holds it: atom keys where the type has a key, string names elsewhere, atoms, times. Its map form is JSON-ready: string keys, and a tag (Macaw.Layers.Tags) for every value JSON can't express. Its JSON form is that map encoded. For a valid value:

from_map(to_map(value)) == {:ok, value}
to_map(from_map(map))   == {:ok, map}    # for a map to_map/2 wrote

A document type implements this behavior: its tag table, the keys it reads as atoms, and the atoms a $atom may spell, each a closed table (Macaw.Layers.Vocabulary), so no atom is ever made from a document. A type with values of its own (a struct, a tuple) writes and reads them through encode_value/1 and decode_value/2, under its own live tags.

The kernel's terms:

ValueMap form
nil, a boolean, a number, a stringas it is
another atom{"$atom": "spelling"}, read back through atoms/0
a DateTime in Etc/UTC{"$time": "ISO 8601"}
a lista list
a mapan object: an atom key by its spelling, a string key as it is, escaped when it starts with $

A function, a PID, a reference, a port, a tuple or a struct the type does not write has no form: it is refused at its path as {:type, :term}.

Summary

Callbacks

The atoms a $atom may spell in this type's documents.

The value of one of the type's own live tags, its payload already read, or :default when the tag or payload is not one it reads.

A value of the type's own, in its map form, or :default for the kernel's rules.

The keys the type reads as atoms, by spelling.

The type's tag table: a module that uses Macaw.Layers.Tags.

Functions

One term's map form, for a type writing its own tag's payload (spec/01 §6): {:ok, form}, or every value and key without one, by path from the term.

The value a JSON document holds, read through every gate (Macaw.Layers.Document.read/3) and then from its map form. type implements this behavior, Macaw.Layers.Version and Macaw.Layers.Document.

The value a map form holds: its tags held to the type's table, its keys read against the type's keys, its $atoms against the type's atoms; {:ok, value} or every fault.

The value's JSON form.

The value's map form: {:ok, map}, or every value and key without one, by path.

Callbacks

atoms()

@callback atoms() :: Macaw.Layers.Vocabulary.table()

The atoms a $atom may spell in this type's documents.

decode_value(tag, payload)

(optional)
@callback decode_value(tag :: String.t(), payload :: term()) :: {:ok, term()} | :default

The value of one of the type's own live tags, its payload already read, or :default when the tag or payload is not one it reads.

encode_value(term)

(optional)
@callback encode_value(term()) :: {:ok, term()} | :default

A value of the type's own, in its map form, or :default for the kernel's rules.

keys()

@callback keys() :: Macaw.Layers.Vocabulary.table()

The keys the type reads as atoms, by spelling.

tags()

@callback tags() :: module()

The type's tag table: a module that uses Macaw.Layers.Tags.

Functions

encode_term(term, type)

@spec encode_term(term(), module()) ::
  {:ok, term()} | {:error, [Macaw.Layers.Fault.t(), ...]}

One term's map form, for a type writing its own tag's payload (spec/01 §6): {:ok, form}, or every value and key without one, by path from the term.

from_json(json, type, opts \\ [])

@spec from_json(binary(), module(), [Macaw.Layers.Document.option()]) ::
  {:ok, map()} | {:error, [Macaw.Layers.Fault.t(), ...]}

The value a JSON document holds, read through every gate (Macaw.Layers.Document.read/3) and then from its map form. type implements this behavior, Macaw.Layers.Version and Macaw.Layers.Document.

from_map(map, type)

@spec from_map(map(), module()) ::
  {:ok, map()} | {:error, [Macaw.Layers.Fault.t(), ...]}

The value a map form holds: its tags held to the type's table, its keys read against the type's keys, its $atoms against the type's atoms; {:ok, value} or every fault.

to_json(value, type)

@spec to_json(map(), module()) ::
  {:ok, binary()} | {:error, [Macaw.Layers.Fault.t(), ...]}

The value's JSON form.

to_map(value, type)

@spec to_map(map(), module()) ::
  {:ok, map()} | {:error, [Macaw.Layers.Fault.t(), ...]}

The value's map form: {:ok, map}, or every value and key without one, by path.