Documentation
¶
Overview ¶
Package cbor implements a bounded, reflection-free subset of RFC 8949.
Decoder exposes typed tokens instead of mapping CBOR to arbitrary Go values. Encoder writes deterministic output and provides helpers for deterministically ordered arrays and maps. Nothing in either path uses reflection, io.ReadAll, or struct tags.
Map key ordering ¶
RFC 8949 defines two deterministic map key orderings, and they produce different bytes for the same map. EncoderOptions.KeyOrder selects between them. The zero value is LengthFirstKeyOrder, the section 4.2.3 length-first ordering that CTAP2 canonical CBOR and COSE require; BytewiseKeyOrder is the section 4.2.1 Core Deterministic Encoding ordering. Callers that care which one reaches the wire should set the field rather than inherit it.
Bounds ¶
Every limit is explicit and every limit is enforced before anything is reserved: a declared length never becomes an allocation on its own, because the length prefix of a string arrives before its bytes and is attacker controlled. DecoderOptions.RejectDuplicateMapKeys additionally validates a bounded root item before exposing any of its tokens, at the cost of retaining up to MaxRawMessageBytes.
Intended uses ¶
Security-sensitive formats where preserving signed integer labels and rejecting hostile input matter more than mapping arbitrary structs: WebAuthn authenticator data and COSE_Key on one side, compact realtime game messages on the other.
The package intentionally does not support struct tags, diagnostic notation, COSE signing, encryption, key management, or indefinite-length output.
Index ¶
- Variables
- func AppendArrayHeader(dst []byte, n int) []byte
- func AppendBool(dst []byte, v bool) []byte
- func AppendBytes(dst, v []byte) []byte
- func AppendFloat(dst []byte, v float64) []byte
- func AppendInt(dst []byte, v int64) []byte
- func AppendMapHeader(dst []byte, n int) []byte
- func AppendNegative(dst []byte, arg uint64) []byte
- func AppendNull(dst []byte) []byte
- func AppendRaw(dst []byte, raw RawMessage) []byte
- func AppendTag(dst []byte, tag uint64) []byte
- func AppendText(dst []byte, v string) []byte
- func AppendUint(dst []byte, v uint64) []byte
- func Validate(data []byte, opts DecoderOptions) error
- type Appender
- type Decodable
- type Decoder
- func (d *Decoder) ReadArray() (length int, indefinite bool, err error)
- func (d *Decoder) ReadBool() (bool, error)
- func (d *Decoder) ReadBytes() ([]byte, error)
- func (d *Decoder) ReadFloat() (float64, error)
- func (d *Decoder) ReadInt() (int64, error)
- func (d *Decoder) ReadMap() (pairs int, indefinite bool, err error)
- func (d *Decoder) ReadNull() error
- func (d *Decoder) ReadRaw() (RawMessage, error)
- func (d *Decoder) ReadTag() (uint64, error)
- func (d *Decoder) ReadText() (string, error)
- func (d *Decoder) ReadToken() (Token, error)
- func (d *Decoder) ReadUint() (uint64, error)
- type DecoderOptions
- type Encoder
- func (e *Encoder) Reset(w io.Writer) error
- func (e *Encoder) WriteArray(items []RawMessage) error
- func (e *Encoder) WriteBool(v bool) error
- func (e *Encoder) WriteBytes(v []byte) error
- func (e *Encoder) WriteFloat(v float64) error
- func (e *Encoder) WriteInt(v int64) error
- func (e *Encoder) WriteMap(entries []MapEntry) error
- func (e *Encoder) WriteNegative(arg uint64) error
- func (e *Encoder) WriteNull() error
- func (e *Encoder) WriteRaw(raw RawMessage) error
- func (e *Encoder) WriteTag(tag uint64, content RawMessage) error
- func (e *Encoder) WriteText(v string) error
- func (e *Encoder) WriteUint(v uint64) error
- type EncoderOptions
- type Error
- type KeyOrder
- type MapEntry
- type Profile
- func (p Profile) AllowingFloats() Profile
- func (p Profile) DecoderOptions() DecoderOptions
- func (p Profile) EncoderOptions() EncoderOptions
- func (p Profile) MaxContainerItems() int
- func (p Profile) MaxInputBytes() int64
- func (p Profile) MaxNestedLevels() int
- func (p Profile) Name() string
- func (p Profile) NewReader(data []byte) (*Reader, error)
- func (p Profile) ReaderOver(data []byte) Reader
- func (p Profile) Validate(data []byte) error
- func (p Profile) ValidateAppended(dst []byte, before int) error
- func (p Profile) WithMaxInputBytes(n int64) Profile
- func (p Profile) WithMaxNestedLevels(n int) Profile
- type RawMessage
- func MarshalBool(v bool) RawMessage
- func MarshalBytes(v []byte) RawMessage
- func MarshalFloat(v float64) RawMessage
- func MarshalInt(v int64) RawMessage
- func MarshalNegative(arg uint64) RawMessage
- func MarshalNull() RawMessage
- func MarshalText(v string) (RawMessage, error)
- func MarshalUint(v uint64) RawMessage
- type Reader
- func (r *Reader) Done() bool
- func (r *Reader) Offset() int
- func (r *Reader) Peek() (TokenKind, error)
- func (r *Reader) ReadArrayHeader() (length int, indefinite bool, err error)
- func (r *Reader) ReadBool() (bool, error)
- func (r *Reader) ReadBreak() error
- func (r *Reader) ReadBytes() ([]byte, error)
- func (r *Reader) ReadFloat() (float64, error)
- func (r *Reader) ReadInt() (int64, error)
- func (r *Reader) ReadInt8() (int8, error)
- func (r *Reader) ReadInt16() (int16, error)
- func (r *Reader) ReadInt32() (int32, error)
- func (r *Reader) ReadInt64() (int64, error)
- func (r *Reader) ReadMapHeader() (pairs int, indefinite bool, err error)
- func (r *Reader) ReadNull() error
- func (r *Reader) ReadRaw() (RawMessage, error)
- func (r *Reader) ReadTag() (uint64, error)
- func (r *Reader) ReadText() (string, error)
- func (r *Reader) ReadTextBytes() ([]byte, error)
- func (r *Reader) ReadUint() (uint64, error)
- func (r *Reader) ReadUint8() (uint8, error)
- func (r *Reader) ReadUint16() (uint16, error)
- func (r *Reader) ReadUint32() (uint32, error)
- func (r *Reader) ReadUint64() (uint64, error)
- func (r *Reader) Remaining() int
- func (r *Reader) Reset(data []byte)
- func (r *Reader) Skip() error
- type Token
- type TokenKind
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrMalformed = errors.New("cbor: malformed input") ErrTruncated = errors.New("cbor: truncated input") ErrLimitExceeded = errors.New("cbor: limit exceeded") ErrDuplicateMapKey = errors.New("cbor: duplicate map key") ErrExtraneousData = errors.New("cbor: extraneous data after root item") ErrUnexpectedToken = errors.New("cbor: unexpected token") ErrIntegerOverflow = errors.New("cbor: integer does not fit int64") // ErrProfileViolation reports CBOR that is well formed but not legal under // the profile it was read or written under. ErrProfileViolation = errors.New("cbor: profile violation") // ErrFloatRefused reports a float where the configuration carries scaled // integers instead. It is a ErrProfileViolation with its own identity, // because a float leak is the specific failure a deterministic simulation // most needs to be told about. ErrFloatRefused = fmt.Errorf("%w: float", ErrProfileViolation) )
Functions ¶
func AppendArrayHeader ¶
AppendArrayHeader appends a definite-length array head for n items, which the caller then appends in order.
This is the half of the encoder that was missing. WriteArray takes children that are already finished byte slices, so a parent cannot be written until every descendant has been built and copied; the cost of that scales with the depth of the tree. Appending a header instead lets a nested structure be written in one pass into one buffer.
func AppendFloat ¶
AppendFloat appends a float in the shortest form that round-trips, which is what makes float output deterministic. A wire Profile refuses floats outright; this exists for the world profile and for COSE.
func AppendMapHeader ¶
AppendMapHeader appends a definite-length map head for n key/value pairs.
Nothing sorts the pairs the caller then appends. A streaming writer cannot: sorting needs every key at once, which is the shape this exists to avoid. Generated code knows its field set before it runs and can emit the pairs in order; hand-written callers that need the sort should keep using Encoder.WriteMap, and either way Validate under a Profile is what proves the result.
func AppendNegative ¶
AppendNegative appends the negative integer -1-arg. It reaches the whole encoded negative range, including the half below the int64 floor that AppendInt cannot express; the decoder has always been able to read that far.
func AppendRaw ¶
func AppendRaw(dst []byte, raw RawMessage) []byte
AppendRaw appends an item that is already encoded, without validating it.
func AppendText ¶
AppendText appends a text string. It does not validate UTF-8.
func AppendUint ¶
AppendUint appends an unsigned integer in its shortest form.
func Validate ¶
func Validate(data []byte, opts DecoderOptions) error
Validate checks that data contains exactly one bounded CBOR item.
Types ¶
type Appender ¶
Appender is implemented by a type that carries its own CBOR encoding.
AppendCBORTo appends exactly one complete CBOR item to dst and returns the extended buffer, the way the strconv.Append and time.AppendFormat families do. It takes a destination rather than returning a fresh slice because a value returning bytes allocates once per value and undoes the caller's buffer pooling at every nested field, which a message per player per tick cannot afford.
It returns no error. The append path below this point carries none, and the obligation that creates is on the implementation: for every value of the type, it must append one valid, complete CBOR item. Nothing here can check that, so an encoder that cares -- one writing under a Profile -- should validate the bytes a foreign implementation appended before they reach the wire. See Profile.ValidateAppended.
type Decodable ¶
Decodable is implemented by a type that carries its own CBOR decoding.
DecodeCBORFrom decodes the single CBOR item in data into the receiver, which must be a pointer. data holds exactly one item and nothing after it; Reader.ReadRaw is what produces it, at whatever depth the field sits.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder incrementally reads CBOR from an io.Reader without io.ReadAll. ReadToken exposes container boundaries; typed Read methods are conveniences that reject a token of the wrong kind.
Example ¶
data := []byte{0xa2, 0x01, 0x02, 0x20, 0x42, 0xca, 0xfe}
d, _ := NewDecoder(bytes.NewReader(data), DecoderOptions{RejectDuplicateMapKeys: true})
pairs, _, _ := d.ReadMap()
fmt.Println(pairs)
Output: 2
func NewDecoder ¶
func NewDecoder(r io.Reader, opts DecoderOptions) (*Decoder, error)
func (*Decoder) ReadRaw ¶
func (d *Decoder) ReadRaw() (RawMessage, error)
ReadRaw reads and validates exactly one item while retaining at most MaxRawMessageBytes. In non-sequence mode it also rejects trailing data.
type DecoderOptions ¶
type DecoderOptions struct {
MaxInputBytes int64
MaxNestedLevels int
MaxContainerItems int
MaxStringBytes int
MaxRawMessageBytes int
RejectDuplicateMapKeys bool
Sequence bool
// RejectFloats refuses every float on input. Under a profile that carries
// scaled integers, a float on the wire is a protocol violation rather than
// a value, and catching it here makes it an error on the receiving side
// instead of a disagreement about what the message meant.
RejectFloats bool
}
DecoderOptions controls resource limits and stream behavior. A zero limit selects a conservative default. Negative limits are rejected by NewDecoder.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder writes deterministic RFC 8949. Each method writes one complete item. WriteArray and WriteMap validate their child RawMessages before writing; WriteMap sorts keys under EncoderOptions.KeyOrder, which defaults to the length-first ordering CTAP2 and COSE require rather than to RFC 8949 Core Deterministic Encoding. Indefinite-length output is not supported, because it cannot be deterministic.
Example ¶
var out bytes.Buffer
e, _ := NewEncoder(&out, EncoderOptions{})
key, _ := MarshalText("alg")
_ = e.WriteMap([]MapEntry{{Key: key, Value: MarshalInt(-7)}})
fmt.Println(len(out.Bytes()))
Output: 6
func NewEncoder ¶
func NewEncoder(w io.Writer, opts EncoderOptions) (*Encoder, error)
Example ¶
package main
import (
"bytes"
"fmt"
"github.com/shibukawa/tinygodriver/encoding/cbor"
)
func main() {
var encoded bytes.Buffer
encoder, err := cbor.NewEncoder(&encoded, cbor.EncoderOptions{})
if err != nil {
panic(err)
}
if err := encoder.WriteText("ok"); err != nil {
panic(err)
}
fmt.Printf("%x\n", encoded.Bytes())
}
Output: 626f6b
func (*Encoder) Reset ¶
Reset points the Encoder at a new writer, keeping its options, so a session can hold one encoder instead of allocating one per message.
func (*Encoder) WriteArray ¶
func (e *Encoder) WriteArray(items []RawMessage) error
func (*Encoder) WriteBytes ¶
func (*Encoder) WriteFloat ¶
func (*Encoder) WriteNegative ¶
WriteNegative writes the negative integer -1-arg. See AppendNegative.
func (*Encoder) WriteRaw ¶
func (e *Encoder) WriteRaw(raw RawMessage) error
WriteRaw writes one already deterministic item after validating it.
type EncoderOptions ¶
type EncoderOptions struct {
MaxNestedLevels int
MaxContainerItems int
MaxStringBytes int
// KeyOrder selects the map key ordering WriteMap emits and WriteRaw
// enforces. The zero value keeps the CTAP2 and COSE ordering.
KeyOrder KeyOrder
}
EncoderOptions controls deterministic output limits and the map key ordering. Zero selects a conservative default. Indefinite-length output is deliberately unsupported.
type Error ¶
type Error struct {
// Offset is the byte position in the input at which the failing item began.
Offset int64
// Path names the container route to the failing item where one is known,
// as it would be written in diagnostic notation, and is empty otherwise.
Path string
Err error
}
Error locates a decode failure. It wraps one of the package sentinels, so errors.Is keeps working unchanged, and adds the offset at which the failing item began.
A byte-format error is otherwise only as useful as the caller's ability to find it. Rejecting one attestation needs the sentinel; comparing two builds that disagree about a message needs the position.
type KeyOrder ¶
type KeyOrder uint8
KeyOrder selects which deterministic map key ordering an Encoder emits and enforces. RFC 8949 defines two, and they produce different bytes for the same map, so the choice is part of the wire contract rather than an internal detail. The zero value is LengthFirstKeyOrder.
const ( // LengthFirstKeyOrder sorts shorter encoded keys first and breaks ties // bytewise. This is the length-first ordering of RFC 8949 section 4.2.3, // which is what CTAP2 canonical CBOR and COSE require. LengthFirstKeyOrder KeyOrder = iota // BytewiseKeyOrder sorts bytewise lexicographically over the whole encoded // key with no length pass. This is RFC 8949 section 4.2.1 Core // Deterministic Encoding. BytewiseKeyOrder )
type MapEntry ¶
type MapEntry struct {
Key RawMessage
Value RawMessage
}
MapEntry is one encoded key/value pair for Encoder.WriteMap. Key and Value must each contain exactly one CBOR item. Keys are sorted according to Core Deterministic Encoding before they are written.
type Profile ¶
type Profile struct {
// contains filtered or unexported fields
}
A Profile is a named restriction on what CBOR is legal, so a caller names the shape it wants rather than assembling limits by hand and hoping both ends assembled the same ones.
A Profile only enforces. It never infers which profile a message should be read under; that belongs to the schema and to the caller.
func Wire ¶
func Wire() Profile
Wire returns the compact profile for realtime messages.
A struct encodes as a fixed-order array with no field names, which is what makes it small and what makes a version mismatch undetectable from the bytes alone: there is nothing in the message to disagree about a field with. That is why the protocol version has to be agreed before any message is read, rather than negotiated per field.
Numerics are scaled integers. Floats are refused outright, at encode and at decode, so a float that reaches the wire is a caught protocol violation rather than two peers drifting apart.
Nesting is not restricted beyond the package's stack safety net. A wire message is shallow in practice, but bounding that would make every envelope over one -- a patch, a delta, a log entry quoting a message -- something the caller has to do arithmetic about, for no protection the restriction on maps, tags and floats does not already give.
func World ¶
func World() Profile
World returns the evolvable profile for snapshots and episode logs.
It admits maps, optional fields and tags, so a schema can grow, and it holds map keys in bytewise order -- RFC 8949 section 4.2.1 Core Deterministic Encoding -- rather than the length-first order CTAP2 requires, because nothing here is COSE.
Its bounds are larger than the wire profile's because a snapshot is larger than a tick. In particular MaxRawMessageBytes is set deliberately: duplicate key detection retains a whole root item, and the 1 MiB default would refuse snapshots this profile is meant to carry.
func (Profile) AllowingFloats ¶
AllowingFloats returns a copy of p that admits floats. A profile carrying scaled integers should not need it; it exists so that a caller who has decided otherwise says so at the call site rather than by editing a preset.
func (Profile) DecoderOptions ¶
func (p Profile) DecoderOptions() DecoderOptions
DecoderOptions returns the limits this profile implies, for NewDecoder or NewReader.
func (Profile) EncoderOptions ¶
func (p Profile) EncoderOptions() EncoderOptions
EncoderOptions returns the limits and key ordering this profile implies.
func (Profile) MaxContainerItems ¶ added in v1.2.6
MaxContainerItems reports the container bound.
func (Profile) MaxInputBytes ¶ added in v1.2.6
MaxInputBytes reports the input bound.
func (Profile) MaxNestedLevels ¶ added in v1.2.6
MaxNestedLevels reports the nesting bound, so a caller wrapping messages of this profile in an envelope can derive its own bound from it rather than guess one. See the note on Validate for the arithmetic.
func (Profile) ReaderOver ¶
ReaderOver returns a Reader by value with this profile's limits. See ReaderOver.
func (Profile) Validate ¶
Validate reports whether data is exactly one item legal under p. It answers the question without decoding the item into anything, which is what makes it usable as a boundary check on bytes from somewhere else.
Depth arithmetic ¶
Neither profile bounds nesting to anything a schema would meet: both take the package default, which is a stack safety net rather than a budget. What follows matters only for a caller who narrows it deliberately.
Validate walks the whole document, so nesting adds up: an envelope that wraps a message costs the envelope's depth plus the message's. A patch or delta carrying a subtree of a document is therefore deeper than the document, and a profile whose bound only just fits its messages will refuse patches of them.
Reading does not add up the same way. Reader.ReadRaw measures the captured item from zero, so decoding an envelope field by field and handing each payload on as raw bytes costs the larger of the two depths rather than their sum. An envelope needing 7 as one document decodes under a bound of 6 that way, and Validate still refuses it.
Where the two must agree -- validating untrusted bytes before decoding them -- the bound has to cover the sum. Derive it rather than guess it:
envelope := World().WithMaxNestedLevels(World().MaxNestedLevels() + 3)
Three is what a patch of the shape [base, [[op, [path...], value], ...]] adds over the value it carries.
func (Profile) ValidateAppended ¶
ValidateAppended checks the item a foreign AppendCBORTo just wrote, given the buffer and the length it had before the call.
A type that carries its own encoding cannot be made to honour a profile by the type system: nothing stops it appending a float, an indefinite-length item, or an unsorted map into a message that must not contain one. Nothing downstream would notice either, because the bytes are well-formed CBOR -- they are simply not the CBOR this profile promised. Running this after the call is what turns that from a silent divergence into an error.
func (Profile) WithMaxInputBytes ¶
WithMaxInputBytes returns a copy of p with a different input bound.
func (Profile) WithMaxNestedLevels ¶ added in v1.2.6
WithMaxNestedLevels returns a copy of p with a different nesting bound.
type RawMessage ¶
type RawMessage []byte
RawMessage holds exactly one validated CBOR item when returned by Decoder. Callers constructing RawMessage directly should pass it through Validate or Encoder.WriteRaw before trusting it.
func MarshalBool ¶
func MarshalBool(v bool) RawMessage
func MarshalBytes ¶
func MarshalBytes(v []byte) RawMessage
func MarshalFloat ¶
func MarshalFloat(v float64) RawMessage
func MarshalInt ¶
func MarshalInt(v int64) RawMessage
func MarshalNegative ¶
func MarshalNegative(arg uint64) RawMessage
MarshalNegative returns the negative integer -1-arg as a RawMessage, reaching the range MarshalInt cannot. See AppendNegative.
func MarshalNull ¶
func MarshalNull() RawMessage
func MarshalText ¶
func MarshalText(v string) (RawMessage, error)
func MarshalUint ¶
func MarshalUint(v uint64) RawMessage
Raw constructors make deterministic primitive values convenient to use in WriteArray and WriteMap.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader decodes CBOR from a byte slice already in memory. It is the counterpart of Decoder for callers that have the whole item: it borrows strings from the input instead of copying them, skips an item without allocating it, and captures a sub-item at any depth, none of which an incremental io.Reader decoder can do.
Every slice a Reader returns aliases the input. They stay valid for as long as the caller keeps the input alive and does not modify it; Reset severs nothing, so a slice from a previous input outlives the Reader but not the bytes behind it. Callers that need independent storage should copy.
A Reader is not safe for concurrent use. Reuse one per connection rather than allocating one per message; that is what Reset is for.
Nesting ¶
Skip, ReadRaw and Profile.Validate drive their own recursion and bound it by DecoderOptions.MaxNestedLevels. ReadArrayHeader and ReadMapHeader do not: they read one head and return, and the walk over the container is the caller's own loop, so its depth is the caller's to bound. This differs from Decoder, which keeps a frame stack and refuses a container past the limit from ReadToken.
The difference is deliberate. A frame stack is the state a Reader does not keep, and keeping one would cost an allocation per reader in the path that exists to have none. For untrusted input, call Profile.Validate first: it answers whether the bytes are legal under a bound without decoding them into anything, and generated code walking a fixed schema then recurses no deeper than the schema does.
func NewReader ¶
func NewReader(data []byte, opts DecoderOptions) (*Reader, error)
NewReader returns a Reader over data. A zero limit in opts selects the same conservative default NewDecoder uses.
func ReaderOver ¶
func ReaderOver(data []byte, opts DecoderOptions) Reader
ReaderOver returns a Reader by value, for a caller that wants it on the stack.
NewReader returns a pointer, which escapes, and a DecodeCBORFrom implementation runs once per field per message: at that rate the constructor is the allocation. A negative limit is treated as unset here rather than refused, because there is no error to return.
func (*Reader) Offset ¶
Offset reports how many bytes have been consumed, which is where the next item begins.
func (*Reader) Peek ¶
Peek reports the kind of the next item without consuming it. It is the way to branch on an optional field: a caller that would otherwise have to capture and rewind can dispatch instead.
func (*Reader) ReadArrayHeader ¶
ReadArrayHeader reads an array head and returns its length. A definite-length array reports indefinite false and its item count; an indefinite one reports true and a length of -1, and ends at the item Peek reports as EndArray.
It bounds the item count but not the nesting depth, which the caller's own walk owns. See the Nesting section of the Reader documentation.
func (*Reader) ReadInt ¶
ReadInt reads an integer of either sign. A negative integer outside the int64 range is ErrIntegerOverflow; ReadRaw preserves it where the value itself is needed.
func (*Reader) ReadInt8 ¶
Sized integer reads. The encoder writes the shortest form, so a field declared int32 arrives as anything from one to five bytes and its width is carried by the schema rather than the bytes. These enforce the declared width, so a value outside it is a protocol error rather than a silent wrap.
func (*Reader) ReadMapHeader ¶
ReadMapHeader reads a map head and returns its pair count, on the same terms as ReadArrayHeader, nesting included.
func (*Reader) ReadRaw ¶
func (r *Reader) ReadRaw() (RawMessage, error)
ReadRaw returns the bytes of exactly one item, at whatever depth the Reader currently sits, and advances past it. The result aliases the input.
This is the primitive a type that carries its own decoding needs: a field of a foreign type is always nested inside something, and handing that type its own bytes is the only way to decode it without knowing its shape.
The captured item is measured from zero against MaxNestedLevels, so the depth already spent reaching it does not count against it. Decoding an envelope field by field therefore costs the larger of the envelope's depth and its payload's, where validating the whole document at once costs their sum. See Profile.Validate.
func (*Reader) ReadTextBytes ¶
ReadTextBytes returns a text string borrowed from the input, without the allocation ReadText's string conversion costs.
func (*Reader) ReadUint16 ¶
func (*Reader) ReadUint32 ¶
func (*Reader) ReadUint64 ¶
ReadUint64 is ReadUint under the name the sized set uses.
func (*Reader) Reset ¶
Reset points the Reader at a new input, keeping its options. Slices returned before the call still alias the old input.
type Token ¶
type Token struct {
Kind TokenKind
Argument uint64
Bytes []byte
Text string
Bool bool
Float float64
Length int
Indefinite bool
}
Token is a typed CBOR token. Argument stores the unsigned argument for integers and tags. A NegativeInteger represents -1-Argument, retaining the full RFC 8949 range even when it cannot fit in int64.