msgpack/map.go

176 lines
3.0 KiB
Go

package msgpack
import (
"fmt"
"reflect"
)
func (e *Encoder) encodeMapLen(l int) error {
switch {
case l < 16:
if err := e.W.WriteByte(fixMapLowCode | byte(l)); err != nil {
return err
}
case l < 65536:
if err := e.write([]byte{
map16Code,
byte(l >> 8),
byte(l),
}); err != nil {
return err
}
default:
if err := e.write([]byte{
map32Code,
byte(l >> 24),
byte(l >> 16),
byte(l >> 8),
byte(l),
}); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeMapStringString(m map[string]string) error {
if err := e.encodeMapLen(len(m)); err != nil {
return err
}
for mk, mv := range m {
if err := e.EncodeString(mk); err != nil {
return err
}
if err := e.EncodeString(mv); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeMap(value reflect.Value) error {
if err := e.encodeMapLen(value.Len()); err != nil {
return err
}
keys := value.MapKeys()
for _, k := range keys {
if err := e.EncodeValue(k); err != nil {
return err
}
if err := e.EncodeValue(value.MapIndex(k)); err != nil {
return err
}
}
return nil
}
func decodeMap(d *Decoder) (interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
m := make(map[interface{}]interface{}, n)
for i := 0; i < n; i++ {
mk, err := d.DecodeInterface()
if err != nil {
return nil, err
}
mv, err := d.DecodeInterface()
if err != nil {
return nil, err
}
m[mk] = mv
}
return m, nil
}
func (d *Decoder) DecodeMapLen() (int, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c == nilCode {
return -1, nil
} else if c >= fixMapLowCode && c <= fixMapHighCode {
return int(c & fixMapMask), nil
}
switch c {
case map16Code:
n, err := d.uint16()
return int(n), err
case map32Code:
n, err := d.uint32()
return int(n), err
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding map length", c)
}
func (d *Decoder) decodeIntoMapStringString(mp *map[string]string) error {
n, err := d.DecodeMapLen()
if err != nil {
return err
}
if n == -1 {
return nil
}
// TODO(vmihailenco): simpler way?
m := *mp
if m == nil {
*mp = make(map[string]string, n)
m = *mp
}
for i := 0; i < n; i++ {
mk, err := d.DecodeString()
if err != nil {
return err
}
mv, err := d.DecodeString()
if err != nil {
return err
}
m[mk] = mv
}
return nil
}
func (d *Decoder) DecodeMap() (interface{}, error) {
return d.DecodeMapFunc(d)
}
func (d *Decoder) mapValue(v reflect.Value) error {
n, err := d.DecodeMapLen()
if err != nil {
return err
}
if n == -1 {
return nil
}
typ := v.Type()
if v.IsNil() {
v.Set(reflect.MakeMap(typ))
}
keyType := typ.Key()
valueType := typ.Elem()
for i := 0; i < n; i++ {
mk := reflect.New(keyType).Elem()
if err := d.DecodeValue(mk); err != nil {
return err
}
mv := reflect.New(valueType).Elem()
if err := d.DecodeValue(mv); err != nil {
return err
}
v.SetMapIndex(mk, mv)
}
return nil
}