ipld-eth-server/vendor/github.com/polydawn/refmt/cbor/cborDecoderTerminals.go

236 lines
7.4 KiB
Go
Raw Normal View History

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
}