cbor v1.0.0 clib Serialization & Data Formats

CBOR binary serialization — RFC 7049 / RFC 8949. Compact, self-describing, schema-free. Build, encode, decode, and inspect CBOR items with a clean handle-based API.

ppm install cbor

What is CBOR?

CBOR (Concise Binary Object Representation) is an IETF binary data format defined in RFC 8949 (updated from RFC 7049). It shares the same conceptual data model as JSON — maps, arrays, strings, numbers, booleans, and null — but uses a compact binary encoding instead of human-readable text.

Key properties that distinguish CBOR from other binary formats:

CBOR vs JSON vs MessagePack

Format Standard Encoding Schema required Tags / types Typical use
CBOR IETF RFC 8949 Binary No Typed + semantic tags IoT, WebAuthn, COSE, CoAP
JSON IETF RFC 8259 Text (UTF-8) No Stringly-typed Web APIs, config files
MessagePack None (community) Binary No Typed, no semantic tags High-throughput RPC, caching

Size comparison

Concrete example: the JSON string {"name":"Alice","age":30} is 24 bytes. The equivalent CBOR encoding is 16 bytes — roughly 33% smaller with no loss of information.

For an IoT sensor fleet sending millions of small packets per day, that 33% reduction translates directly into lower bandwidth costs, longer battery life, and faster transmission over constrained links such as LoRaWAN or NB-IoT.

CBOR major types

Every CBOR data item begins with a one-byte initial byte whose upper 3 bits identify the major type and whose lower 5 bits carry the additional info (the actual value or length).

Major typeNameDescription
0Unsigned integerNon-negative integer (0 .. 264−1). Values 0–23 fit in the initial byte itself.
1Negative integerNegative integer encoded as −1 − n where n is the unsigned value.
2Byte stringArbitrary binary data. Length in bytes precedes the content.
3Text stringUTF-8 encoded text. Length is the byte count of the UTF-8 sequence.
4ArrayOrdered sequence of data items. Length is the number of elements.
5MapKey-value pairs. Length is the number of pairs. Keys may be any type.
6Tagged itemA numeric semantic tag followed by a single wrapped data item.
7Float / Simple valuesIEEE 754 floats (16/32/64-bit) plus simple values: true, false, null, undefined.

CBOR semantic tags

Tags (major type 6) annotate any item with a well-known semantic meaning without changing the underlying encoding. The TCBORTag enum covers the most commonly used IANA-registered tag numbers:

TagConstantMeaning
0ctTagDateTimeDate/time as an ISO 8601 text string.
1ctTagEpochTimeUnix timestamp as an integer or float.
2ctTagBignumPositive bignum encoded as a byte string.
3ctTagNegBignumNegative bignum encoded as a byte string.
21ctTagBase64URLByte string should be encoded as base64url when converted to JSON.
22ctTagBase64Byte string should be encoded as base64 when converted to JSON.
32ctTagURIText string is an absolute URI (RFC 3986).
37ctTagUUID16-byte string is a UUID (RFC 4122).

Use cases

Where CBOR is the right choice:

IoT / constrained devices — CoAP (Constrained Application Protocol, RFC 7252) mandates CBOR as its payload format. Microcontrollers with 32 KB of RAM can encode and decode CBOR without heap allocation.

COSE — CBOR Object Signing and Encryption (RFC 8152) is the binary equivalent of JOSE/JWT. Used in secure hardware attestation and firmware updates.

WebAuthn / FIDO2 — Browser security key attestation objects and authenticator data are CBOR-encoded. Decoding them requires a full CBOR implementation.

CBOR-LD — A CBOR encoding of JSON-LD linked data that achieves 60–80% size reduction compared to the JSON-LD equivalent.

Concise Problem Details — The binary variant of RFC 7807 problem detail objects uses CBOR to report API errors from constrained servers.

Types

TCBORItem is an opaque integer handle. All CBOR data items are created through constructor functions and freed with FreeItem. The handle is valid until freed; freeing a parent item recursively frees all children.

TCBORType — discriminates the runtime kind of a TCBORItem:
ctUInt(0), ctNegInt(1), ctByteStr(2), ctTextStr(3), ctArray(4),
ctMap(5), ctTag(6), ctFloat(7), ctBool(8), ctNull(9), ctUndefined(10)

API Reference

