Skip to content

haggqvist/cbor-model

Repository files navigation

CBOR Model

cbor-model adds CBOR serialization and CDDL schema generation to Pydantic models.

Installation

pip install cbor-model

or with uv:

uv add cbor-model

Quick start

Map encoding

Fields are encoded as a CBOR map keyed by the integer or string supplied to CBORField(key=...).

from typing import Annotated
from cbor_model import CBORModel, CBORField

class Sensor(CBORModel):
    name: Annotated[str, CBORField(key=0)]
    value: Annotated[float, CBORField(key=1)]

sensor = Sensor(name="temp", value=21.5)
data = sensor.model_dump_cbor()  # a2006474656d7001fb4035800000000000
assert Sensor.model_validate_cbor(data) == sensor

Array encoding

Switch to array encoding by setting CBORConfig(encoding="array") and using CBORField(index=...) — fields are serialized in index order.

from typing import Annotated
from cbor_model import CBORModel, CBORField, CBORConfig

class Point(CBORModel):
    cbor_config = CBORConfig(encoding="array")

    x: Annotated[int, CBORField(index=0)]
    y: Annotated[int, CBORField(index=1)]

pt = Point(x=4, y=2)
data = pt.model_dump_cbor()  # 820402
assert Point.model_validate_cbor(data) == pt

CBOR tags

Wrap a field's value in a CBOR tag using CBORField(tag=...), or tag the entire model with CBORConfig(tag=...).

from typing import Annotated
from cbor_model import CBORModel, CBORField, CBORConfig

class Reading(CBORModel):
    cbor_config = CBORConfig(tag=40001)

    sensor_id: Annotated[int, CBORField(key=0)]
    raw: Annotated[bytes, CBORField(key=1, tag=40002)]

Serialization context

Pass a CBORSerializationContext to control None and empty-collection exclusion:

from cbor_model import CBORSerializationContext

ctx = CBORSerializationContext(exclude_none=False, exclude_empty=False)
data = sensor.model_dump_cbor(context=ctx)

Custom encoders

Register encoders for types not natively supported by cbor2:

import decimal
from cbor_model import CBORConfig

class MyModel(CBORModel):
    cbor_config = CBORConfig(
        encoders={decimal.Decimal: lambda d: str(d)}
    )
    amount: Annotated[decimal.Decimal, CBORField(key=0)]

CDDL generation

Generate a CDDL schema from one or more models:

from cbor_model.cddl import CDDLGenerator

print(CDDLGenerator().generate(Sensor))
# sensor_name = 0
# sensor_value = 1
#
# Sensor = {
#     ? sensor_name: tstr,
#     ? sensor_value: float
# }

Integer constraints are rendered as precise RFC 8610-compatible CDDL. For example, lower-only bounds use numeric controls such as .gt or .ge, and closed integer bounds are emitted as ranges:

from typing import Annotated
from pydantic import Field

from cbor_model import CBORField, CBORModel
from cbor_model.cddl import CDDLGenerator


class Packet(CBORModel):
    count: Annotated[int, CBORField(key=0), Field(gt=0)]
    code: Annotated[int, CBORField(key=1), Field(ge=0, le=255)]


print(CDDLGenerator().generate(Packet))
# packet_count = 0
# packet_code = 1
#
# Packet = {
#     packet_count: int .gt 0,
#     packet_code: 0..255
# }

Map-encoded models always emit a per-model block of integer-key constants (prefix is the model class name converted to snake_case) and reference those constants in the map body. Use CBORField(description=...) to attach a free-text comment that is rendered as ; <text> after the field definition, and CBORField(override_name=...) to override the identifier (used verbatim).

Public type aliases

The package also exposes a small set of reusable integer aliases under cbor_model.types:

from typing import Annotated

from cbor_model import CBORField, CBORModel, types


class Header(CBORModel):
    version: Annotated[types.UInt1, CBORField(key=0)]
    length: Annotated[types.UInt2, CBORField(key=1)]

The currently available aliases are:

  • types.Int1: signed 8-bit integer (-128..127)
  • types.UInt: unsigned integer (ge=0)
  • types.UInt1: unsigned 8-bit integer (0..255)
  • types.UInt2: unsigned 16-bit integer (0..65535)
  • types.UInt4: unsigned 32-bit integer (0..4294967295)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages