cbor

package
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package cbor is the deterministic CBOR that committed records are written in.

The codec is the subset of RFC 8949 a record needs, with the core deterministic encoding rules of §4.2.1 enforced on BOTH sides. The encoder only ever writes canonical bytes; the decoder refuses anything that is not canonical or is outside the subset, so a record that decodes is byte for byte the record its encoder produced, and a hostile publisher cannot hand a host two different byte strings for one value.

Supported: unsigned integers (major type 0), negative integers (1), byte strings (2), text strings (3, valid UTF-8), arrays (4), maps (5, keys in bytewise lexicographic order of their encodings, no duplicates), and the simple values false, true and null (7). Refused: indefinite lengths, tags, floats, undefined, every other simple value, and nesting deeper than MaxDepth. Nothing here allocates from a declared length before the bytes are known to be present.

Index

Examples

Constants

View Source
const MaxDepth = 16

MaxDepth bounds nesting. A committed record is two levels deep (a map whose body is a map); sixteen leaves room for a body that nests without letting a hostile item recurse without limit.

Variables

View Source
var (
	ErrNotCanonical = errors.New("cbor: not canonical")
	ErrUnsupported  = errors.New("cbor: unsupported item")
	ErrTruncated    = errors.New("cbor: truncated")
	ErrTrailing     = errors.New("cbor: trailing bytes")
	ErrDepth        = errors.New("cbor: nesting too deep")
	ErrDuplicateKey = errors.New("cbor: duplicate map key")
	ErrKeyOrder     = errors.New("cbor: map keys out of order")
	ErrUTF8         = errors.New("cbor: invalid UTF-8")
)

Functions

func Encode

func Encode(v Value) ([]byte, error)

Encode writes v in core deterministic encoding.

Example

Encode sorts a map's keys into canonical order (bytewise order of their encodings), whatever order the Map lists them in, and writes every head in its shortest form. Decoding gives the pairs back in wire order.

package main

import (
	"fmt"

	"github.com/lightwebinc/bcommon/cbor"
)

func main() {
	record := cbor.Map{
		{Key: "name", Val: "example"},
		{Key: uint64(2), Val: []byte{0xca, 0xfe}},
		{Key: uint64(1), Val: int64(-1)},
		{Key: "tags", Val: []cbor.Value{"a", true, nil}},
	}
	b, err := cbor.Encode(record)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%x\n", b)

	v, err := cbor.DecodeValue(b)
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, p := range v.(cbor.Map) {
		fmt.Printf("%v => %v\n", p.Key, p.Val)
	}
	name, _ := v.(cbor.Map).Get("name")
	fmt.Println("name:", name)
}
Output:
a401200242cafe646e616d65676578616d706c656474616773836161f5f6
1 => -1
2 => [202 254]
name => example
tags => [a true <nil>]
name: example

Types

type Map

type Map []Pair

Map is a CBOR map. It is a slice, not a Go map, so keys of any supported type can be carried and unknown keys keep their wire position.

func (Map) Get

func (m Map) Get(key Value) (Value, bool)

Get returns the value for key, matching by encoded key bytes.

type Pair

type Pair struct {
	Key Value
	Val Value
}

Pair is one map entry. Map keeps entries in the order given; Encode sorts them, Decode returns them in the (already canonical) wire order.

type Value

type Value any

Value is one decoded item: uint64, int64 (negative values only; a decoder never produces a non-negative int64), []byte, string, []Value, Map, bool, or nil. Encoders additionally accept int, uint and uint8 for convenience.

func DecodeValue

func DecodeValue(b []byte) (Value, error)

DecodeValue parses exactly one canonical item and refuses trailing bytes.

Example (Refusals)

The decoder refuses every encoding the encoder would not have written, so a value has exactly one byte string a reader accepts.

package main

import (
	"fmt"

	"github.com/lightwebinc/bcommon/cbor"
)

func main() {
	for _, c := range []struct {
		what string
		b    []byte
	}{
		{"23 in two bytes", []byte{0x18, 0x17}},
		{"map keys out of order", []byte{0xa2, 0x02, 0x00, 0x01, 0x00}},
		{"duplicate map key", []byte{0xa2, 0x01, 0x00, 0x01, 0x00}},
		{"indefinite-length array", []byte{0x9f, 0x01, 0xff}},
		{"a float", []byte{0xf9, 0x3c, 0x00}},
		{"trailing bytes", []byte{0x01, 0x02}},
		{"truncated string", []byte{0x43, 0x01}},
	} {
		_, err := cbor.DecodeValue(c.b)
		fmt.Printf("%s: %v\n", c.what, err)
	}
}
Output:
23 in two bytes: cbor: not canonical
map keys out of order: cbor: map keys out of order
duplicate map key: cbor: duplicate map key
indefinite-length array: cbor: unsupported item
a float: cbor: unsupported item
trailing bytes: cbor: trailing bytes
truncated string: cbor: truncated

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL