176 lines
3.0 KiB
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
|
|
}
|