Documentation ¶
Overview ¶
Package cbor implements a basic encoding/decoding API for RFC 8949 Concise Binary Object Representation (CBOR).
Not supported:
- Indefinite length arrays, maps, byte strings, or text strings
- Simple values other than bool, null, and undefined
- Numbers greater than 64 bits
- Decoding structs with more than one omittable field
- Encoding/decoding structs to/from CBOR maps
- Decoding CBOR maps with array/map/uncomparable keys to Go maps
- Floats (yet)
- UTF-8 validation of strings
However, the Marshaler/Unmarshaler interfaces allow any determinate sized CBOR item to be encoded to/from any Go type.
Specifically, >1 omittable struct fields (i.e. `omitempty`) is not supported, because handling this case is not generally solvable and depends on the specification of the API being implemented.
Encoding ¶
Encoding can be done with [any] or Marshal. Using an Encoder may be more efficient when writing many items if a buffered writer is used. It also allows for setting encoding options.
var w bytes.Buffer enc := cbor.NewEncoder(&w) # Simple _ = enc.Encode(true) // true _ = enc.Encode(false) // false _ = enc.Encode((*int)(nil)) // null # Numbers _ = enc.Encode(-1) // 0x20 // All encode to 0x01 _ = enc.Encode(int(1)) _ = enc.Encode(int8(1)) _ = enc.Encode(int16(1)) _ = enc.Encode(int32(1)) _ = enc.Encode(int64(1)) _ = enc.Encode(uint(1)) _ = enc.Encode(uint8(1)) _ = enc.Encode(uint16(1)) _ = enc.Encode(uint32(1)) _ = enc.Encode(uint64(1)) # Binary/Text _ = enc.Encode([]byte{0x01, 0x02}) // 0x42 0x01 0x02 _ = enc.Encode("Hello World!") # Homogeneous Arrays _ = enc.Encode([]int{1, 2, 3}) _ = enc.Encode([][]byte{{0x01}, {0x02}, {0x03}}) # Heterogeneous Arrays (Tuples/Structs) _ = enc.Encode(struct{ A int }{A: 1}) // 0x81, 0x01 _ = enc.Encode(struct{ A int; B string }{A: 1, B: "IETF"}) // 0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46 // Struct tags: change order by setting weights _ = enc.Encode(struct{ A int `cbor:"1"` B string `cbor:"0" }{ A: 1, B: "IETF", }) // 0x82, 0x64, 0x49, 0x45, 0x54, 0x46, 0x01 // Struct tags: ignore fields _ = enc.Encode(struct{ A int B string C bool `cbor:"-"` }{ A: 1, B: "IETF", C: true, }) // 0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46 // Struct embedded fields type Embed struct{ A int } _ = enc.Encode(struct{ Embed B string }{ Embed: Embed{A: 1}, B: "IETF", }) // 0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46 # Maps _ = enc.Encode(map[int]string{1: "hello"}) // Empty struct values also work (for sets) _ = enc.Encode(map[int]struct{}{1: {}, 2: {}}) // Core deterministic encoding is used by default _ = enc.Encode(map[int]struct{}{1: {}, 2: {}}, "hello": {}) // always ordered 1, 2, "hello" # Tags _ = enc.Encode(cbor.Tag[string]{Num: 42, Val: "Meaning of life"}) _ = enc.Encode(cbor.Tag[[]string]{Num: 42, Val: []string{"Meaning", "of", "life"}})
Decoding ¶
Decoding can be done with Decoder.Decode or Unmarshal. Using a Decoder is generally more memory efficient than reading an entire io.Reader into a []byte and then unmarshaling it.
# Simple var b bool _ = cbor.Unmarshal([]byte{0xf4}, &b) // b = false _ = cbor.Unmarshal([]byte{0xf5}, &b) // b = true var i int ip := &i _ = cbor.Unmarshal([]byte{0xf6}, &ip) // ip = nil # Numbers var i8 int8 _ = cbor.Unmarshal([]byte{0x01}, &i8) // i8 = 1 _ = cbor.Unmarshal([]0byte{x20}, &i8) // i8 = -1 # Binary/Text var bin []byte _ = cbor.Unmarshal([]byte{0x45, 0x68, 0x65, 0x6c, 0x6c, 0x6f}, &bin) // bin = ['h', 'e', 'l', 'l', 'o'] var text string _ = cbor.Unmarshal([]byte{0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f}, &text) // text = "hello" # Homogeneous Arrays var ints []int _ = cbor.Unmarshal([]byte{0x85, 0x01, 0x02, 0x03, 0x04, 0x05}, &ints) // ints = [1, 2, 3, 4, 5] # Heterogeneous Arrays (Tuples/Structs) var s1 struct{ A int } _ = cbor.Unmarshal([]byte{0x81, 0x01}, &s1) // s1 = {A: 1} var s2 struct{ A int; B string } _ = cbor.Unmarshal([]byte{0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46}, &s2) // s2 = {A: 1, B: "IETF"} // Struct tags: change order by setting weights var s3 struct{ A int `cbor:"1"` B string `cbor:"0" } _ = cbor.Unmarshal([]byte{0x82, 0x64, 0x49, 0x45, 0x54, 0x46, 0x01}, &s3) // s3 = {A: 1, B: "IETF"} // Struct tags: ignore fields var s4 struct{ A int B string C bool `cbor:"-"` } _ = cbor.Unmarshal([]byte{0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46}, &s4) // s4 = {A: 1, B: "IETF", C: false} // Struct tags: omit empty var s5 struct{ A int B string C bool `cbor:",omitempty"` } _ = cbor.Unmarshal([]byte{0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46}, &s5) // s5 = {A: 1, B: "IETF", C: false} // Struct embedded fields type Embed struct{ A int } var s6 struct{ Embed B string } _ = cbor.Unmarshal([]byte{0x82, 0x01, 0x64, 0x49, 0x45, 0x54, 0x46}, &s6) // s6 = {Embed: {A: 1}, B: "IETF"} # Maps var m1 map[int]int // m = nil _ = cbor.Unmarshal([]byte{0xa0}, &m1) // m1 = {} <- non-nil! _ = cbor.Unmarshal([]byte{0xa2, 0x01, 0x02, 0x03, 0x04}, &m1) // m1 = {1: 2, 3: 4} # Tags var tag cbor.Tag[string] _ = cbor.Unmarshal([]byte{0xc1, 0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f}, &tag) // tag = {Num: 1, Val: "hello"}
When decoding into an any/empty interface type, the following CBOR to Go type mapping is used:
Unsigned -> int64 Negative -> int64 Byte String -> []byte Text String -> string Array -> []interface{} Map -> map[interface{}]interface{} Tag -> cbor.Tag[cbor.RawBytes] Simple(Bool) -> bool
Decoding other types will fail, because it is not clear what memory to allocate. Even null cannot be decoded, because nil values still require a type in Go.
Index ¶
- Constants
- func BytewiseLexicalSort(indices []int, keys [][]byte) func(i, j int) bool
- func Marshal(v any) ([]byte, error)
- func Unmarshal(data []byte, v any) error
- type Bstr
- type ByteWrap
- type Decoder
- type Encoder
- type ErrUnsupportedType
- type FlatMarshaler
- type FlatUnmarshaler
- type Marshaler
- type OmitEmpty
- type RawBytes
- type Tag
- type TagData
- type Timestamp
- type Unmarshaler
- type X509Certificate
- type X509CertificateRequest
Constants ¶
const MaxArrayDecodeLength = 100_000
MaxArrayDecodeLength limits the max size of an array, string, byte slice, or map (where each key-value pair counts as two items).
Variables ¶
This section is empty.
Functions ¶
func BytewiseLexicalSort ¶
BytewiseLexicalSort is a map key sorting function. It is the default for an `Encoder`.
It is the "new" canonical form whereas length-first is the "old" canonical form.
Types ¶
type Bstr ¶
type Bstr[T any] struct{ Val T }
Bstr marshals and unmarshals CBOR data that is a byte array of the CBOR encoding of its underlying value.
CDDL: bstr .cbor T
This is a common convention in specifications like COSE and FDO and acts as a sort of type erasure. While a specification may wish to erase a type to allow for operating on arbitrary data (i.e. payloads in COSE signature structures), implementations sometimes _do_ want to specify the encoded type.
This generic bstr structure conveys type information as well as handles automatically unmarshaling into the proper type. If type erasure is indeed desired, then use a type alias: `type bstr = cbor.Bstr[cbor.RawBytes]`.
func NewBstr ¶
NewBstr is shorthand for struct initialization and is useful, because it often does not require writing the type parameter.
func (Bstr[T]) MarshalCBOR ¶
MarshalCBOR implements Marshaler.
func (*Bstr[T]) UnmarshalCBOR ¶
UnmarshalCBOR implements Unmarshaler.
type ByteWrap ¶
type ByteWrap[T any] struct{ Val T }
ByteWrap is a Bstr that treats Bstr[[]byte] as Bstr[cbor.RawBytes]. While Bstr guarantees that the inner bytes are valid CBOR, ByteWrap does not. ByteWrap only ensures that the marshaled type is a bytestring.
In other words, it avoids double-encoding a byte string. This convention is used in COSE.
func NewByteWrap ¶
NewByteWrap is shorthand for struct initialization and is useful, because it often does not require writing the type parameter.
func (ByteWrap[T]) MarshalCBOR ¶
MarshalCBOR implements Marshaler.
func (*ByteWrap[T]) UnmarshalCBOR ¶
UnmarshalCBOR implements Unmarshaler.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder iteratively consumes a reader, decoding CBOR types.
func NewDecoder ¶
NewDecoder returns a new Decoder. The io.Reader is not copied.
type Encoder ¶
type Encoder struct { // MapKeySort is used to determine sort order of map keys for encoding. If // none is set, then Core Deterministic (bytewise lexical) encoding is // used. // // The provided function is called with indices 0..len(keys)-1 and // marshaled map keys in a random order. The return value is expected to be // a "less" function that is used to iteratively sort the indices in place // while the marshaled keys remain unmodified. MapKeySort func(indices []int, marshaledKeys [][]byte) func(i, j int) bool // contains filtered or unexported fields }
Encoder allows for setting encoding options when marshaling CBOR data.
func NewEncoder ¶
NewEncoder returns a new Encoder. The io.Writer is not automatically flushed.
type ErrUnsupportedType ¶
type ErrUnsupportedType struct {
// contains filtered or unexported fields
}
ErrUnsupportedType means that a value of this type cannot be encoded.
func (ErrUnsupportedType) Error ¶
func (e ErrUnsupportedType) Error() string
type FlatMarshaler ¶
type FlatMarshaler interface { // FlatMarshalCBOR encodes CBOR objects to a stream (not wrapped in a CBOR // array). The number of objects decoded must match the flatN option of the // cbor tag. FlatMarshalCBOR(io.Writer) error }
FlatMarshaler is implemented by types to provide more than one object of an array. This is particularly useful in structs to match the behavior of embedded struct fields, but with full control, like Marshaler.
FlatMarshaler is used iff the field has a flatN cbor struct tag, i.e. `cbor:",flat2"`.
type FlatUnmarshaler ¶
type FlatUnmarshaler interface { // FlatUnmarshalCBOR decodes CBOR objects from a stream (not an array). The // number of objects decoded must match the flatN option of the cbor tag. FlatUnmarshalCBOR(io.Reader) error }
FlatUnmarshaler is implemented by types to consume more than one object of an array. This is particularly useful in structs to match the behavior of embedded struct fields, but with full control, like Unmarshaler.
FlatUnmarshaler is used iff the field has a flatN cbor struct tag, i.e. `cbor:",flat2"`.
type Marshaler ¶
Marshaler is the interface implemented by types that can marshal themselves into valid CBOR.
type OmitEmpty ¶
type OmitEmpty[T any] struct{ Val T }
OmitEmpty encodes a zero value (zero, empty array, empty byte string, empty string, empty map) as zero bytes.
func (OmitEmpty[T]) MarshalCBOR ¶
MarshalCBOR encodes a zero value (zero, empty array, empty byte string, empty string, empty map) as zero bytes.
func (*OmitEmpty[T]) UnmarshalCBOR ¶
UnmarshalCBOR decodes data into its generic typed Val field. Note that OmitEmpty is treated specially by the cbor package such that reading zero bytes (EOF) will not cause an error.
type RawBytes ¶
type RawBytes []byte
RawBytes encodes and decodes untransformed. When encoding, it must contain valid CBOR.
func (RawBytes) MarshalCBOR ¶
MarshalCBOR implements Marshaler.
func (*RawBytes) UnmarshalCBOR ¶
UnmarshalCBOR implements Unmarshaler.
type Tag ¶
Tag is a tagged CBOR type.
type Timestamp ¶
Timestamp implements the timestamp CBOR format used in the FDO error message type. The expected string format, if used, is RFC3339.
timestamp = null / UTCStr / UTCInt / TIME_T UTCStr = #6.0(tstr) UTCInt = #6.1(uint) TIMET = #6.1(uint)
func (Timestamp) MarshalCBOR ¶
MarshalCBOR implements Marshaler.
func (*Timestamp) UnmarshalCBOR ¶
UnmarshalCBOR implements Unmarshaler.
type Unmarshaler ¶
Unmarshaler is the interface implemented by types that can unmarshal a CBOR description of themselves. The data is invalid upon the function returning.
type X509Certificate ¶
type X509Certificate x509.Certificate
X509Certificate is a newtype for x509.Certificate implementing proper CBOR encoding.
func (*X509Certificate) MarshalCBOR ¶
func (c *X509Certificate) MarshalCBOR() ([]byte, error)
MarshalCBOR implements Marshaler interface.
func (*X509Certificate) UnmarshalCBOR ¶
func (c *X509Certificate) UnmarshalCBOR(data []byte) error
UnmarshalCBOR implements Unmarshaler interface.
type X509CertificateRequest ¶
type X509CertificateRequest x509.CertificateRequest
X509CertificateRequest is a newtype for x509.CertificateRequest implementing proper CBOR encoding.
func (X509CertificateRequest) MarshalCBOR ¶
func (c X509CertificateRequest) MarshalCBOR() ([]byte, error)
MarshalCBOR implements Marshaler interface.
func (*X509CertificateRequest) UnmarshalCBOR ¶
func (c *X509CertificateRequest) UnmarshalCBOR(data []byte) error
UnmarshalCBOR implements Unmarshaler interface.