|
@@ -0,0 +1,1073 @@
|
|
|
|
+package msgp
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "bytes"
|
|
|
|
+ "encoding/binary"
|
|
|
|
+ "math"
|
|
|
|
+ "time"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+var big = binary.BigEndian
|
|
|
|
+
|
|
|
|
+// NextType returns the type of the next
|
|
|
|
+// object in the slice. If the length
|
|
|
|
+// of the input is zero, it returns
|
|
|
|
+// InvalidType.
|
|
|
|
+func NextType(b []byte) Type {
|
|
|
|
+ if len(b) == 0 {
|
|
|
|
+ return InvalidType
|
|
|
|
+ }
|
|
|
|
+ spec := sizes[b[0]]
|
|
|
|
+ t := spec.typ
|
|
|
|
+ if t == ExtensionType && len(b) > int(spec.size) {
|
|
|
|
+ var tp int8
|
|
|
|
+ if spec.extra == constsize {
|
|
|
|
+ tp = int8(b[1])
|
|
|
|
+ } else {
|
|
|
|
+ tp = int8(b[spec.size-1])
|
|
|
|
+ }
|
|
|
|
+ switch tp {
|
|
|
|
+ case TimeExtension:
|
|
|
|
+ return TimeType
|
|
|
|
+ case Complex128Extension:
|
|
|
|
+ return Complex128Type
|
|
|
|
+ case Complex64Extension:
|
|
|
|
+ return Complex64Type
|
|
|
|
+ default:
|
|
|
|
+ return ExtensionType
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return t
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// IsNil returns true if len(b)>0 and
|
|
|
|
+// the leading byte is a 'nil' MessagePack
|
|
|
|
+// byte; false otherwise
|
|
|
|
+func IsNil(b []byte) bool {
|
|
|
|
+ if len(b) != 0 && b[0] == mnil {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Raw is raw MessagePack.
|
|
|
|
+// Raw allows you to read and write
|
|
|
|
+// data without interpreting its contents.
|
|
|
|
+type Raw []byte
|
|
|
|
+
|
|
|
|
+// MarshalMsg implements msgp.Marshaler.
|
|
|
|
+// It appends the raw contents of 'raw'
|
|
|
|
+// to the provided byte slice. If 'raw'
|
|
|
|
+// is 0 bytes, 'nil' will be appended instead.
|
|
|
|
+func (r Raw) MarshalMsg(b []byte) ([]byte, error) {
|
|
|
|
+ i := len(r)
|
|
|
|
+ if i == 0 {
|
|
|
|
+ return AppendNil(b), nil
|
|
|
|
+ }
|
|
|
|
+ o, l := ensure(b, i)
|
|
|
|
+ copy(o[l:], []byte(r))
|
|
|
|
+ return o, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// UnmarshalMsg implements msgp.Unmarshaler.
|
|
|
|
+// It sets the contents of *Raw to be the next
|
|
|
|
+// object in the provided byte slice.
|
|
|
|
+func (r *Raw) UnmarshalMsg(b []byte) ([]byte, error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ out, err := Skip(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return b, err
|
|
|
|
+ }
|
|
|
|
+ rlen := l - len(out)
|
|
|
|
+ if cap(*r) < rlen {
|
|
|
|
+ *r = make(Raw, rlen)
|
|
|
|
+ } else {
|
|
|
|
+ *r = (*r)[0:rlen]
|
|
|
|
+ }
|
|
|
|
+ copy(*r, b[:rlen])
|
|
|
|
+ return out, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// EncodeMsg implements msgp.Encodable.
|
|
|
|
+// It writes the raw bytes to the writer.
|
|
|
|
+// If r is empty, it writes 'nil' instead.
|
|
|
|
+func (r Raw) EncodeMsg(w *Writer) error {
|
|
|
|
+ if len(r) == 0 {
|
|
|
|
+ return w.WriteNil()
|
|
|
|
+ }
|
|
|
|
+ _, err := w.Write([]byte(r))
|
|
|
|
+ return err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// DecodeMsg implements msgp.Decodable.
|
|
|
|
+// It sets the value of *Raw to be the
|
|
|
|
+// next object on the wire.
|
|
|
|
+func (r *Raw) DecodeMsg(f *Reader) error {
|
|
|
|
+ *r = (*r)[:0]
|
|
|
|
+ return appendNext(f, (*[]byte)(r))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Msgsize implements msgp.Sizer
|
|
|
|
+func (r Raw) Msgsize() int {
|
|
|
|
+ l := len(r)
|
|
|
|
+ if l == 0 {
|
|
|
|
+ return 1 // for 'nil'
|
|
|
|
+ }
|
|
|
|
+ return l
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func appendNext(f *Reader, d *[]byte) error {
|
|
|
|
+ amt, o, err := getNextSize(f.r)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ var i int
|
|
|
|
+ *d, i = ensure(*d, int(amt))
|
|
|
|
+ _, err = f.r.ReadFull((*d)[i:])
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ for o > 0 {
|
|
|
|
+ err = appendNext(f, d)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ o--
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// MarshalJSON implements json.Marshaler
|
|
|
|
+func (r *Raw) MarshalJSON() ([]byte, error) {
|
|
|
|
+ var buf bytes.Buffer
|
|
|
|
+ _, err := UnmarshalAsJSON(&buf, []byte(*r))
|
|
|
|
+ return buf.Bytes(), err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadMapHeaderBytes reads a map header size
|
|
|
|
+// from 'b' and returns the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a map)
|
|
|
|
+func ReadMapHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ if isfixmap(lead) {
|
|
|
|
+ sz = uint32(rfixmap(lead))
|
|
|
|
+ o = b[1:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch lead {
|
|
|
|
+ case mmap16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sz = uint32(big.Uint16(b[1:]))
|
|
|
|
+ o = b[3:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case mmap32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sz = big.Uint32(b[1:])
|
|
|
|
+ o = b[5:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(MapType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadMapKeyZC attempts to read a map key
|
|
|
|
+// from 'b' and returns the key bytes and the remaining bytes
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a str or bin)
|
|
|
|
+func ReadMapKeyZC(b []byte) ([]byte, []byte, error) {
|
|
|
|
+ o, b, err := ReadStringZC(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType {
|
|
|
|
+ return ReadBytesZC(b)
|
|
|
|
+ }
|
|
|
|
+ return nil, b, err
|
|
|
|
+ }
|
|
|
|
+ return o, b, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadArrayHeaderBytes attempts to read
|
|
|
|
+// the array header size off of 'b' and return
|
|
|
|
+// the size and remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not an array)
|
|
|
|
+func ReadArrayHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
|
|
|
|
+ if len(b) < 1 {
|
|
|
|
+ return 0, nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ lead := b[0]
|
|
|
|
+ if isfixarray(lead) {
|
|
|
|
+ sz = uint32(rfixarray(lead))
|
|
|
|
+ o = b[1:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch lead {
|
|
|
|
+ case marray16:
|
|
|
|
+ if len(b) < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sz = uint32(big.Uint16(b[1:]))
|
|
|
|
+ o = b[3:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case marray32:
|
|
|
|
+ if len(b) < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sz = big.Uint32(b[1:])
|
|
|
|
+ o = b[5:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(ArrayType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadNilBytes tries to read a "nil" byte
|
|
|
|
+// off of 'b' and return the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a 'nil')
|
|
|
|
+// - InvalidPrefixError
|
|
|
|
+func ReadNilBytes(b []byte) ([]byte, error) {
|
|
|
|
+ if len(b) < 1 {
|
|
|
|
+ return nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ if b[0] != mnil {
|
|
|
|
+ return b, badPrefix(NilType, b[0])
|
|
|
|
+ }
|
|
|
|
+ return b[1:], nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadFloat64Bytes tries to read a float64
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a float64)
|
|
|
|
+func ReadFloat64Bytes(b []byte) (f float64, o []byte, err error) {
|
|
|
|
+ if len(b) < 9 {
|
|
|
|
+ if len(b) >= 5 && b[0] == mfloat32 {
|
|
|
|
+ var tf float32
|
|
|
|
+ tf, o, err = ReadFloat32Bytes(b)
|
|
|
|
+ f = float64(tf)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if b[0] != mfloat64 {
|
|
|
|
+ if b[0] == mfloat32 {
|
|
|
|
+ var tf float32
|
|
|
|
+ tf, o, err = ReadFloat32Bytes(b)
|
|
|
|
+ f = float64(tf)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ err = badPrefix(Float64Type, b[0])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ f = math.Float64frombits(getMuint64(b))
|
|
|
|
+ o = b[9:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadFloat32Bytes tries to read a float64
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a float32)
|
|
|
|
+func ReadFloat32Bytes(b []byte) (f float32, o []byte, err error) {
|
|
|
|
+ if len(b) < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if b[0] != mfloat32 {
|
|
|
|
+ err = TypeError{Method: Float32Type, Encoded: getType(b[0])}
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ f = math.Float32frombits(getMuint32(b))
|
|
|
|
+ o = b[5:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadBoolBytes tries to read a float64
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a bool)
|
|
|
|
+func ReadBoolBytes(b []byte) (bool, []byte, error) {
|
|
|
|
+ if len(b) < 1 {
|
|
|
|
+ return false, b, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ switch b[0] {
|
|
|
|
+ case mtrue:
|
|
|
|
+ return true, b[1:], nil
|
|
|
|
+ case mfalse:
|
|
|
|
+ return false, b[1:], nil
|
|
|
|
+ default:
|
|
|
|
+ return false, b, badPrefix(BoolType, b[0])
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadInt64Bytes tries to read an int64
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError (not a int)
|
|
|
|
+func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ return 0, nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ if isfixint(lead) {
|
|
|
|
+ i = int64(rfixint(lead))
|
|
|
|
+ o = b[1:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if isnfixint(lead) {
|
|
|
|
+ i = int64(rnfixint(lead))
|
|
|
|
+ o = b[1:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch lead {
|
|
|
|
+ case mint8:
|
|
|
|
+ if l < 2 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ i = int64(getMint8(b))
|
|
|
|
+ o = b[2:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case mint16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ i = int64(getMint16(b))
|
|
|
|
+ o = b[3:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case mint32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ i = int64(getMint32(b))
|
|
|
|
+ o = b[5:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case mint64:
|
|
|
|
+ if l < 9 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ i = getMint64(b)
|
|
|
|
+ o = b[9:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(IntType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadInt32Bytes tries to read an int32
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a int)
|
|
|
|
+// - IntOverflow{} (value doesn't fit in int32)
|
|
|
|
+func ReadInt32Bytes(b []byte) (int32, []byte, error) {
|
|
|
|
+ i, o, err := ReadInt64Bytes(b)
|
|
|
|
+ if i > math.MaxInt32 || i < math.MinInt32 {
|
|
|
|
+ return 0, o, IntOverflow{Value: i, FailedBitsize: 32}
|
|
|
|
+ }
|
|
|
|
+ return int32(i), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadInt16Bytes tries to read an int16
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a int)
|
|
|
|
+// - IntOverflow{} (value doesn't fit in int16)
|
|
|
|
+func ReadInt16Bytes(b []byte) (int16, []byte, error) {
|
|
|
|
+ i, o, err := ReadInt64Bytes(b)
|
|
|
|
+ if i > math.MaxInt16 || i < math.MinInt16 {
|
|
|
|
+ return 0, o, IntOverflow{Value: i, FailedBitsize: 16}
|
|
|
|
+ }
|
|
|
|
+ return int16(i), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadInt8Bytes tries to read an int16
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a int)
|
|
|
|
+// - IntOverflow{} (value doesn't fit in int8)
|
|
|
|
+func ReadInt8Bytes(b []byte) (int8, []byte, error) {
|
|
|
|
+ i, o, err := ReadInt64Bytes(b)
|
|
|
|
+ if i > math.MaxInt8 || i < math.MinInt8 {
|
|
|
|
+ return 0, o, IntOverflow{Value: i, FailedBitsize: 8}
|
|
|
|
+ }
|
|
|
|
+ return int8(i), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadIntBytes tries to read an int
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a int)
|
|
|
|
+// - IntOverflow{} (value doesn't fit in int; 32-bit platforms only)
|
|
|
|
+func ReadIntBytes(b []byte) (int, []byte, error) {
|
|
|
|
+ if smallint {
|
|
|
|
+ i, b, err := ReadInt32Bytes(b)
|
|
|
|
+ return int(i), b, err
|
|
|
|
+ }
|
|
|
|
+ i, b, err := ReadInt64Bytes(b)
|
|
|
|
+ return int(i), b, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadUint64Bytes tries to read a uint64
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a uint)
|
|
|
|
+func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ return 0, nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ if isfixint(lead) {
|
|
|
|
+ u = uint64(rfixint(lead))
|
|
|
|
+ o = b[1:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch lead {
|
|
|
|
+ case muint8:
|
|
|
|
+ if l < 2 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ u = uint64(getMuint8(b))
|
|
|
|
+ o = b[2:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case muint16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ u = uint64(getMuint16(b))
|
|
|
|
+ o = b[3:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case muint32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ u = uint64(getMuint32(b))
|
|
|
|
+ o = b[5:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case muint64:
|
|
|
|
+ if l < 9 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ u = getMuint64(b)
|
|
|
|
+ o = b[9:]
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(UintType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadUint32Bytes tries to read a uint32
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a uint)
|
|
|
|
+// - UintOverflow{} (value too large for uint32)
|
|
|
|
+func ReadUint32Bytes(b []byte) (uint32, []byte, error) {
|
|
|
|
+ v, o, err := ReadUint64Bytes(b)
|
|
|
|
+ if v > math.MaxUint32 {
|
|
|
|
+ return 0, nil, UintOverflow{Value: v, FailedBitsize: 32}
|
|
|
|
+ }
|
|
|
|
+ return uint32(v), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadUint16Bytes tries to read a uint16
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a uint)
|
|
|
|
+// - UintOverflow{} (value too large for uint16)
|
|
|
|
+func ReadUint16Bytes(b []byte) (uint16, []byte, error) {
|
|
|
|
+ v, o, err := ReadUint64Bytes(b)
|
|
|
|
+ if v > math.MaxUint16 {
|
|
|
|
+ return 0, nil, UintOverflow{Value: v, FailedBitsize: 16}
|
|
|
|
+ }
|
|
|
|
+ return uint16(v), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadUint8Bytes tries to read a uint8
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a uint)
|
|
|
|
+// - UintOverflow{} (value too large for uint8)
|
|
|
|
+func ReadUint8Bytes(b []byte) (uint8, []byte, error) {
|
|
|
|
+ v, o, err := ReadUint64Bytes(b)
|
|
|
|
+ if v > math.MaxUint8 {
|
|
|
|
+ return 0, nil, UintOverflow{Value: v, FailedBitsize: 8}
|
|
|
|
+ }
|
|
|
|
+ return uint8(v), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadUintBytes tries to read a uint
|
|
|
|
+// from 'b' and return the value and the remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a uint)
|
|
|
|
+// - UintOverflow{} (value too large for uint; 32-bit platforms only)
|
|
|
|
+func ReadUintBytes(b []byte) (uint, []byte, error) {
|
|
|
|
+ if smallint {
|
|
|
|
+ u, b, err := ReadUint32Bytes(b)
|
|
|
|
+ return uint(u), b, err
|
|
|
|
+ }
|
|
|
|
+ u, b, err := ReadUint64Bytes(b)
|
|
|
|
+ return uint(u), b, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadByteBytes is analagous to ReadUint8Bytes
|
|
|
|
+func ReadByteBytes(b []byte) (byte, []byte, error) {
|
|
|
|
+ return ReadUint8Bytes(b)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadBytesBytes reads a 'bin' object
|
|
|
|
+// from 'b' and returns its vaue and
|
|
|
|
+// the remaining bytes in 'b'.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (too few bytes)
|
|
|
|
+// - TypeError{} (not a 'bin' object)
|
|
|
|
+func ReadBytesBytes(b []byte, scratch []byte) (v []byte, o []byte, err error) {
|
|
|
|
+ return readBytesBytes(b, scratch, false)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func readBytesBytes(b []byte, scratch []byte, zc bool) (v []byte, o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ return nil, nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ var read int
|
|
|
|
+ switch lead {
|
|
|
|
+ case mbin8:
|
|
|
|
+ if l < 2 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ read = int(b[1])
|
|
|
|
+ b = b[2:]
|
|
|
|
+
|
|
|
|
+ case mbin16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = int(big.Uint16(b[1:]))
|
|
|
|
+ b = b[3:]
|
|
|
|
+
|
|
|
|
+ case mbin32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = int(big.Uint32(b[1:]))
|
|
|
|
+ b = b[5:]
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(BinType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if len(b) < read {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // zero-copy
|
|
|
|
+ if zc {
|
|
|
|
+ v = b[0:read]
|
|
|
|
+ o = b[read:]
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if cap(scratch) >= read {
|
|
|
|
+ v = scratch[0:read]
|
|
|
|
+ } else {
|
|
|
|
+ v = make([]byte, read)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o = b[copy(v, b):]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadBytesZC extracts the messagepack-encoded
|
|
|
|
+// binary field without copying. The returned []byte
|
|
|
|
+// points to the same memory as the input slice.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (b not long enough)
|
|
|
|
+// - TypeError{} (object not 'bin')
|
|
|
|
+func ReadBytesZC(b []byte) (v []byte, o []byte, err error) {
|
|
|
|
+ return readBytesBytes(b, nil, true)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func ReadExactBytes(b []byte, into []byte) (o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ var read uint32
|
|
|
|
+ var skip int
|
|
|
|
+ switch lead {
|
|
|
|
+ case mbin8:
|
|
|
|
+ if l < 2 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ read = uint32(b[1])
|
|
|
|
+ skip = 2
|
|
|
|
+
|
|
|
|
+ case mbin16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = uint32(big.Uint16(b[1:]))
|
|
|
|
+ skip = 3
|
|
|
|
+
|
|
|
|
+ case mbin32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = uint32(big.Uint32(b[1:]))
|
|
|
|
+ skip = 5
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = badPrefix(BinType, lead)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if read != uint32(len(into)) {
|
|
|
|
+ err = ArrayError{Wanted: uint32(len(into)), Got: read}
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ o = b[skip+copy(into, b[skip:]):]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadStringZC reads a messagepack string field
|
|
|
|
+// without copying. The returned []byte points
|
|
|
|
+// to the same memory as the input slice.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (b not long enough)
|
|
|
|
+// - TypeError{} (object not 'str')
|
|
|
|
+func ReadStringZC(b []byte) (v []byte, o []byte, err error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l < 1 {
|
|
|
|
+ return nil, nil, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lead := b[0]
|
|
|
|
+ var read int
|
|
|
|
+
|
|
|
|
+ if isfixstr(lead) {
|
|
|
|
+ read = int(rfixstr(lead))
|
|
|
|
+ b = b[1:]
|
|
|
|
+ } else {
|
|
|
|
+ switch lead {
|
|
|
|
+ case mstr8:
|
|
|
|
+ if l < 2 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = int(b[1])
|
|
|
|
+ b = b[2:]
|
|
|
|
+
|
|
|
|
+ case mstr16:
|
|
|
|
+ if l < 3 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = int(big.Uint16(b[1:]))
|
|
|
|
+ b = b[3:]
|
|
|
|
+
|
|
|
|
+ case mstr32:
|
|
|
|
+ if l < 5 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ read = int(big.Uint32(b[1:]))
|
|
|
|
+ b = b[5:]
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = TypeError{Method: StrType, Encoded: getType(lead)}
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if len(b) < read {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ v = b[0:read]
|
|
|
|
+ o = b[read:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadStringBytes reads a 'str' object
|
|
|
|
+// from 'b' and returns its value and the
|
|
|
|
+// remaining bytes in 'b'.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (b not long enough)
|
|
|
|
+// - TypeError{} (not 'str' type)
|
|
|
|
+// - InvalidPrefixError
|
|
|
|
+func ReadStringBytes(b []byte) (string, []byte, error) {
|
|
|
|
+ v, o, err := ReadStringZC(b)
|
|
|
|
+ return string(v), o, err
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadComplex128Bytes reads a complex128
|
|
|
|
+// extension object from 'b' and returns the
|
|
|
|
+// remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (not enough bytes in 'b')
|
|
|
|
+// - TypeError{} (object not a complex128)
|
|
|
|
+// - InvalidPrefixError
|
|
|
|
+// - ExtensionTypeError{} (object an extension of the correct size, but not a complex128)
|
|
|
|
+func ReadComplex128Bytes(b []byte) (c complex128, o []byte, err error) {
|
|
|
|
+ if len(b) < 18 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if b[0] != mfixext16 {
|
|
|
|
+ err = badPrefix(Complex128Type, b[0])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if int8(b[1]) != Complex128Extension {
|
|
|
|
+ err = errExt(int8(b[1]), Complex128Extension)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ c = complex(math.Float64frombits(big.Uint64(b[2:])),
|
|
|
|
+ math.Float64frombits(big.Uint64(b[10:])))
|
|
|
|
+ o = b[18:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadComplex64Bytes reads a complex64
|
|
|
|
+// extension object from 'b' and returns the
|
|
|
|
+// remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (not enough bytes in 'b')
|
|
|
|
+// - TypeError{} (object not a complex64)
|
|
|
|
+// - ExtensionTypeError{} (object an extension of the correct size, but not a complex64)
|
|
|
|
+func ReadComplex64Bytes(b []byte) (c complex64, o []byte, err error) {
|
|
|
|
+ if len(b) < 10 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if b[0] != mfixext8 {
|
|
|
|
+ err = badPrefix(Complex64Type, b[0])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if b[1] != Complex64Extension {
|
|
|
|
+ err = errExt(int8(b[1]), Complex64Extension)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ c = complex(math.Float32frombits(big.Uint32(b[2:])),
|
|
|
|
+ math.Float32frombits(big.Uint32(b[6:])))
|
|
|
|
+ o = b[10:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadTimeBytes reads a time.Time
|
|
|
|
+// extension object from 'b' and returns the
|
|
|
|
+// remaining bytes.
|
|
|
|
+// Possible errors:
|
|
|
|
+// - ErrShortBytes (not enough bytes in 'b')
|
|
|
|
+// - TypeError{} (object not a complex64)
|
|
|
|
+// - ExtensionTypeError{} (object an extension of the correct size, but not a time.Time)
|
|
|
|
+func ReadTimeBytes(b []byte) (t time.Time, o []byte, err error) {
|
|
|
|
+ if len(b) < 15 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if b[0] != mext8 || b[1] != 12 {
|
|
|
|
+ err = badPrefix(TimeType, b[0])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if int8(b[2]) != TimeExtension {
|
|
|
|
+ err = errExt(int8(b[2]), TimeExtension)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sec, nsec := getUnix(b[3:])
|
|
|
|
+ t = time.Unix(sec, int64(nsec)).Local()
|
|
|
|
+ o = b[15:]
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadMapStrIntfBytes reads a map[string]interface{}
|
|
|
|
+// out of 'b' and returns the map and remaining bytes.
|
|
|
|
+// If 'old' is non-nil, the values will be read into that map.
|
|
|
|
+func ReadMapStrIntfBytes(b []byte, old map[string]interface{}) (v map[string]interface{}, o []byte, err error) {
|
|
|
|
+ var sz uint32
|
|
|
|
+ o = b
|
|
|
|
+ sz, o, err = ReadMapHeaderBytes(o)
|
|
|
|
+
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if old != nil {
|
|
|
|
+ for key := range old {
|
|
|
|
+ delete(old, key)
|
|
|
|
+ }
|
|
|
|
+ v = old
|
|
|
|
+ } else {
|
|
|
|
+ v = make(map[string]interface{}, int(sz))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for z := uint32(0); z < sz; z++ {
|
|
|
|
+ if len(o) < 1 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ var key []byte
|
|
|
|
+ key, o, err = ReadMapKeyZC(o)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ var val interface{}
|
|
|
|
+ val, o, err = ReadIntfBytes(o)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ v[string(key)] = val
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ReadIntfBytes attempts to read
|
|
|
|
+// the next object out of 'b' as a raw interface{} and
|
|
|
|
+// return the remaining bytes.
|
|
|
|
+func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) {
|
|
|
|
+ if len(b) < 1 {
|
|
|
|
+ err = ErrShortBytes
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ k := NextType(b)
|
|
|
|
+
|
|
|
|
+ switch k {
|
|
|
|
+ case MapType:
|
|
|
|
+ i, o, err = ReadMapStrIntfBytes(b, nil)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case ArrayType:
|
|
|
|
+ var sz uint32
|
|
|
|
+ sz, b, err = ReadArrayHeaderBytes(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ j := make([]interface{}, int(sz))
|
|
|
|
+ i = j
|
|
|
|
+ for d := range j {
|
|
|
|
+ j[d], b, err = ReadIntfBytes(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case Float32Type:
|
|
|
|
+ i, o, err = ReadFloat32Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case Float64Type:
|
|
|
|
+ i, o, err = ReadFloat64Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case IntType:
|
|
|
|
+ i, o, err = ReadInt64Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case UintType:
|
|
|
|
+ i, o, err = ReadUint64Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case BoolType:
|
|
|
|
+ i, o, err = ReadBoolBytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case TimeType:
|
|
|
|
+ i, o, err = ReadTimeBytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case Complex64Type:
|
|
|
|
+ i, o, err = ReadComplex64Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case Complex128Type:
|
|
|
|
+ i, o, err = ReadComplex128Bytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case ExtensionType:
|
|
|
|
+ var t int8
|
|
|
|
+ t, err = peekExtension(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // use a user-defined extension,
|
|
|
|
+ // if it's been registered
|
|
|
|
+ f, ok := extensionReg[t]
|
|
|
|
+ if ok {
|
|
|
|
+ e := f()
|
|
|
|
+ o, err = ReadExtensionBytes(b, e)
|
|
|
|
+ i = e
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // last resort is a raw extension
|
|
|
|
+ e := RawExtension{}
|
|
|
|
+ e.Type = int8(t)
|
|
|
|
+ o, err = ReadExtensionBytes(b, &e)
|
|
|
|
+ i = &e
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case NilType:
|
|
|
|
+ o, err = ReadNilBytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case BinType:
|
|
|
|
+ i, o, err = ReadBytesBytes(b, nil)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ case StrType:
|
|
|
|
+ i, o, err = ReadStringBytes(b)
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ err = InvalidPrefixError(b[0])
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Skip skips the next object in 'b' and
|
|
|
|
+// returns the remaining bytes. If the object
|
|
|
|
+// is a map or array, all of its elements
|
|
|
|
+// will be skipped.
|
|
|
|
+// Possible Errors:
|
|
|
|
+// - ErrShortBytes (not enough bytes in b)
|
|
|
|
+// - InvalidPrefixError (bad encoding)
|
|
|
|
+func Skip(b []byte) ([]byte, error) {
|
|
|
|
+ sz, asz, err := getSize(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return b, err
|
|
|
|
+ }
|
|
|
|
+ if uintptr(len(b)) < sz {
|
|
|
|
+ return b, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ b = b[sz:]
|
|
|
|
+ for asz > 0 {
|
|
|
|
+ b, err = Skip(b)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return b, err
|
|
|
|
+ }
|
|
|
|
+ asz--
|
|
|
|
+ }
|
|
|
|
+ return b, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// returns (skip N bytes, skip M objects, error)
|
|
|
|
+func getSize(b []byte) (uintptr, uintptr, error) {
|
|
|
|
+ l := len(b)
|
|
|
|
+ if l == 0 {
|
|
|
|
+ return 0, 0, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ lead := b[0]
|
|
|
|
+ spec := &sizes[lead] // get type information
|
|
|
|
+ size, mode := spec.size, spec.extra
|
|
|
|
+ if size == 0 {
|
|
|
|
+ return 0, 0, InvalidPrefixError(lead)
|
|
|
|
+ }
|
|
|
|
+ if mode >= 0 { // fixed composites
|
|
|
|
+ return uintptr(size), uintptr(mode), nil
|
|
|
|
+ }
|
|
|
|
+ if l < int(size) {
|
|
|
|
+ return 0, 0, ErrShortBytes
|
|
|
|
+ }
|
|
|
|
+ switch mode {
|
|
|
|
+ case extra8:
|
|
|
|
+ return uintptr(size) + uintptr(b[1]), 0, nil
|
|
|
|
+ case extra16:
|
|
|
|
+ return uintptr(size) + uintptr(big.Uint16(b[1:])), 0, nil
|
|
|
|
+ case extra32:
|
|
|
|
+ return uintptr(size) + uintptr(big.Uint32(b[1:])), 0, nil
|
|
|
|
+ case map16v:
|
|
|
|
+ return uintptr(size), 2 * uintptr(big.Uint16(b[1:])), nil
|
|
|
|
+ case map32v:
|
|
|
|
+ return uintptr(size), 2 * uintptr(big.Uint32(b[1:])), nil
|
|
|
|
+ case array16v:
|
|
|
|
+ return uintptr(size), uintptr(big.Uint16(b[1:])), nil
|
|
|
|
+ case array32v:
|
|
|
|
+ return uintptr(size), uintptr(big.Uint32(b[1:])), nil
|
|
|
|
+ default:
|
|
|
|
+ return 0, 0, fatal
|
|
|
|
+ }
|
|
|
|
+}
|