Build — constructors
function NewUInt(Value: Int64): TCBORItem
Create an unsigned integer item.
function NewNegInt(Value: Int64): TCBORItem
Create a negative integer item.
function NewText(S: string): TCBORItem
Create a UTF-8 text string item.
function NewBytes(Data: string): TCBORItem
Create a byte string item from raw binary data.
function NewFloat(Value: Double): TCBORItem
Create a float (IEEE 754 64-bit) item.
function NewBool(Value: Boolean): TCBORItem
Create a boolean simple value (true or false).
function NewNull: TCBORItem
Create a null simple value.
function NewArray: TCBORItem
Create an empty array. Populate with ArrayAppend.
function NewMap: TCBORItem
Create an empty map. Populate with MapAdd or MapAddStr.
function NewTagged(Tag: Int64; Item: TCBORItem): TCBORItem
Wrap any item with a semantic tag number (see TCBORTag).
Array operations
procedure ArrayAppend(Arr, Item: TCBORItem)
Append an item to the end of an array.
function ArraySize(Arr: TCBORItem): Integer
Return the number of elements in the array.
function ArrayGet(Arr: TCBORItem; Index: Integer): TCBORItem
Return the element at zero-based Index.
Map operations
procedure MapAdd(Map, Key, Value: TCBORItem)
Add a key-value pair where both key and value are CBOR items.
procedure MapAddStr(Map: TCBORItem; Key: string; Value: TCBORItem)
Convenience form: adds a text-string key without creating a separate NewText item.
function MapSize(Map: TCBORItem): Integer
Return the number of key-value pairs in the map.
function MapKey(Map: TCBORItem; Index: Integer): TCBORItem
Return the key item at position Index (insertion order).
function MapValue(Map: TCBORItem; Index: Integer): TCBORItem
Return the value item at position Index (insertion order).
function MapGetStr(Map: TCBORItem; Key: string): TCBORItem
Look up a value by text key. Returns 0 if the key is not present.
Encode / Decode
function Encode(Item: TCBORItem): string
Serialize a CBOR item tree to a binary byte string.
function Decode(Data: string): TCBORItem
Deserialize binary CBOR bytes back into an item tree. Returns the root item.
Read values
function GetType(Item: TCBORItem): TCBORType
Return the major type discriminant of an item.
function GetUInt(Item: TCBORItem): Int64
Read the unsigned integer value.
function GetNegInt(Item: TCBORItem): Int64
Read the negative integer value.
function GetText(Item: TCBORItem): string
Read the UTF-8 text string value.
function GetBytes(Item: TCBORItem): string
Read the raw byte string value.
function GetFloat(Item: TCBORItem): Double
Read the float value.
function GetBool(Item: TCBORItem): Boolean
Read the boolean simple value.
function GetTag(Item: TCBORItem): Int64
Read the numeric tag number from a tagged item.
function GetTaggedItem(Item: TCBORItem): TCBORItem
Return the inner item wrapped by a tag.
Debug
function Diagnostic(Item: TCBORItem): string
Return the CBOR diagnostic notation for the item — a human-readable representation similar to JSON, as defined in RFC 8949 Appendix G. Example: {"sensor": "temperature", "value": 23.5_3}.
function ToHex(Data: string): string
Convert a binary CBOR byte string to a lowercase hex string, useful for logging and protocol debugging.
Memory
procedure FreeItem(Item: TCBORItem)
Free a CBOR item and all child items recursively. Always call this on root items you have finished using.

Code Example

Build a sensor reading map, encode it to CBOR binary, print the byte count and diagnostic notation, then decode and read a field back:

uses cbor;

var
  Root, Tags, Tag: TCBORItem;
  Data: string;
  Decoded: TCBORItem;

begin
  Root := NewMap;
  MapAddStr(Root, 'sensor', NewText('temperature'));
  MapAddStr(Root, 'value',  NewFloat(23.5));
  MapAddStr(Root, 'unit',   NewText('C'));
  MapAddStr(Root, 'ts',     NewTagged(1, NewUInt(1710000000)));  { epoch time }

  Tags := NewArray;
  ArrayAppend(Tags, NewText('room1'));
  ArrayAppend(Tags, NewText('floor2'));
  MapAddStr(Root, 'tags', Tags);

  Data := Encode(Root);
  WriteLn('Encoded: ', Length(Data), ' bytes');
  WriteLn('Diagnostic: ', Diagnostic(Root));
  FreeItem(Root);

  Decoded := Decode(Data);
  WriteLn('Sensor: ', GetText(MapGetStr(Decoded, 'sensor')));
  FreeItem(Decoded);
end.

Package Info

Version1.0.0
Typeclib
C Librarylibcbor-dev
StandardRFC 7049 / 8949
Authorgustavo

Install

ppm install cbor
Requires: libcbor-dev
Ubuntu / Debian: sudo apt install libcbor-dev
macOS: brew install libcbor

API Summary

  • NewUInt / NewNegInt
  • NewText / NewBytes
  • NewFloat / NewBool / NewNull
  • NewArray / NewMap
  • NewTagged
  • ArrayAppend / ArraySize / ArrayGet
  • MapAdd / MapAddStr
  • MapSize / MapKey / MapValue
  • MapGetStr
  • Encode / Decode
  • GetType
  • GetUInt / GetNegInt
  • GetText / GetBytes
  • GetFloat / GetBool
  • GetTag / GetTaggedItem
  • Diagnostic / ToHex
  • FreeItem
  • CBORVersion

RFC Reference

RFC 8949 (updated CBOR) and its predecessor RFC 7049 are both IETF standards. All major type numbers, tag assignments, and diagnostic notation in this package follow the IANA CBOR registry.