|
|
package msgpack
import ( "fmt" "reflect"
"github.com/vmihailenco/msgpack/codes" )
const sliceElemsAllocLimit = 1e4
var sliceStringPtrType = reflect.TypeOf((*[]string)(nil))
func (d *Decoder) DecodeArrayLen() (int, error) { c, err := d.readCode() if err != nil { return 0, err } return d.arrayLen(c) }
func (d *Decoder) arrayLen(c codes.Code) (int, error) { if c == codes.Nil { return -1, nil } else if c >= codes.FixedArrayLow && c <= codes.FixedArrayHigh { return int(c & codes.FixedArrayMask), nil } switch c { case codes.Array16: n, err := d.uint16() return int(n), err case codes.Array32: n, err := d.uint32() return int(n), err } return 0, fmt.Errorf("msgpack: invalid code=%x decoding array length", c) }
func decodeStringSliceValue(d *Decoder, v reflect.Value) error { ptr := v.Addr().Convert(sliceStringPtrType).Interface().(*[]string) return d.decodeStringSlicePtr(ptr) }
func (d *Decoder) decodeStringSlicePtr(ptr *[]string) error { n, err := d.DecodeArrayLen() if err != nil { return err } if n == -1 { return nil }
ss := setStringsCap(*ptr, n) for i := 0; i < n; i++ { s, err := d.DecodeString() if err != nil { return err } ss = append(ss, s) } *ptr = ss
return nil }
func setStringsCap(s []string, n int) []string { if n > sliceElemsAllocLimit { n = sliceElemsAllocLimit }
if s == nil { return make([]string, 0, n) }
if cap(s) >= n { return s[:0] }
s = s[:cap(s)] s = append(s, make([]string, n-len(s))...) return s[:0] }
func decodeSliceValue(d *Decoder, v reflect.Value) error { n, err := d.DecodeArrayLen() if err != nil { return err }
if n == -1 { v.Set(reflect.Zero(v.Type())) return nil } if n == 0 && v.IsNil() { v.Set(reflect.MakeSlice(v.Type(), 0, 0)) return nil }
if v.Cap() >= n { v.Set(v.Slice(0, n)) } else if v.Len() < v.Cap() { v.Set(v.Slice(0, v.Cap())) }
for i := 0; i < n; i++ { if i >= v.Len() { v.Set(growSliceValue(v, n)) } sv := v.Index(i) if err := d.DecodeValue(sv); err != nil { return err } }
return nil }
func growSliceValue(v reflect.Value, n int) reflect.Value { diff := n - v.Len() if diff > sliceElemsAllocLimit { diff = sliceElemsAllocLimit } v = reflect.AppendSlice(v, reflect.MakeSlice(v.Type(), diff, diff)) return v }
func decodeArrayValue(d *Decoder, v reflect.Value) error { n, err := d.DecodeArrayLen() if err != nil { return err }
if n == -1 { return nil }
if n > v.Len() { return fmt.Errorf("%s len is %d, but msgpack has %d elements", v.Type(), v.Len(), n) } for i := 0; i < n; i++ { sv := v.Index(i) if err := d.DecodeValue(sv); err != nil { return err } }
return nil }
func (d *Decoder) DecodeSlice() ([]interface{}, error) { c, err := d.readCode() if err != nil { return nil, err } return d.decodeSlice(c) }
func (d *Decoder) decodeSlice(c codes.Code) ([]interface{}, error) { n, err := d.arrayLen(c) if err != nil { return nil, err } if n == -1 { return nil, nil }
s := make([]interface{}, 0, min(n, sliceElemsAllocLimit)) for i := 0; i < n; i++ { v, err := d.DecodeInterface() if err != nil { return nil, err } s = append(s, v) }
return s, nil }
func (d *Decoder) skipSlice(c codes.Code) error { n, err := d.arrayLen(c) if err != nil { return err }
for i := 0; i < n; i++ { if err := d.Skip(); err != nil { return err } }
return nil }
|