Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
44
vendor/github.com/polydawn/refmt/cbor/cborCommon.go
generated
vendored
Normal file
44
vendor/github.com/polydawn/refmt/cbor/cborCommon.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package cbor
|
||||
|
||||
// "Major types" enum, as per https://tools.ietf.org/html/rfc7049#section-2.1 .
|
||||
//
|
||||
// These numbers are the bottom of the range for that major type when encoded;
|
||||
// that is, ints can be between `cborMajorUint` (inclusive) and `cborMajorNegInt` (exclusive).
|
||||
// Zero out the 0x1f bitrange of a byte to see which major type it is (those bits are
|
||||
// used for packing either length info or other specific enumerated meanings).
|
||||
const (
|
||||
cborMajorUint byte = 0x00
|
||||
cborMajorNegInt = 0x20
|
||||
cborMajorBytes = 0x40
|
||||
cborMajorString = 0x60
|
||||
cborMajorArray = 0x80
|
||||
cborMajorMap = 0xa0
|
||||
cborMajorTag = 0xc0
|
||||
cborMajorSimple = 0xe0 // Floating point, "simple" types like bool, etc, are above.
|
||||
)
|
||||
|
||||
// Enumeration of some values with single fixed-byte representations.
|
||||
// All of these are in the "simple" space.
|
||||
// See https://tools.ietf.org/html/rfc7049#section-2.3 for tables.
|
||||
// The prefix indicating a float is also packed into the simple space.
|
||||
const (
|
||||
cborSigilFalse byte = 0xf4
|
||||
cborSigilTrue = 0xf5
|
||||
cborSigilNil = 0xf6
|
||||
cborSigilUndefined = 0xf7
|
||||
cborSigilFloat16 = 0xf9
|
||||
cborSigilFloat32 = 0xfA
|
||||
cborSigilFloat64 = 0xfB
|
||||
)
|
||||
|
||||
// The highest value in the range for bytes, text, arrays, and maps all indicate
|
||||
// an "indefinite length" / "streaming" entry coming up. These have a different parse path.
|
||||
// The special 'break' value from the "simple" space (all bits on)
|
||||
// indicates termination of stream for all four kinds major types in this mode.
|
||||
const (
|
||||
cborSigilIndefiniteBytes byte = 0x5f
|
||||
cborSigilIndefiniteString = 0x7f
|
||||
cborSigilIndefiniteArray = 0x9f
|
||||
cborSigilIndefiniteMap = 0xbf
|
||||
cborSigilBreak = 0xff
|
||||
)
|
||||
309
vendor/github.com/polydawn/refmt/cbor/cborDecoder.go
generated
vendored
Normal file
309
vendor/github.com/polydawn/refmt/cbor/cborDecoder.go
generated
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/polydawn/refmt/shared"
|
||||
. "github.com/polydawn/refmt/tok"
|
||||
)
|
||||
|
||||
type Decoder struct {
|
||||
cfg DecodeOptions
|
||||
r shared.SlickReader
|
||||
|
||||
stack []decoderPhase // When empty, and step returns done, all done.
|
||||
phase decoderPhase // Shortcut to end of stack.
|
||||
left []int // Statekeeping space for definite-len map and array.
|
||||
}
|
||||
|
||||
type decoderPhase uint8
|
||||
|
||||
const (
|
||||
decoderPhase_acceptValue decoderPhase = iota
|
||||
decoderPhase_acceptArrValueOrBreak
|
||||
decoderPhase_acceptMapIndefKey
|
||||
decoderPhase_acceptMapIndefValueOrBreak
|
||||
decoderPhase_acceptArrValue
|
||||
decoderPhase_acceptMapKey
|
||||
decoderPhase_acceptMapValue
|
||||
)
|
||||
|
||||
func NewDecoder(cfg DecodeOptions, r io.Reader) (d *Decoder) {
|
||||
d = &Decoder{
|
||||
cfg: cfg,
|
||||
r: shared.NewReader(r),
|
||||
stack: make([]decoderPhase, 0, 10),
|
||||
left: make([]int, 0, 10),
|
||||
}
|
||||
d.phase = decoderPhase_acceptValue
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Decoder) Reset() {
|
||||
d.stack = d.stack[0:0]
|
||||
d.phase = decoderPhase_acceptValue
|
||||
d.left = d.left[0:0]
|
||||
}
|
||||
|
||||
type decoderStep func(tokenSlot *Token) (done bool, err error)
|
||||
|
||||
func (d *Decoder) Step(tokenSlot *Token) (done bool, err error) {
|
||||
switch d.phase {
|
||||
case decoderPhase_acceptValue:
|
||||
done, err = d.step_acceptValue(tokenSlot)
|
||||
case decoderPhase_acceptArrValueOrBreak:
|
||||
done, err = d.step_acceptArrValueOrBreak(tokenSlot)
|
||||
case decoderPhase_acceptMapIndefKey:
|
||||
done, err = d.step_acceptMapIndefKey(tokenSlot)
|
||||
case decoderPhase_acceptMapIndefValueOrBreak:
|
||||
done, err = d.step_acceptMapIndefValueOrBreak(tokenSlot)
|
||||
case decoderPhase_acceptArrValue:
|
||||
done, err = d.step_acceptArrValue(tokenSlot)
|
||||
case decoderPhase_acceptMapKey:
|
||||
done, err = d.step_acceptMapKey(tokenSlot)
|
||||
case decoderPhase_acceptMapValue:
|
||||
done, err = d.step_acceptMapValue(tokenSlot)
|
||||
}
|
||||
// If the step errored: out, entirely.
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
// If the step wasn't done, return same status.
|
||||
if !done {
|
||||
return false, nil
|
||||
}
|
||||
// If it WAS done, pop next, or if stack empty, we're entirely done.
|
||||
nSteps := len(d.stack) - 1
|
||||
if nSteps <= 0 {
|
||||
return true, nil // that's all folks
|
||||
}
|
||||
d.phase = d.stack[nSteps]
|
||||
d.stack = d.stack[0:nSteps]
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) pushPhase(newPhase decoderPhase) {
|
||||
d.stack = append(d.stack, d.phase)
|
||||
d.phase = newPhase
|
||||
}
|
||||
|
||||
// The original step, where any value is accepted, and no terminators for composites are valid.
|
||||
// ONLY used in the original step; all other steps handle leaf nodes internally.
|
||||
func (d *Decoder) step_acceptValue(tokenSlot *Token) (done bool, err error) {
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
tokenSlot.Tagged = false
|
||||
return d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
}
|
||||
|
||||
// Step in midst of decoding an indefinite-length array.
|
||||
func (d *Decoder) step_acceptArrValueOrBreak(tokenSlot *Token) (done bool, err error) {
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
tokenSlot.Tagged = false
|
||||
switch majorByte {
|
||||
case cborSigilBreak:
|
||||
tokenSlot.Type = TArrClose
|
||||
return true, nil
|
||||
default:
|
||||
_, err := d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Step in midst of decoding an indefinite-length map, key expected up next, or end.
|
||||
func (d *Decoder) step_acceptMapIndefKey(tokenSlot *Token) (done bool, err error) {
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
tokenSlot.Tagged = false
|
||||
switch majorByte {
|
||||
case cborSigilBreak:
|
||||
tokenSlot.Type = TMapClose
|
||||
return true, nil
|
||||
default:
|
||||
d.phase = decoderPhase_acceptMapIndefValueOrBreak
|
||||
_, err := d.stepHelper_acceptValue(majorByte, tokenSlot) // FIXME surely not *any* value? not composites, at least?
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Step in midst of decoding an indefinite-length map, value expected up next.
|
||||
func (d *Decoder) step_acceptMapIndefValueOrBreak(tokenSlot *Token) (done bool, err error) {
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
tokenSlot.Tagged = false
|
||||
switch majorByte {
|
||||
case cborSigilBreak:
|
||||
return true, fmt.Errorf("unexpected break; expected value in indefinite-length map")
|
||||
default:
|
||||
d.phase = decoderPhase_acceptMapIndefKey
|
||||
_, err = d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Step in midst of decoding a definite-length array.
|
||||
func (d *Decoder) step_acceptArrValue(tokenSlot *Token) (done bool, err error) {
|
||||
// Yield close token, pop state, and return done flag if expecting no more entries.
|
||||
ll := len(d.left) - 1
|
||||
if d.left[ll] == 0 {
|
||||
d.left = d.left[0:ll]
|
||||
tokenSlot.Type = TArrClose
|
||||
return true, nil
|
||||
}
|
||||
d.left[ll]--
|
||||
// Read next value.
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
tokenSlot.Tagged = false
|
||||
_, err = d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Step in midst of decoding an definite-length map, key expected up next.
|
||||
func (d *Decoder) step_acceptMapKey(tokenSlot *Token) (done bool, err error) {
|
||||
// Yield close token, pop state, and return done flag if expecting no more entries.
|
||||
ll := len(d.left) - 1
|
||||
if d.left[ll] == 0 {
|
||||
d.left = d.left[0:ll]
|
||||
tokenSlot.Type = TMapClose
|
||||
return true, nil
|
||||
}
|
||||
d.left[ll]--
|
||||
// Read next key.
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
d.phase = decoderPhase_acceptMapValue
|
||||
tokenSlot.Tagged = false
|
||||
_, err = d.stepHelper_acceptValue(majorByte, tokenSlot) // FIXME surely not *any* value? not composites, at least?
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Step in midst of decoding an definite-length map, value expected up next.
|
||||
func (d *Decoder) step_acceptMapValue(tokenSlot *Token) (done bool, err error) {
|
||||
// Read next value.
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
d.phase = decoderPhase_acceptMapKey
|
||||
tokenSlot.Tagged = false
|
||||
_, err = d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (d *Decoder) stepHelper_acceptValue(majorByte byte, tokenSlot *Token) (done bool, err error) {
|
||||
switch majorByte {
|
||||
case cborSigilNil:
|
||||
tokenSlot.Type = TNull
|
||||
return true, nil
|
||||
case cborSigilUndefined:
|
||||
if d.cfg.CoerceUndefToNull {
|
||||
tokenSlot.Type = TNull
|
||||
return true, nil
|
||||
}
|
||||
return true, fmt.Errorf("encountered cbor 'undefined' byte (%x) during decoding", cborSigilUndefined)
|
||||
case cborSigilFalse:
|
||||
tokenSlot.Type = TBool
|
||||
tokenSlot.Bool = false
|
||||
return true, nil
|
||||
case cborSigilTrue:
|
||||
tokenSlot.Type = TBool
|
||||
tokenSlot.Bool = true
|
||||
return true, nil
|
||||
case cborSigilFloat16, cborSigilFloat32, cborSigilFloat64:
|
||||
tokenSlot.Type = TFloat64
|
||||
tokenSlot.Float64, err = d.decodeFloat(majorByte)
|
||||
return true, err
|
||||
case cborSigilIndefiniteBytes:
|
||||
tokenSlot.Type = TBytes
|
||||
tokenSlot.Bytes, err = d.decodeBytesIndefinite(nil)
|
||||
return true, err
|
||||
case cborSigilIndefiniteString:
|
||||
tokenSlot.Type = TString
|
||||
tokenSlot.Str, err = d.decodeStringIndefinite()
|
||||
return true, err
|
||||
case cborSigilIndefiniteArray:
|
||||
tokenSlot.Type = TArrOpen
|
||||
tokenSlot.Length = -1
|
||||
d.pushPhase(decoderPhase_acceptArrValueOrBreak)
|
||||
return false, nil
|
||||
case cborSigilIndefiniteMap:
|
||||
tokenSlot.Type = TMapOpen
|
||||
tokenSlot.Length = -1
|
||||
d.pushPhase(decoderPhase_acceptMapIndefKey)
|
||||
return false, nil
|
||||
default:
|
||||
switch {
|
||||
case majorByte >= cborMajorUint && majorByte < cborMajorNegInt:
|
||||
tokenSlot.Type = TUint
|
||||
tokenSlot.Uint, err = d.decodeUint(majorByte)
|
||||
return true, err
|
||||
case majorByte >= cborMajorNegInt && majorByte < cborMajorBytes:
|
||||
tokenSlot.Type = TInt
|
||||
tokenSlot.Int, err = d.decodeNegInt(majorByte)
|
||||
return true, err
|
||||
case majorByte >= cborMajorBytes && majorByte < cborMajorString:
|
||||
tokenSlot.Type = TBytes
|
||||
tokenSlot.Bytes, err = d.decodeBytes(majorByte)
|
||||
return true, err
|
||||
case majorByte >= cborMajorString && majorByte < cborMajorArray:
|
||||
tokenSlot.Type = TString
|
||||
tokenSlot.Str, err = d.decodeString(majorByte)
|
||||
return true, err
|
||||
case majorByte >= cborMajorArray && majorByte < cborMajorMap:
|
||||
var n int
|
||||
n, err = d.decodeLen(majorByte)
|
||||
tokenSlot.Type = TArrOpen
|
||||
tokenSlot.Length = n
|
||||
d.left = append(d.left, n)
|
||||
d.pushPhase(decoderPhase_acceptArrValue)
|
||||
return false, err
|
||||
case majorByte >= cborMajorMap && majorByte < cborMajorTag:
|
||||
var n int
|
||||
n, err = d.decodeLen(majorByte)
|
||||
tokenSlot.Type = TMapOpen
|
||||
tokenSlot.Length = n
|
||||
d.left = append(d.left, n)
|
||||
d.pushPhase(decoderPhase_acceptMapKey)
|
||||
return false, err
|
||||
case majorByte >= cborMajorTag && majorByte < cborMajorSimple:
|
||||
// CBOR tags are, frankly, bonkers, and should not be used.
|
||||
// They break isomorphism to basic standards like JSON.
|
||||
// We'll parse basic integer tag values -- SINGLE layer only.
|
||||
// We will NOT parse the full gamut of recursive tags: doing so
|
||||
// would mean allowing an unbounded number of allocs *during
|
||||
// *processing of a single token*, which is _not reasonable_.
|
||||
if tokenSlot.Tagged {
|
||||
return true, fmt.Errorf("unsupported multiple tags on a single data item")
|
||||
}
|
||||
tokenSlot.Tagged = true
|
||||
tokenSlot.Tag, err = d.decodeLen(majorByte)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
// Okay, we slurped a tag.
|
||||
// Read next value.
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return d.stepHelper_acceptValue(majorByte, tokenSlot)
|
||||
default:
|
||||
return true, fmt.Errorf("Invalid majorByte: 0x%x", majorByte)
|
||||
}
|
||||
}
|
||||
}
|
||||
235
vendor/github.com/polydawn/refmt/cbor/cborDecoderTerminals.go
generated
vendored
Normal file
235
vendor/github.com/polydawn/refmt/cbor/cborDecoderTerminals.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
maxUint = ^uint(0)
|
||||
maxInt = int(maxUint >> 1)
|
||||
)
|
||||
|
||||
func (d *Decoder) decodeFloat(majorByte byte) (f float64, err error) {
|
||||
var bs []byte
|
||||
switch majorByte {
|
||||
case cborSigilFloat16:
|
||||
bs, err = d.r.Readnzc(2)
|
||||
f = float64(math.Float32frombits(halfFloatToFloatBits(binary.BigEndian.Uint16(bs))))
|
||||
case cborSigilFloat32:
|
||||
bs, err = d.r.Readnzc(4)
|
||||
f = float64(math.Float32frombits(binary.BigEndian.Uint32(bs)))
|
||||
case cborSigilFloat64:
|
||||
bs, err = d.r.Readnzc(8)
|
||||
f = math.Float64frombits(binary.BigEndian.Uint64(bs))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Decode an unsigned int.
|
||||
// Must continue to hand down the majorByte because some of its bits are either
|
||||
// packed with the value outright, or tell us how many more bytes the value fills.
|
||||
func (d *Decoder) decodeUint(majorByte byte) (ui uint64, err error) {
|
||||
v := majorByte & 0x1f
|
||||
if v <= 0x17 {
|
||||
ui = uint64(v)
|
||||
} else {
|
||||
if v == 0x18 {
|
||||
var b byte
|
||||
b, err = d.r.Readn1()
|
||||
ui = uint64(b)
|
||||
} else if v == 0x19 {
|
||||
var bs []byte
|
||||
bs, err = d.r.Readnzc(2)
|
||||
ui = uint64(binary.BigEndian.Uint16(bs))
|
||||
} else if v == 0x1a {
|
||||
var bs []byte
|
||||
bs, err = d.r.Readnzc(4)
|
||||
ui = uint64(binary.BigEndian.Uint32(bs))
|
||||
} else if v == 0x1b {
|
||||
var bs []byte
|
||||
bs, err = d.r.Readnzc(8)
|
||||
ui = uint64(binary.BigEndian.Uint64(bs))
|
||||
} else {
|
||||
err = fmt.Errorf("decodeUint: Invalid descriptor: %v", majorByte)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Decode a *negative* integer.
|
||||
// Note that CBOR has a very funny-shaped hole here: there is unsigned positive int,
|
||||
// and there is explicitly negative signed int... and there is no signed, positive int.
|
||||
// *We have no 'decodeInt' function because that **doesn't exist** in CBOR.*
|
||||
// So! Hopefully our consumer doesn't mind having to cast uints to ints fairly frequently.
|
||||
func (d *Decoder) decodeNegInt(majorByte byte) (i int64, err error) {
|
||||
// The packed bits in the majorByte and the following bytes if any are layed out
|
||||
// the exact same as a uint; only the major type bits are different.
|
||||
ui, err := d.decodeUint(majorByte)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
pos := ui + 1
|
||||
if pos > uint64(-math.MinInt64) {
|
||||
return -1, errors.New("cbor: negative integer out of rage of int64 type")
|
||||
}
|
||||
|
||||
return -int64(pos), nil
|
||||
}
|
||||
|
||||
// Decode expecting a positive integer.
|
||||
// None of our token-yielding functions call this directly;
|
||||
// it's used inside the library when we expect to read e.g. a length header.
|
||||
// Does not check that your majorByte indicates an integer type at all;
|
||||
// in context, it often doesn't, e.g. when decoding the length of a string.
|
||||
func (d *Decoder) decodeLen(majorByte byte) (i int, err error) {
|
||||
ui, err := d.decodeUint(majorByte)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if ui > uint64(maxInt) {
|
||||
return 0, errors.New("cbor: positive integer is out of length")
|
||||
}
|
||||
return int(ui), nil
|
||||
}
|
||||
|
||||
// Decoding indefinite-length byte strings in cbor is actually decoding a sequence of
|
||||
// definite-length byte strings until you encounter a break.
|
||||
// Caller: use `bs[:0]` if you have something to reuse, or nil
|
||||
func (d *Decoder) decodeBytesIndefinite(bs []byte) (bsOut []byte, err error) {
|
||||
return d.decodeBytesOrStringIndefinite(bs, cborMajorBytes)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeStringIndefinite() (s string, err error) {
|
||||
bs, err := d.decodeBytesOrStringIndefinite(nil, cborMajorString)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bs), nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeBytesOrStringIndefinite(bs []byte, majorWanted byte) (bsOut []byte, err error) {
|
||||
if bs == nil {
|
||||
bs = make([]byte, 0, 16)
|
||||
}
|
||||
var n int
|
||||
for {
|
||||
// Read first byte; check for break, or hunk, or invalid.
|
||||
// (It's not necessary to have the first majorByte as a param to this function, because
|
||||
// indefinite length sequences have a separate sigil which doesn't pack any len info.)
|
||||
majorByte, err := d.r.Readn1()
|
||||
if err != nil {
|
||||
return bs, err
|
||||
}
|
||||
if majorByte == cborSigilBreak {
|
||||
return bs, nil
|
||||
} else if major := majorByte | 0x1f - 0x1f; major != majorWanted {
|
||||
return bs, fmt.Errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, majorByte)
|
||||
}
|
||||
// Read length header for this hunk, and ensure we have at least that much cap.
|
||||
n, err = d.decodeLen(majorByte)
|
||||
if err != nil {
|
||||
return bs, err
|
||||
}
|
||||
oldLen := len(bs)
|
||||
newLen := oldLen + n
|
||||
if n > 33554432 {
|
||||
return nil, fmt.Errorf("cbor: decoding rejected oversized indefinite string/bytes field: %d is too large", n)
|
||||
}
|
||||
if newLen > cap(bs) {
|
||||
bs2 := make([]byte, newLen, 2*cap(bs)+n)
|
||||
copy(bs2, bs)
|
||||
bs = bs2
|
||||
} else {
|
||||
bs = bs[:newLen]
|
||||
}
|
||||
// Read that hunk.
|
||||
d.r.Readb(bs[oldLen:newLen])
|
||||
}
|
||||
}
|
||||
|
||||
// Decode a single length-prefixed hunk of bytes.
|
||||
//
|
||||
// There are a number of ways this may try to conserve allocations:
|
||||
//
|
||||
// - If you say zerocopy=true, and the underlying reader system already has an
|
||||
// appropriate byte slice available, then a slice from that will be returned.
|
||||
//
|
||||
// - If you provide a byte slice, we will attempt to use it.
|
||||
// The byte slice is truncated and used for its capacity only -- not appended.
|
||||
// The final returned slice may be a different one if the provided slice did not
|
||||
// have sufficient capacity.
|
||||
//
|
||||
// - If you say zerocopy=true, and the underlying read system doesn't have an
|
||||
// efficient way to yield a slice of its internal buffer, and you provided no
|
||||
// destination slice, then we will use a recycleable piece of memory in the Decoder
|
||||
// state and return a slice viewing into it. For small values this will
|
||||
// likely save an alloc.
|
||||
//
|
||||
// The above rules are resolved in this order; e.g. your byte slice is disregarded
|
||||
// if zerocopy=true and the underlying reader can do something even more efficient,
|
||||
// though there is also no harm to providing the slice argument.
|
||||
// Generally, set zerocopy if you know you're not going to publicly yield the results,
|
||||
// and the implementation will do its best to be as efficient as possible.
|
||||
//
|
||||
// Zerocopy is appropriate when planning to turn the bytes into a string, for example,
|
||||
// since in that path we know the slice will be treated immutably, not publicly
|
||||
// exposed, and also any other copy to another intermediate is definitely useless.
|
||||
func (d *Decoder) decodeBytes(majorByte byte) (bs []byte, err error) {
|
||||
n, err := d.decodeLen(majorByte)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n > 33554432 {
|
||||
return nil, fmt.Errorf("cbor: decoding rejected oversized byte field: %d is too large", n)
|
||||
}
|
||||
return d.r.Readn(n)
|
||||
}
|
||||
|
||||
// Decode a single length-prefixed string.
|
||||
func (d *Decoder) decodeString(majorByte byte) (s string, err error) {
|
||||
n, err := d.decodeLen(majorByte)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if n > 33554432 {
|
||||
return "", fmt.Errorf("cbor: decoding rejected oversized string field: %d is too large", n)
|
||||
}
|
||||
bs, err := d.r.Readnzc(n)
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// culled from OGRE (Object-Oriented Graphics Rendering Engine)
|
||||
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
|
||||
func halfFloatToFloatBits(yy uint16) (d uint32) {
|
||||
y := uint32(yy)
|
||||
s := (y >> 15) & 0x01
|
||||
e := (y >> 10) & 0x1f
|
||||
m := y & 0x03ff
|
||||
|
||||
if e == 0 {
|
||||
if m == 0 { // plu or minus 0
|
||||
return s << 31
|
||||
} else { // Denormalized number -- renormalize it
|
||||
for (m & 0x00000400) == 0 {
|
||||
m <<= 1
|
||||
e -= 1
|
||||
}
|
||||
e += 1
|
||||
const zz uint32 = 0x0400
|
||||
m &= ^zz
|
||||
}
|
||||
} else if e == 31 {
|
||||
if m == 0 { // Inf
|
||||
return (s << 31) | 0x7f800000
|
||||
} else { // NaN
|
||||
return (s << 31) | 0x7f800000 | (m << 13)
|
||||
}
|
||||
}
|
||||
e = e + (127 - 15)
|
||||
m = m << 13
|
||||
return (s << 31) | (e << 23) | m
|
||||
}
|
||||
276
vendor/github.com/polydawn/refmt/cbor/cborEncoder.go
generated
vendored
Normal file
276
vendor/github.com/polydawn/refmt/cbor/cborEncoder.go
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
. "github.com/polydawn/refmt/tok"
|
||||
)
|
||||
|
||||
type Encoder struct {
|
||||
w quickWriter
|
||||
|
||||
stack []encoderPhase // When empty, and step returns done, all done.
|
||||
current encoderPhase // Shortcut to end of stack.
|
||||
// Note unlike decoder, we need no statekeeping space for definite-len map and array.
|
||||
|
||||
spareBytes []byte
|
||||
}
|
||||
|
||||
func NewEncoder(w io.Writer) (d *Encoder) {
|
||||
d = &Encoder{
|
||||
w: newQuickWriterStream(w),
|
||||
stack: make([]encoderPhase, 0, 10),
|
||||
current: phase_anyExpectValue,
|
||||
spareBytes: make([]byte, 8),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Encoder) Reset() {
|
||||
d.stack = d.stack[0:0]
|
||||
d.current = phase_anyExpectValue
|
||||
}
|
||||
|
||||
type encoderPhase byte
|
||||
|
||||
// There's about twice as many phases that the cbor encoder can be in compared to the json encoder
|
||||
// because the presense of indefinite vs definite length maps and arrays effectively adds a dimension to those.
|
||||
const (
|
||||
phase_anyExpectValue encoderPhase = iota
|
||||
phase_mapDefExpectKeyOrEnd // must not yield break at end
|
||||
phase_mapDefExpectValue // only necessary to flip back to DefExpectKey
|
||||
phase_mapIndefExpectKeyOrEnd // must yield break at end
|
||||
phase_mapIndefExpectValue // only necessary to flip back to IndefExpectKey
|
||||
phase_arrDefExpectValueOrEnd // must not yield break at end
|
||||
phase_arrIndefExpectValueOrEnd // must yield break at end
|
||||
)
|
||||
|
||||
func (d *Encoder) pushPhase(p encoderPhase) {
|
||||
d.current = p
|
||||
d.stack = append(d.stack, d.current)
|
||||
}
|
||||
|
||||
// Pop a phase from the stack; return 'true' if stack now empty.
|
||||
func (d *Encoder) popPhase() bool {
|
||||
n := len(d.stack) - 1
|
||||
if n == 0 {
|
||||
return true
|
||||
}
|
||||
if n < 0 { // the state machines are supposed to have already errored better
|
||||
panic("cborEncoder stack overpopped")
|
||||
}
|
||||
d.current = d.stack[n-1]
|
||||
d.stack = d.stack[0:n]
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *Encoder) Step(tokenSlot *Token) (done bool, err error) {
|
||||
/*
|
||||
Though it reads somewhat backwards from how a human would probably intuit
|
||||
cause and effect, switching on the token type we got first,
|
||||
*then* switching for whether it is acceptable for our current phase... is by
|
||||
far the shorter volume of code to write.
|
||||
*/
|
||||
phase := d.current
|
||||
switch tokenSlot.Type {
|
||||
case TMapOpen:
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
if tokenSlot.Length >= 0 {
|
||||
d.pushPhase(phase_mapDefExpectKeyOrEnd)
|
||||
d.emitMajorPlusLen(cborMajorMap, uint64(tokenSlot.Length))
|
||||
} else {
|
||||
d.pushPhase(phase_mapIndefExpectKeyOrEnd)
|
||||
d.w.writen1(cborSigilIndefiniteMap)
|
||||
}
|
||||
return false, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TMapClose:
|
||||
switch phase {
|
||||
case phase_mapDefExpectKeyOrEnd:
|
||||
return d.popPhase(), nil
|
||||
case phase_mapIndefExpectKeyOrEnd:
|
||||
d.w.writen1(cborSigilBreak)
|
||||
return d.popPhase(), d.w.checkErr()
|
||||
case phase_anyExpectValue, phase_mapDefExpectValue, phase_mapIndefExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForValue}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TArrOpen:
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
if tokenSlot.Length >= 0 {
|
||||
d.pushPhase(phase_arrDefExpectValueOrEnd)
|
||||
d.emitMajorPlusLen(cborMajorArray, uint64(tokenSlot.Length))
|
||||
} else {
|
||||
d.pushPhase(phase_arrIndefExpectValueOrEnd)
|
||||
d.w.writen1(cborSigilIndefiniteArray)
|
||||
}
|
||||
return false, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TArrClose:
|
||||
switch phase {
|
||||
case phase_arrDefExpectValueOrEnd:
|
||||
return d.popPhase(), nil
|
||||
case phase_arrIndefExpectValueOrEnd:
|
||||
d.w.writen1(cborSigilBreak)
|
||||
return d.popPhase(), d.w.checkErr()
|
||||
case phase_anyExpectValue, phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForValue}
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TNull: // terminal value; not accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.w.writen1(cborSigilNil)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TString: // terminal value; YES, accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
goto emitStr
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
d.current += 1
|
||||
goto emitStr
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
emitStr:
|
||||
{
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeString(tokenSlot.Str)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
}
|
||||
case TBytes: // terminal value; not accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeBytes(tokenSlot.Bytes)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TBool: // terminal value; not accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeBool(tokenSlot.Bool)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
case TInt: // terminal value; YES, accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
goto emitInt
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
d.current += 1
|
||||
goto emitInt
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
emitInt:
|
||||
{
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeInt64(tokenSlot.Int)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
}
|
||||
case TUint: // terminal value; YES, accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
goto emitUint
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
d.current += 1
|
||||
goto emitUint
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
emitUint:
|
||||
{
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeUint64(tokenSlot.Uint)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
}
|
||||
case TFloat64: // terminal value; not accepted as map key.
|
||||
switch phase {
|
||||
case phase_mapDefExpectValue, phase_mapIndefExpectValue:
|
||||
d.current -= 1
|
||||
fallthrough
|
||||
case phase_anyExpectValue, phase_arrDefExpectValueOrEnd, phase_arrIndefExpectValueOrEnd:
|
||||
if tokenSlot.Tagged {
|
||||
d.emitMajorPlusLen(cborMajorTag, uint64(tokenSlot.Tag))
|
||||
}
|
||||
d.encodeFloat64(tokenSlot.Float64)
|
||||
return phase == phase_anyExpectValue, d.w.checkErr()
|
||||
case phase_mapDefExpectKeyOrEnd, phase_mapIndefExpectKeyOrEnd:
|
||||
return true, &ErrInvalidTokenStream{Got: *tokenSlot, Acceptable: tokenTypesForKey}
|
||||
default:
|
||||
panic("unreachable phase")
|
||||
}
|
||||
default:
|
||||
panic("unhandled token type")
|
||||
}
|
||||
}
|
||||
77
vendor/github.com/polydawn/refmt/cbor/cborEncoderTerminals.go
generated
vendored
Normal file
77
vendor/github.com/polydawn/refmt/cbor/cborEncoderTerminals.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
)
|
||||
|
||||
func (d *Encoder) emitLen(majorByte byte, length int) {
|
||||
d.emitMajorPlusLen(majorByte, uint64(length))
|
||||
}
|
||||
|
||||
func (d *Encoder) emitMajorPlusLen(majorByte byte, v uint64) {
|
||||
if v <= 0x17 {
|
||||
d.w.writen1(majorByte + byte(v))
|
||||
} else if v <= math.MaxUint8 {
|
||||
d.w.writen2(majorByte+0x18, uint8(v))
|
||||
} else if v <= math.MaxUint16 {
|
||||
d.w.writen1(majorByte + 0x19)
|
||||
d.spareBytes = d.spareBytes[:2]
|
||||
binary.BigEndian.PutUint16(d.spareBytes, uint16(v))
|
||||
d.w.writeb(d.spareBytes)
|
||||
} else if v <= math.MaxUint32 {
|
||||
d.w.writen1(majorByte + 0x1a)
|
||||
d.spareBytes = d.spareBytes[:4]
|
||||
binary.BigEndian.PutUint32(d.spareBytes, uint32(v))
|
||||
d.w.writeb(d.spareBytes)
|
||||
} else { // if v <= math.MaxUint64 {
|
||||
d.w.writen1(majorByte + 0x1b)
|
||||
d.spareBytes = d.spareBytes[:8]
|
||||
binary.BigEndian.PutUint64(d.spareBytes, v)
|
||||
d.w.writeb(d.spareBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeNull() {
|
||||
d.w.writen1(cborSigilNil)
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeString(s string) {
|
||||
d.emitMajorPlusLen(cborMajorString, uint64(len(s)))
|
||||
d.w.writestr(s)
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeBytes(bs []byte) {
|
||||
d.emitMajorPlusLen(cborMajorBytes, uint64(len(bs)))
|
||||
d.w.writeb(bs)
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeBool(b bool) {
|
||||
if b {
|
||||
d.w.writen1(cborSigilTrue)
|
||||
} else {
|
||||
d.w.writen1(cborSigilFalse)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeInt64(v int64) {
|
||||
if v >= 0 {
|
||||
d.emitMajorPlusLen(cborMajorUint, uint64(v))
|
||||
} else {
|
||||
d.emitMajorPlusLen(cborMajorNegInt, uint64(-1-v))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeUint64(v uint64) {
|
||||
d.emitMajorPlusLen(cborMajorUint, v)
|
||||
}
|
||||
|
||||
func (d *Encoder) encodeFloat64(v float64) {
|
||||
// Can we pack it into 32? No idea: float precision is fraught with peril.
|
||||
// See https://play.golang.org/p/u9sN6x0kk6
|
||||
// So we *only* emit the full 64-bit style. The CBOR spec permits this.
|
||||
d.w.writen1(cborSigilFloat64)
|
||||
d.spareBytes = d.spareBytes[:8]
|
||||
binary.BigEndian.PutUint64(d.spareBytes, math.Float64bits(v))
|
||||
d.w.writeb(d.spareBytes)
|
||||
}
|
||||
106
vendor/github.com/polydawn/refmt/cbor/cborHelpers.go
generated
vendored
Normal file
106
vendor/github.com/polydawn/refmt/cbor/cborHelpers.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/polydawn/refmt/obj"
|
||||
"github.com/polydawn/refmt/obj/atlas"
|
||||
"github.com/polydawn/refmt/shared"
|
||||
)
|
||||
|
||||
// All of the methods in this file are exported,
|
||||
// and their names and type declarations are intended to be
|
||||
// identical to the naming and types of the golang stdlib
|
||||
// 'encoding/json' packages, with ONE EXCEPTION:
|
||||
// what stdlib calls "NewEncoder", we call "NewMarshaller";
|
||||
// what stdlib calls "NewDecoder", we call "NewUnmarshaller";
|
||||
// and similarly the types and methods are "Marshaller.Marshal"
|
||||
// and "Unmarshaller.Unmarshal".
|
||||
// You should be able to migrate with a sed script!
|
||||
//
|
||||
// (In refmt, the encoder/decoder systems are for token streams;
|
||||
// if you're talking about object mapping, we consistently
|
||||
// refer to that as marshalling/unmarshalling.)
|
||||
//
|
||||
// Most methods also have an "Atlased" variant,
|
||||
// which lets you specify advanced type mapping instructions.
|
||||
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := NewMarshaller(&buf).Marshal(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func MarshalAtlased(v interface{}, atl atlas.Atlas) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := NewMarshallerAtlased(&buf, atl).Marshal(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type Marshaller struct {
|
||||
marshaller *obj.Marshaller
|
||||
encoder *Encoder
|
||||
pump shared.TokenPump
|
||||
}
|
||||
|
||||
func (x *Marshaller) Marshal(v interface{}) error {
|
||||
x.marshaller.Bind(v)
|
||||
x.encoder.Reset()
|
||||
return x.pump.Run()
|
||||
}
|
||||
|
||||
func NewMarshaller(wr io.Writer) *Marshaller {
|
||||
return NewMarshallerAtlased(wr, atlas.MustBuild())
|
||||
}
|
||||
|
||||
func NewMarshallerAtlased(wr io.Writer, atl atlas.Atlas) *Marshaller {
|
||||
x := &Marshaller{
|
||||
marshaller: obj.NewMarshaller(atl),
|
||||
encoder: NewEncoder(wr),
|
||||
}
|
||||
x.pump = shared.TokenPump{
|
||||
x.marshaller,
|
||||
x.encoder,
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func Unmarshal(cfg DecodeOptions, data []byte, v interface{}) error {
|
||||
return NewUnmarshaller(cfg, bytes.NewBuffer(data)).Unmarshal(v)
|
||||
}
|
||||
|
||||
func UnmarshalAtlased(cfg DecodeOptions, data []byte, v interface{}, atl atlas.Atlas) error {
|
||||
return NewUnmarshallerAtlased(cfg, bytes.NewBuffer(data), atl).Unmarshal(v)
|
||||
}
|
||||
|
||||
type Unmarshaller struct {
|
||||
unmarshaller *obj.Unmarshaller
|
||||
decoder *Decoder
|
||||
pump shared.TokenPump
|
||||
}
|
||||
|
||||
func (x *Unmarshaller) Unmarshal(v interface{}) error {
|
||||
x.unmarshaller.Bind(v)
|
||||
x.decoder.Reset()
|
||||
return x.pump.Run()
|
||||
}
|
||||
|
||||
func NewUnmarshaller(cfg DecodeOptions, r io.Reader) *Unmarshaller {
|
||||
return NewUnmarshallerAtlased(cfg, r, atlas.MustBuild())
|
||||
}
|
||||
func NewUnmarshallerAtlased(cfg DecodeOptions, r io.Reader, atl atlas.Atlas) *Unmarshaller {
|
||||
x := &Unmarshaller{
|
||||
unmarshaller: obj.NewUnmarshaller(atl),
|
||||
decoder: NewDecoder(cfg, r),
|
||||
}
|
||||
x.pump = shared.TokenPump{
|
||||
x.decoder,
|
||||
x.unmarshaller,
|
||||
}
|
||||
return x
|
||||
}
|
||||
20
vendor/github.com/polydawn/refmt/cbor/cborOptions.go
generated
vendored
Normal file
20
vendor/github.com/polydawn/refmt/cbor/cborOptions.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package cbor
|
||||
|
||||
type EncodeOptions struct {
|
||||
// there aren't a ton of options for cbor, but we still need this
|
||||
// for use as a sigil for the top-level refmt methods to demux on.
|
||||
}
|
||||
|
||||
// marker method -- you may use this type to instruct `refmt.Marshal`
|
||||
// what kind of encoder to use.
|
||||
func (EncodeOptions) IsEncodeOptions() {}
|
||||
|
||||
type DecodeOptions struct {
|
||||
CoerceUndefToNull bool
|
||||
|
||||
// future: options to validate canonical serial order
|
||||
}
|
||||
|
||||
// marker method -- you may use this type to instruct `refmt.Marshal`
|
||||
// what kind of encoder to use.
|
||||
func (DecodeOptions) IsDecodeOptions() {}
|
||||
27
vendor/github.com/polydawn/refmt/cbor/doc.go
generated
vendored
Normal file
27
vendor/github.com/polydawn/refmt/cbor/doc.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Package implementing the CBOR -- Concise Binary Object Notation
|
||||
-- http://cbor.io/ -- spec.
|
||||
|
||||
CBOR is more or less freely interchangable with json: it's schemaless,
|
||||
and composed of similar map and array types.
|
||||
However, CBOR is binary, length delimited -- and thus very fast to parse,
|
||||
and can store binary data without expansion problems -- and also distinguishes
|
||||
types like integer, string, float, and bytes all clearly from each other.
|
||||
|
||||
The `cbor.Marshal` and `cbor.Unmarshal` functions are the quickest way
|
||||
to convert your Go objects to and from serial CBOR.
|
||||
|
||||
The `cbor.NewMarshaller` and `cbor.NewUmarshaller` functions give a little
|
||||
more control. If performance is important, prefer these; recycling
|
||||
the marshaller instances will significantly cut down on memory allocations
|
||||
and improve performance.
|
||||
|
||||
The `*Atlased` variants of constructors allow you set up marshalling with
|
||||
an `refmt/obj/atlas.Atlas`, unlocking all of refmt's advanced features
|
||||
and custom object mapping powertools.
|
||||
|
||||
The `cbor.Encoder` and `cbor.Decoder` types implement the low-level functionality
|
||||
of converting serial CBOR byte streams into refmt Token streams.
|
||||
Users don't usually need to use these directly.
|
||||
*/
|
||||
package cbor
|
||||
107
vendor/github.com/polydawn/refmt/cbor/encodeWriter.go
generated
vendored
Normal file
107
vendor/github.com/polydawn/refmt/cbor/encodeWriter.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
_ quickWriter = &quickWriterStream{}
|
||||
)
|
||||
|
||||
// quickWriter is implements several methods that are specificly useful to the performance
|
||||
// needs of our encoders, and abstracts writing to a byte array or to an io.Writer.
|
||||
type quickWriter interface {
|
||||
writeb([]byte)
|
||||
writestr(string)
|
||||
writen1(byte)
|
||||
writen2(byte, byte)
|
||||
checkErr() error
|
||||
clearErr()
|
||||
}
|
||||
|
||||
// Interface used to detect if efficient string writing is supported.
|
||||
// Same as in stdlib 'io' pkg; also not exported there, so we declare it again ourselves.
|
||||
type stringWriter interface {
|
||||
WriteString(s string) (n int, err error)
|
||||
}
|
||||
|
||||
// quickWriterStream is a quickWriter that routes bytes to an io.Writer.
|
||||
// While this implementation does use some internal buffers, it's still advisable
|
||||
// to use a buffered writer to avoid small operations for any external IO like disk or network.
|
||||
type quickWriterStream struct {
|
||||
w io.Writer
|
||||
ws stringWriter // nil if not available
|
||||
|
||||
scratch [2]byte
|
||||
scratch1 []byte
|
||||
scratch2 []byte
|
||||
err error
|
||||
}
|
||||
|
||||
func newQuickWriterStream(w io.Writer) *quickWriterStream {
|
||||
z := &quickWriterStream{w: w}
|
||||
if ws, ok := w.(stringWriter); ok {
|
||||
z.ws = ws
|
||||
}
|
||||
z.scratch1 = z.scratch[:1]
|
||||
z.scratch2 = z.scratch[:2]
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) writeb(bs []byte) {
|
||||
n, err := z.w.Write(bs)
|
||||
if err != nil && z.err == nil {
|
||||
z.err = err
|
||||
}
|
||||
if n < len(bs) && z.err == nil {
|
||||
z.err = fmt.Errorf("underwrite")
|
||||
}
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) writestr(s string) {
|
||||
var n int
|
||||
var err error
|
||||
if z.ws != nil {
|
||||
n, err = z.ws.WriteString(s)
|
||||
} else {
|
||||
n, err = z.w.Write([]byte(s)) // Notice: alloc!
|
||||
}
|
||||
if err != nil && z.err == nil {
|
||||
z.err = err
|
||||
}
|
||||
if n < len(s) && z.err == nil {
|
||||
z.err = fmt.Errorf("underwrite")
|
||||
}
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) writen1(b byte) {
|
||||
z.scratch1[0] = b
|
||||
n, err := z.w.Write(z.scratch1)
|
||||
if err != nil && z.err == nil {
|
||||
z.err = err
|
||||
}
|
||||
if n < 1 && z.err == nil {
|
||||
z.err = fmt.Errorf("underwrite")
|
||||
}
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) writen2(b1 byte, b2 byte) {
|
||||
z.scratch2[0] = b1
|
||||
z.scratch2[1] = b2
|
||||
n, err := z.w.Write(z.scratch2)
|
||||
if err != nil && z.err == nil {
|
||||
z.err = err
|
||||
}
|
||||
if n < 2 && z.err == nil {
|
||||
z.err = fmt.Errorf("underwrite")
|
||||
}
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) checkErr() error {
|
||||
return z.err
|
||||
}
|
||||
|
||||
func (z *quickWriterStream) clearErr() {
|
||||
z.err = nil
|
||||
}
|
||||
22
vendor/github.com/polydawn/refmt/cbor/errors.go
generated
vendored
Normal file
22
vendor/github.com/polydawn/refmt/cbor/errors.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/polydawn/refmt/tok"
|
||||
)
|
||||
|
||||
// Error raised by Encoder when invalid tokens or invalid ordering, e.g. a MapClose with no matching open.
|
||||
// Should never be seen by the user in practice unless generating their own token streams.
|
||||
type ErrInvalidTokenStream struct {
|
||||
Got Token
|
||||
Acceptable []TokenType
|
||||
}
|
||||
|
||||
func (e *ErrInvalidTokenStream) Error() string {
|
||||
return fmt.Sprintf("ErrInvalidTokenStream: unexpected %v, expected %v", e.Got, e.Acceptable)
|
||||
// More comprehensible strings might include "start of value", "start of key or end of map", "start of value or end of array".
|
||||
}
|
||||
|
||||
var tokenTypesForKey = []TokenType{TString, TInt, TUint}
|
||||
var tokenTypesForValue = []TokenType{TMapOpen, TArrOpen, TNull, TString, TBytes, TInt, TUint, TFloat64}
|
||||
Reference in New Issue
Block a user