Skip to content

Serialization

The canonical wire codec for stable kernel graphs.

serialization

Canonical wire codec for stable QIEC graphs.

The codec is an explicit allowlist, not a generic Python object serializer. Only frozen kernel records, concrete identifier classes, kernel enums, tuples, bytes, and JSON scalars cross the boundary. Runtime attachments, handler callbacks, modules, mappings, and unknown future node tags are rejected.

QIEC_WIRE_FORMAT module-attribute

QIEC_WIRE_FORMAT = 'qiec-json/v1'

The format tag every encoded document carries, checked on decoding.

JsonValue

JsonValue = None | bool | int | float | str | list[JsonValue] | dict[str, JsonValue]

A JSON document as json.loads returns it and json.dumps accepts it.

SerializationError

Bases: ValueError

A value is not in the stable QIEC wire language.

to_data

to_data(value: object) -> dict[str, JsonValue]

Encode a stable QIEC graph in its versioned wire envelope.

PARAMETER DESCRIPTION
value

The graph to encode.

TYPE: object

RETURNS DESCRIPTION
dict[str, JsonValue]

The envelope, carrying the wire format and the ABI alongside the graph. Both are recorded because neither can be guessed from the payload, and a reader that guessed wrong would misread it.

RAISES DESCRIPTION
SerializationError

If the graph contains a value that may not cross the boundary.

Source code in src/quivers/qiec/serialization.py
def to_data(value: object) -> dict[str, JsonValue]:
    """Encode a stable QIEC graph in its versioned wire envelope.

    Parameters
    ----------
    value : object
        The graph to encode.

    Returns
    -------
    dict[str, JsonValue]
        The envelope, carrying the wire format and the ABI alongside the
        graph. Both are recorded because neither can be guessed from the
        payload, and a reader that guessed wrong would misread it.

    Raises
    ------
    SerializationError
        If the graph contains a value that may not cross the boundary.
    """
    return {
        "$schema": QIEC_WIRE_FORMAT,
        "abi": QIEC_ABI,
        "root": _encode(value),
    }

from_data

from_data(data: object) -> object

Decode a QIEC graph, rejecting other ABIs and unknown node tags.

PARAMETER DESCRIPTION
data

The decoded envelope.

TYPE: object

RETURNS DESCRIPTION
object

The reconstructed graph.

RAISES DESCRIPTION
SerializationError

If the envelope is malformed, declares another wire format or ABI, or holds a graph that fails to decode. An ABI mismatch is refused rather than attempted, since a payload from another version may use the same tags for different shapes.

Source code in src/quivers/qiec/serialization.py
def from_data(data: object) -> object:
    """Decode a QIEC graph, rejecting other ABIs and unknown node tags.

    Parameters
    ----------
    data : object
        The decoded envelope.

    Returns
    -------
    object
        The reconstructed graph.

    Raises
    ------
    SerializationError
        If the envelope is malformed, declares another wire format or
        ABI, or holds a graph that fails to decode. An ABI mismatch is
        refused rather than attempted, since a payload from another
        version may use the same tags for different shapes.
    """
    if not isinstance(data, dict) or any(not isinstance(key, str) for key in data):
        raise SerializationError("QIEC wire envelope must be an object")
    typed = cast(dict[str, JsonValue], data)
    _exact_keys(typed, {"$schema", "abi", "root"}, "QIEC wire envelope")
    if typed["$schema"] != QIEC_WIRE_FORMAT:
        raise SerializationError(f"unsupported QIEC wire format {typed['$schema']!r}")
    if typed["abi"] != QIEC_ABI:
        raise SerializationError(
            f"QIEC ABI mismatch: expected {QIEC_ABI!r}, got {typed['abi']!r}"
        )
    return _decode(typed["root"])

dumps

dumps(value: object) -> str

Serialize a QIEC graph as deterministic UTF-8-compatible JSON text.

PARAMETER DESCRIPTION
value

The graph to serialize.

TYPE: object

RETURNS DESCRIPTION
str

Compact, key-sorted JSON. Determinism matters because identities downstream are content addressed: the same graph must produce the same bytes on every run and every platform.

RAISES DESCRIPTION
SerializationError

If the graph contains a value that may not cross the boundary.

Source code in src/quivers/qiec/serialization.py
def dumps(value: object) -> str:
    """Serialize a QIEC graph as deterministic UTF-8-compatible JSON text.

    Parameters
    ----------
    value : object
        The graph to serialize.

    Returns
    -------
    str
        Compact, key-sorted JSON. Determinism matters because identities
        downstream are content addressed: the same graph must produce the
        same bytes on every run and every platform.

    Raises
    ------
    SerializationError
        If the graph contains a value that may not cross the boundary.
    """
    return json.dumps(
        to_data(value),
        ensure_ascii=False,
        allow_nan=False,
        separators=(",", ":"),
        sort_keys=True,
    )

loads

loads(text: str | bytes | bytearray) -> object

Deserialize one canonical QIEC JSON document.

PARAMETER DESCRIPTION
text

The document to read.

TYPE: str or bytes or bytearray

RETURNS DESCRIPTION
object

The reconstructed graph.

RAISES DESCRIPTION
SerializationError

If the text is not valid JSON, repeats an object key at any depth, or fails any of the decoding checks.

Source code in src/quivers/qiec/serialization.py
def loads(text: str | bytes | bytearray) -> object:
    """Deserialize one canonical QIEC JSON document.

    Parameters
    ----------
    text : str or bytes or bytearray
        The document to read.

    Returns
    -------
    object
        The reconstructed graph.

    Raises
    ------
    SerializationError
        If the text is not valid JSON, repeats an object key at any
        depth, or fails any of the decoding checks.
    """
    try:
        data = json.loads(text, object_pairs_hook=_unique_object)
    except (json.JSONDecodeError, UnicodeDecodeError) as error:
        raise SerializationError(f"invalid QIEC JSON: {error}") from error
    return from_data(data)