initial commit

This commit is contained in:
Pavel Merzlyakov 2022-10-01 21:05:46 +03:00
commit f8719a06fa
16 changed files with 3343 additions and 0 deletions

27
LICENSE Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2013 The msgpack for Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

87
README.md Normal file
View File

@ -0,0 +1,87 @@
Msgpack implementation for Golang
=================================
Supports:
- Primitives, arrays, maps, structs and interface{}.
- time.Time.
- Appengine *datastore.Key and datastore.Cursor.
- Extensions for user defined types.
- Tags.
API docs: http://godoc.org/github.com/vmihailenco/msgpack
Installation
------------
Install:
go get github.com/vmihailenco/msgpack
Usage
-----
Examples:
func ExampleEncode() {
b, err := msgpack.Marshal(true)
fmt.Printf("%v %#v\n", err, b)
// Output: <nil> []byte{0xc3}
}
func ExampleDecode() {
var out bool
err := msgpack.Unmarshal([]byte{0xc3}, &out)
fmt.Println(err, out)
// Output: <nil> true
}
func ExampleMapStringInterface() {
in := map[string]interface{}{"foo": 1, "hello": "world"}
b, err := msgpack.Marshal(in)
_ = err
var out map[string]interface{}
err = msgpack.Unmarshal(b, &out)
fmt.Printf("%v %#v\n", err, out)
// Output: <nil> map[string]interface {}{"foo":1, "hello":"world"}
}
func ExampleRecursiveMapStringInterface() {
buf := &bytes.Buffer{}
enc := msgpack.NewEncoder(buf)
in := map[string]interface{}{"foo": map[string]interface{}{"hello": "world"}}
_ = enc.Encode(in)
dec := msgpack.NewDecoder(buf)
dec.DecodeMapFunc = func(d *msgpack.Decoder) (interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
m := make(map[string]interface{}, n)
for i := 0; i < n; i++ {
mk, err := d.DecodeString()
if err != nil {
return nil, err
}
mv, err := d.DecodeInterface()
if err != nil {
return nil, err
}
m[mk] = mv
}
return m, nil
}
out, err := dec.DecodeInterface()
fmt.Printf("%v %#v\n", err, out)
// Output: <nil> map[string]interface {}{"foo":map[string]interface {}{"hello":"world"}}
}
Extensions
----------
Look at [appengine.go](https://github.com/vmihailenco/msgpack/blob/master/appengine.go) for example.

69
appengine.go Normal file
View File

@ -0,0 +1,69 @@
// +build appengine
package msgpack
import (
"reflect"
ds "appengine/datastore"
)
var (
keyPtrType = reflect.TypeOf((*ds.Key)(nil))
cursorType = reflect.TypeOf((*ds.Cursor)(nil)).Elem()
)
func init() {
Register(keyPtrType, encodeDatastoreKeyValue, decodeDatastoreKeyValue)
Register(cursorType, encodeDatastoreCursorValue, decodeDatastoreCursorValue)
}
func EncodeDatastoreKey(e *Encoder, key *ds.Key) error {
if key == nil {
return e.EncodeNil()
}
return e.EncodeString(key.Encode())
}
func encodeDatastoreKeyValue(e *Encoder, v reflect.Value) error {
key := v.Interface().(*ds.Key)
return EncodeDatastoreKey(e, key)
}
func DecodeDatastoreKey(d *Decoder) (*ds.Key, error) {
v, err := d.DecodeString()
if err != nil {
return nil, err
}
if v == "" {
return nil, nil
}
return ds.DecodeKey(v)
}
func decodeDatastoreKeyValue(d *Decoder, v reflect.Value) error {
key, err := DecodeDatastoreKey(d)
if err != nil {
return err
}
v.Set(reflect.ValueOf(key))
return nil
}
func encodeDatastoreCursorValue(e *Encoder, v reflect.Value) error {
cursor := v.Interface().(ds.Cursor)
return e.Encode(cursor.String())
}
func decodeDatastoreCursorValue(d *Decoder, v reflect.Value) error {
s, err := d.DecodeString()
if err != nil {
return err
}
cursor, err := ds.DecodeCursor(s)
if err != nil {
return err
}
v.Set(reflect.ValueOf(cursor))
return nil
}

42
codes.go Normal file
View File

@ -0,0 +1,42 @@
package msgpack
const (
posFixNumHighCode = 0x7f
negFixNumLowCode = 0xe0
nilCode = 0xc0
falseCode = 0xc2
trueCode = 0xc3
floatCode = 0xca
doubleCode = 0xcb
uint8Code = 0xcc
uint16Code = 0xcd
uint32Code = 0xce
uint64Code = 0xcf
int8Code = 0xd0
int16Code = 0xd1
int32Code = 0xd2
int64Code = 0xd3
fixRawLowCode = 0xa0
fixRawHighCode = 0xbf
fixRawMask = 0x1f
raw16Code = 0xda
raw32Code = 0xdb
fixArrayLowCode = 0x90
fixArrayHighCode = 0x9f
fixArrayMask = 0xf
array16Code = 0xdc
array32Code = 0xdd
fixMapLowCode = 0x80
fixMapHighCode = 0x8f
fixMapMask = 0xf
map16Code = 0xde
map32Code = 0xdf
)

19
custom.go Normal file
View File

@ -0,0 +1,19 @@
package msgpack
import (
"reflect"
)
var (
typEncMap = make(map[reflect.Type]encoderFunc)
typDecMap = make(map[reflect.Type]decoderFunc)
)
type encoderFunc func(*Encoder, reflect.Value) error
type decoderFunc func(*Decoder, reflect.Value) error
func Register(typ reflect.Type, enc encoderFunc, dec decoderFunc) {
typEncMap[typ] = enc
typDecMap[typ] = dec
}

807
decode.go Normal file
View File

@ -0,0 +1,807 @@
package msgpack
import (
"errors"
"fmt"
"io"
"math"
"reflect"
"time"
"github.com/vmihailenco/bufio"
)
type bufReader interface {
Read([]byte) (int, error)
ReadByte() (byte, error)
UnreadByte() error
Peek(int) ([]byte, error)
ReadN(int) ([]byte, error)
}
func Unmarshal(data []byte, v ...interface{}) error {
buf := bufio.NewBuffer(data)
return NewDecoder(buf).Decode(v...)
}
type Decoder struct {
R bufReader
DecodeMapFunc func(*Decoder) (interface{}, error)
}
func NewDecoder(rd io.Reader) *Decoder {
brd, ok := rd.(bufReader)
if !ok {
brd = bufio.NewReader(rd)
}
return &Decoder{
R: brd,
DecodeMapFunc: decodeMap,
}
}
func (d *Decoder) Decode(v ...interface{}) error {
for _, vv := range v {
if err := d.decode(vv); err != nil {
return err
}
}
return nil
}
func (d *Decoder) decode(iv interface{}) error {
var err error
switch v := iv.(type) {
case *string:
if v != nil {
*v, err = d.DecodeString()
return err
}
case *[]byte:
if v != nil {
*v, err = d.DecodeBytes()
return err
}
case *int:
if v != nil {
*v, err = d.DecodeInt()
return err
}
case *int8:
if v != nil {
*v, err = d.DecodeInt8()
return err
}
case *int16:
if v != nil {
*v, err = d.DecodeInt16()
return err
}
case *int32:
if v != nil {
*v, err = d.DecodeInt32()
return err
}
case *int64:
if v != nil {
*v, err = d.DecodeInt64()
return err
}
case *uint:
if v != nil {
*v, err = d.DecodeUint()
return err
}
case *uint8:
if v != nil {
*v, err = d.DecodeUint8()
return err
}
case *uint16:
if v != nil {
*v, err = d.DecodeUint16()
return err
}
case *uint32:
if v != nil {
*v, err = d.DecodeUint32()
return err
}
case *uint64:
if v != nil {
*v, err = d.DecodeUint64()
return err
}
case *bool:
if v != nil {
*v, err = d.DecodeBool()
return err
}
case *float32:
if v != nil {
*v, err = d.DecodeFloat32()
return err
}
case *float64:
if v != nil {
*v, err = d.DecodeFloat64()
return err
}
case *[]string:
return d.decodeIntoStrings(v)
case *map[string]string:
return d.decodeIntoMapStringString(v)
case *time.Duration:
if v != nil {
vv, err := d.DecodeInt64()
*v = time.Duration(vv)
return err
}
case *time.Time:
if v != nil {
*v, err = d.DecodeTime()
return err
}
}
v := reflect.ValueOf(iv)
if !v.IsValid() {
return errors.New("msgpack: Decode(" + v.String() + ")")
}
if v.Kind() != reflect.Ptr {
return errors.New("msgpack: pointer expected")
}
return d.DecodeValue(v)
}
func (d *Decoder) DecodeValue(v reflect.Value) error {
c, err := d.R.ReadByte()
if err != nil {
return err
}
if c == nilCode {
return nil
}
if err := d.R.UnreadByte(); err != nil {
return err
}
switch v.Kind() {
case reflect.Bool:
return d.boolValue(v)
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return d.uint64Value(v)
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return d.int64Value(v)
case reflect.Float32:
return d.float32Value(v)
case reflect.Float64:
return d.float64Value(v)
case reflect.String:
return d.stringValue(v)
case reflect.Array, reflect.Slice:
return d.sliceValue(v)
case reflect.Map:
return d.mapValue(v)
case reflect.Struct:
typ := v.Type()
if dec, ok := typDecMap[typ]; ok {
return dec(d, v)
}
if dec, ok := v.Interface().(decoder); ok {
return dec.DecodeMsgpack(d.R)
}
return d.structValue(v)
case reflect.Ptr:
typ := v.Type()
if v.IsNil() {
v.Set(reflect.New(typ.Elem()))
}
if dec, ok := typDecMap[typ]; ok {
return dec(d, v)
}
if dec, ok := v.Interface().(decoder); ok {
return dec.DecodeMsgpack(d.R)
}
return d.DecodeValue(v.Elem())
case reflect.Interface:
if v.IsNil() {
return d.interfaceValue(v)
} else {
return d.DecodeValue(v.Elem())
}
}
return fmt.Errorf("msgpack: unsupported type %v", v.Type().String())
}
func (d *Decoder) DecodeBool() (bool, error) {
c, err := d.R.ReadByte()
if err != nil {
return false, err
}
switch c {
case falseCode:
return false, nil
case trueCode:
return true, nil
}
return false, fmt.Errorf("msgpack: invalid code %x decoding bool", c)
}
func (d *Decoder) boolValue(value reflect.Value) error {
v, err := d.DecodeBool()
if err != nil {
return err
}
value.SetBool(v)
return nil
}
func (d *Decoder) uint16() (uint16, error) {
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (uint16(b[0]) << 8) | uint16(b[1]), nil
}
func (d *Decoder) uint32() (uint32, error) {
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
n := (uint32(b[0]) << 24) |
(uint32(b[1]) << 16) |
(uint32(b[2]) << 8) |
uint32(b[3])
return n, nil
}
func (d *Decoder) uint64() (uint64, error) {
b, err := d.R.ReadN(8)
if err != nil {
return 0, err
}
n := (uint64(b[0]) << 56) |
(uint64(b[1]) << 48) |
(uint64(b[2]) << 40) |
(uint64(b[3]) << 32) |
(uint64(b[4]) << 24) |
(uint64(b[5]) << 16) |
(uint64(b[6]) << 8) |
uint64(b[7])
return n, nil
}
func (d *Decoder) DecodeUint64() (uint64, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode {
return uint64(c), nil
}
switch c {
case uint8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return uint64(c), nil
case uint16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (uint64(b[0]) << 8) | uint64(b[1]), nil
case uint32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := (uint64(b[0]) << 24) |
(uint64(b[1]) << 16) |
(uint64(b[2]) << 8) |
uint64(b[3])
return v, nil
case uint64Code:
b, err := d.R.ReadN(8)
if err != nil {
return 0, err
}
v := (uint64(b[0]) << 56) |
(uint64(b[1]) << 48) |
(uint64(b[2]) << 40) |
(uint64(b[3]) << 32) |
(uint64(b[4]) << 24) |
(uint64(b[5]) << 16) |
(uint64(b[6]) << 8) |
uint64(b[7])
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding uint64", c)
}
func (d *Decoder) uint64Value(value reflect.Value) error {
v, err := d.DecodeUint64()
if err != nil {
return err
}
value.SetUint(v)
return nil
}
func (d *Decoder) DecodeInt64() (int64, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return int64(int8(c)), nil
}
switch c {
case int8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return int64(int8(c)), nil
case int16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return int64((int16(b[0]) << 8) | int16(b[1])), nil
case int32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := int64((int32(b[0]) << 24) |
(int32(b[1]) << 16) |
(int32(b[2]) << 8) |
int32(b[3]))
return v, nil
case int64Code:
b, err := d.R.ReadN(8)
if err != nil {
return 0, err
}
v := (int64(b[0]) << 56) |
(int64(b[1]) << 48) |
(int64(b[2]) << 40) |
(int64(b[3]) << 32) |
(int64(b[4]) << 24) |
(int64(b[5]) << 16) |
(int64(b[6]) << 8) |
int64(b[7])
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding int64", c)
}
func (d *Decoder) int64Value(value reflect.Value) error {
v, err := d.DecodeInt64()
if err != nil {
return err
}
value.SetInt(v)
return nil
}
func (d *Decoder) DecodeFloat32() (float32, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c != floatCode {
return 0, fmt.Errorf("msgpack: invalid code %x decoding float32", c)
}
b, err := d.uint32()
if err != nil {
return 0, err
}
return math.Float32frombits(b), nil
}
func (d *Decoder) float32Value(value reflect.Value) error {
v, err := d.DecodeFloat32()
if err != nil {
return err
}
value.SetFloat(float64(v))
return nil
}
func (d *Decoder) DecodeFloat64() (float64, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c != doubleCode {
return 0, fmt.Errorf("msgpack: invalid code %x decoding float64", c)
}
b, err := d.uint64()
if err != nil {
return 0, err
}
return math.Float64frombits(b), nil
}
func (d *Decoder) float64Value(value reflect.Value) error {
v, err := d.DecodeFloat64()
if err != nil {
return err
}
value.SetFloat(v)
return nil
}
func (d *Decoder) structLen() (int, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
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 struct length", c)
}
func (d *Decoder) structValue(v reflect.Value) error {
n, err := d.structLen()
if err != nil {
return err
}
typ := v.Type()
for i := 0; i < n; i++ {
name, err := d.DecodeString()
if err != nil {
return err
}
f := structs.Field(typ, name)
if f != nil {
if err := f.DecodeValue(d, v); err != nil {
return err
}
} else {
_, err := d.DecodeInterface()
if err != nil {
return err
}
}
}
return nil
}
//------------------------------------------------------------------------------
func (d *Decoder) DecodeUint() (uint, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode {
return uint(c), nil
}
switch c {
case uint8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return uint(c), nil
case uint16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (uint(b[0]) << 8) | uint(b[1]), nil
case uint32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := (uint(b[0]) << 24) |
(uint(b[1]) << 16) |
(uint(b[2]) << 8) |
uint(b[3])
return v, nil
case uint64Code:
b, err := d.R.ReadN(8)
if err != nil {
return 0, err
}
v := (uint(b[0]) << 56) |
(uint(b[1]) << 48) |
(uint(b[2]) << 40) |
(uint(b[3]) << 32) |
(uint(b[4]) << 24) |
(uint(b[5]) << 16) |
(uint(b[6]) << 8) |
uint(b[7])
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding uint", c)
}
func (d *Decoder) DecodeUint8() (uint8, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode {
return uint8(c), nil
}
switch c {
case uint8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return uint8(c), nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding uint8", c)
}
func (d *Decoder) DecodeUint16() (uint16, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode {
return uint16(c), nil
}
switch c {
case uint8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return uint16(c), nil
case uint16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (uint16(b[0]) << 8) | uint16(b[1]), nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding uint16", c)
}
func (d *Decoder) DecodeUint32() (uint32, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode {
return uint32(c), nil
}
switch c {
case uint8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return uint32(c), nil
case uint16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (uint32(b[0]) << 8) | uint32(b[1]), nil
case uint32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := (uint32(b[0]) << 24) |
(uint32(b[1]) << 16) |
(uint32(b[2]) << 8) |
uint32(b[3])
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding uint32", c)
}
//------------------------------------------------------------------------------
func (d *Decoder) DecodeInt() (int, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return int(int8(c)), nil
}
switch c {
case int8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return int(int8(c)), nil
case int16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return int((int16(b[0]) << 8) | int16(b[1])), nil
case int32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := int((int32(b[0]) << 24) |
(int32(b[1]) << 16) |
(int32(b[2]) << 8) |
int32(b[3]))
return v, nil
case int64Code:
b, err := d.R.ReadN(8)
if err != nil {
return 0, err
}
v := int((int64(b[0]) << 56) |
(int64(b[1]) << 48) |
(int64(b[2]) << 40) |
(int64(b[3]) << 32) |
(int64(b[4]) << 24) |
(int64(b[5]) << 16) |
(int64(b[6]) << 8) |
int64(b[7]))
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding int64", c)
}
func (d *Decoder) DecodeInt8() (int8, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return int8(c), nil
}
switch c {
case int8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return int8(c), nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding int8", c)
}
func (d *Decoder) DecodeInt16() (int16, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return int16(int8(c)), nil
}
switch c {
case int8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return int16(int8(c)), nil
case int16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return (int16(b[0]) << 8) | int16(b[1]), nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding int16", c)
}
func (d *Decoder) DecodeInt32() (int32, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return int32(int8(c)), nil
}
switch c {
case int8Code:
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
return int32(int8(c)), nil
case int16Code:
b, err := d.R.ReadN(2)
if err != nil {
return 0, err
}
return int32((int16(b[0]) << 8) | int16(b[1])), nil
case int32Code:
b, err := d.R.ReadN(4)
if err != nil {
return 0, err
}
v := (int32(b[0]) << 24) |
(int32(b[1]) << 16) |
(int32(b[2]) << 8) |
int32(b[3])
return v, nil
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding int32", c)
}
//------------------------------------------------------------------------------
func (d *Decoder) interfaceValue(v reflect.Value) error {
iface, err := d.DecodeInterface()
if err != nil {
return err
}
v.Set(reflect.ValueOf(iface))
return nil
}
// Decodes value into interface. Possible value types are:
// - nil,
// - int64,
// - uint64,
// - bool,
// - float32 and float64,
// - string,
// - slices of any of the above,
// - maps of any of the above.
func (d *Decoder) DecodeInterface() (interface{}, error) {
b, err := d.R.Peek(1)
if err != nil {
return nil, err
}
c := b[0]
if c <= posFixNumHighCode || c >= negFixNumLowCode {
return d.DecodeInt64()
} else if c >= fixMapLowCode && c <= fixMapHighCode {
return d.DecodeMap()
} else if c >= fixArrayLowCode && c <= fixArrayHighCode {
return d.DecodeSlice()
} else if c >= fixRawLowCode && c <= fixRawHighCode {
return d.DecodeString()
}
switch c {
case nilCode:
_, err := d.R.ReadByte()
return nil, err
case falseCode, trueCode:
return d.DecodeBool()
case floatCode:
return d.DecodeFloat32()
case doubleCode:
return d.DecodeFloat64()
case uint8Code, uint16Code, uint32Code, uint64Code:
return d.DecodeUint64()
case int8Code, int16Code, int32Code, int64Code:
return d.DecodeInt64()
case raw16Code, raw32Code:
return d.DecodeString()
case array16Code, array32Code:
return d.DecodeSlice()
case map16Code, map32Code:
return d.DecodeMap()
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding interface{}", c)
}

343
encode.go Normal file
View File

@ -0,0 +1,343 @@
package msgpack
import (
"bytes"
"fmt"
"io"
"math"
"reflect"
"time"
)
type writer interface {
io.Writer
WriteByte(byte) error
WriteString(string) (int, error)
}
type writeByte struct {
io.Writer
}
func (w *writeByte) WriteByte(b byte) error {
n, err := w.Write([]byte{b})
if err != nil {
return err
}
if n != 1 {
return io.ErrShortWrite
}
return nil
}
func (w *writeByte) WriteString(s string) (int, error) {
return w.Write([]byte(s))
}
func Marshal(v ...interface{}) ([]byte, error) {
buf := &bytes.Buffer{}
err := NewEncoder(buf).Encode(v...)
return buf.Bytes(), err
}
type Encoder struct {
W writer
}
func NewEncoder(w io.Writer) *Encoder {
ww, ok := w.(writer)
if !ok {
ww = &writeByte{Writer: w}
}
return &Encoder{
W: ww,
}
}
func (e *Encoder) Encode(v ...interface{}) error {
for _, vv := range v {
if err := e.encode(vv); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encode(iv interface{}) error {
if iv == nil {
return e.EncodeNil()
}
switch v := iv.(type) {
case string:
return e.EncodeString(v)
case []byte:
return e.EncodeBytes(v)
case int:
return e.EncodeInt64(int64(v))
case int64:
return e.EncodeInt64(v)
case uint:
return e.EncodeUint64(uint64(v))
case uint64:
return e.EncodeUint64(v)
case bool:
return e.EncodeBool(v)
case float32:
return e.EncodeFloat32(v)
case float64:
return e.EncodeFloat64(v)
case []string:
return e.encodeStringSlice(v)
case map[string]string:
return e.encodeMapStringString(v)
case time.Duration:
return e.EncodeInt64(int64(v))
case time.Time:
return e.EncodeTime(v)
case encoder:
return v.EncodeMsgpack(e.W)
}
return e.EncodeValue(reflect.ValueOf(iv))
}
func (e *Encoder) EncodeValue(v reflect.Value) error {
switch v.Kind() {
case reflect.String:
return e.EncodeString(v.String())
case reflect.Bool:
return e.EncodeBool(v.Bool())
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return e.EncodeUint64(v.Uint())
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return e.EncodeInt64(v.Int())
case reflect.Float32:
return e.EncodeFloat32(float32(v.Float()))
case reflect.Float64:
return e.EncodeFloat64(v.Float())
case reflect.Array:
return e.encodeSlice(v)
case reflect.Slice:
if v.IsNil() {
return e.EncodeNil()
}
return e.encodeSlice(v)
case reflect.Map:
return e.encodeMap(v)
case reflect.Interface, reflect.Ptr:
if v.IsNil() {
return e.EncodeNil()
}
if enc, ok := typEncMap[v.Type()]; ok {
return enc(e, v)
}
if enc, ok := v.Interface().(encoder); ok {
return enc.EncodeMsgpack(e.W)
}
return e.EncodeValue(v.Elem())
case reflect.Struct:
typ := v.Type()
if enc, ok := typEncMap[typ]; ok {
return enc(e, v)
}
if enc, ok := v.Interface().(encoder); ok {
return enc.EncodeMsgpack(e.W)
}
return e.encodeStruct(v)
default:
return fmt.Errorf("msgpack: unsupported type %v", v.Type().String())
}
panic("not reached")
}
func (e *Encoder) EncodeNil() error {
return e.W.WriteByte(nilCode)
}
func (e *Encoder) EncodeUint(v uint) error {
return e.EncodeUint64(uint64(v))
}
func (e *Encoder) EncodeUint8(v uint8) error {
return e.EncodeUint64(uint64(v))
}
func (e *Encoder) EncodeUint16(v uint16) error {
return e.EncodeUint64(uint64(v))
}
func (e *Encoder) EncodeUint32(v uint32) error {
return e.EncodeUint64(uint64(v))
}
func (e *Encoder) EncodeUint64(v uint64) error {
switch {
case v < 128:
return e.W.WriteByte(byte(v))
case v < 256:
return e.write([]byte{uint8Code, byte(v)})
case v < 65536:
return e.write([]byte{uint16Code, byte(v >> 8), byte(v)})
case v < 4294967296:
return e.write([]byte{
uint32Code,
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
default:
return e.write([]byte{
uint64Code,
byte(v >> 56),
byte(v >> 48),
byte(v >> 40),
byte(v >> 32),
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
}
panic("not reached")
}
func (e *Encoder) EncodeInt(v int) error {
return e.EncodeInt64(int64(v))
}
func (e *Encoder) EncodeInt8(v int8) error {
return e.EncodeInt64(int64(v))
}
func (e *Encoder) EncodeInt16(v int16) error {
return e.EncodeInt64(int64(v))
}
func (e *Encoder) EncodeInt32(v int32) error {
return e.EncodeInt64(int64(v))
}
func (e *Encoder) EncodeInt64(v int64) error {
switch {
case v < -2147483648 || v >= 2147483648:
return e.write([]byte{
int64Code,
byte(v >> 56),
byte(v >> 48),
byte(v >> 40),
byte(v >> 32),
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
case v < -32768 || v >= 32768:
return e.write([]byte{
int32Code,
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
case v < -128 || v >= 128:
return e.write([]byte{int16Code, byte(v >> 8), byte(v)})
case v < -32:
return e.write([]byte{int8Code, byte(v)})
default:
return e.W.WriteByte(byte(v))
}
panic("not reached")
}
func (e *Encoder) EncodeBool(value bool) error {
if value {
return e.W.WriteByte(trueCode)
}
return e.W.WriteByte(falseCode)
}
func (e *Encoder) EncodeFloat32(value float32) error {
v := math.Float32bits(value)
return e.write([]byte{
floatCode,
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
}
func (e *Encoder) EncodeFloat64(value float64) error {
v := math.Float64bits(value)
return e.write([]byte{
doubleCode,
byte(v >> 56),
byte(v >> 48),
byte(v >> 40),
byte(v >> 32),
byte(v >> 24),
byte(v >> 16),
byte(v >> 8),
byte(v),
})
}
func (e *Encoder) encodeStruct(v reflect.Value) error {
fields := structs.Fields(v.Type())
switch l := len(fields); {
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
}
}
for _, f := range fields {
if err := e.EncodeString(f.Name()); err != nil {
return err
}
if err := f.EncodeValue(e, v); err != nil {
return err
}
}
return nil
}
func (e *Encoder) write(data []byte) error {
n, err := e.W.Write(data)
if err != nil {
return err
}
if n < len(data) {
return io.ErrShortWrite
}
return nil
}
func (e *Encoder) writeString(s string) error {
n, err := e.W.WriteString(s)
if err != nil {
return err
}
if n < len(s) {
return io.ErrShortWrite
}
return nil
}

67
example_test.go Normal file
View File

@ -0,0 +1,67 @@
package msgpack_test
import (
"bytes"
"fmt"
"git.bit5.ru/backend/msgpack"
)
func ExampleMarshal() {
b, err := msgpack.Marshal(true)
fmt.Printf("%v %#v\n", err, b)
// Output: <nil> []byte{0xc3}
}
func ExampleUnmarshal() {
var out bool
err := msgpack.Unmarshal([]byte{0xc3}, &out)
fmt.Println(err, out)
// Output: <nil> true
}
func Example_mapStringInterface() {
in := map[string]interface{}{"foo": 1, "hello": "world"}
b, err := msgpack.Marshal(in)
_ = err
var out map[string]interface{}
err = msgpack.Unmarshal(b, &out)
fmt.Printf("%v %#v\n", err, out)
// Output: <nil> map[string]interface {}{"foo":1, "hello":"world"}
}
func Example_recursiveMapStringInterface() {
buf := &bytes.Buffer{}
enc := msgpack.NewEncoder(buf)
in := map[string]interface{}{"foo": map[string]interface{}{"hello": "world"}}
_ = enc.Encode(in)
dec := msgpack.NewDecoder(buf)
dec.DecodeMapFunc = func(d *msgpack.Decoder) (interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
m := make(map[string]interface{}, n)
for i := 0; i < n; i++ {
mk, err := d.DecodeString()
if err != nil {
return nil, err
}
mv, err := d.DecodeInterface()
if err != nil {
return nil, err
}
m[mk] = mv
}
return m, nil
}
out, err := dec.DecodeInterface()
fmt.Printf("%v %#v\n", err, out)
// Output: <nil> map[string]interface {}{"foo":map[string]interface {}{"hello":"world"}}
}

10
go.mod Normal file
View File

@ -0,0 +1,10 @@
module git.bit5.ru/backend/msgpack
go 1.13
require (
github.com/ugorji/go/codec v1.2.7
github.com/vmihailenco/bufio v0.0.0-20140618134113-fe7b595919de
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
launchpad.net/gocheck v0.0.0-20140225173054-000000000087
)

10
go.sum Normal file
View File

@ -0,0 +1,10 @@
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/vmihailenco/bufio v0.0.0-20140618134113-fe7b595919de h1:U+I4zEVstMdfNES/2UO8iqkIf214SDMRhdaFTE3A5rA=
github.com/vmihailenco/bufio v0.0.0-20140618134113-fe7b595919de/go.mod h1:ghSGoeEoFFkXNguSget72dMA0+OLq3AGZiqRohVojxI=
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU=
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=

175
map.go Normal file
View File

@ -0,0 +1,175 @@
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
}

18
msgpack.go Normal file
View File

@ -0,0 +1,18 @@
package msgpack
import (
"io"
)
type encoder interface {
EncodeMsgpack(io.Writer) error
}
type decoder interface {
DecodeMsgpack(io.Reader) error
}
type Coder interface {
encoder
decoder
}

1048
msgpack_test.go Normal file

File diff suppressed because it is too large Load Diff

285
slice.go Normal file
View File

@ -0,0 +1,285 @@
package msgpack
import (
"fmt"
"io"
"reflect"
"github.com/vmihailenco/bufio"
)
func (e *Encoder) encodeBytesLen(l int) error {
switch {
case l < 32:
if err := e.W.WriteByte(fixRawLowCode | uint8(l)); err != nil {
return err
}
case l < 65536:
if err := e.write([]byte{
raw16Code,
byte(l >> 8),
byte(l),
}); err != nil {
return err
}
default:
if err := e.write([]byte{
raw32Code,
byte(l >> 24),
byte(l >> 16),
byte(l >> 8),
byte(l),
}); err != nil {
return err
}
}
return nil
}
func (e *Encoder) EncodeString(v string) error {
if err := e.encodeBytesLen(len(v)); err != nil {
return err
}
return e.writeString(v)
}
func (e *Encoder) EncodeBytes(v []byte) error {
if v == nil {
return e.EncodeNil()
}
if err := e.encodeBytesLen(len(v)); err != nil {
return err
}
return e.write(v)
}
func (e *Encoder) encodeSliceLen(l int) error {
switch {
case l < 16:
if err := e.W.WriteByte(fixArrayLowCode | byte(l)); err != nil {
return err
}
case l < 65536:
if err := e.write([]byte{array16Code, byte(l >> 8), byte(l)}); err != nil {
return err
}
default:
if err := e.write([]byte{
array32Code,
byte(l >> 24),
byte(l >> 16),
byte(l >> 8),
byte(l),
}); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeStringSlice(s []string) error {
if s == nil {
return e.EncodeNil()
}
if err := e.encodeSliceLen(len(s)); err != nil {
return err
}
for _, v := range s {
if err := e.EncodeString(v); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeSlice(v reflect.Value) error {
switch v.Type().Elem().Kind() {
case reflect.Uint8:
return e.EncodeBytes(v.Bytes())
}
l := v.Len()
if err := e.encodeSliceLen(l); err != nil {
return err
}
for i := 0; i < l; i++ {
if err := e.EncodeValue(v.Index(i)); err != nil {
return err
}
}
return nil
}
func (d *Decoder) DecodeBytesLen() (int, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c == nilCode {
return -1, nil
} else if c >= fixRawLowCode && c <= fixRawHighCode {
return int(c & fixRawMask), nil
}
switch c {
case raw16Code:
n, err := d.uint16()
return int(n), err
case raw32Code:
n, err := d.uint32()
return int(n), err
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding bytes length", c)
}
func (d *Decoder) DecodeBytes() ([]byte, error) {
n, err := d.DecodeBytesLen()
if err != nil {
return nil, err
}
if n == -1 {
return nil, nil
}
b := make([]byte, n)
_, err = io.ReadFull(d.R, b)
if err != nil {
return nil, err
}
return b, nil
}
func (d *Decoder) bytesValue(value reflect.Value) error {
v, err := d.DecodeBytes()
if err != nil {
return err
}
value.SetBytes(v)
return nil
}
func (d *Decoder) DecodeString() (string, error) {
n, err := d.DecodeBytesLen()
if err != nil {
return "", err
}
if n == -1 {
return "", nil
}
b, err := d.R.ReadN(n)
if err == bufio.ErrBufferFull {
newB := make([]byte, n)
n := copy(newB, b)
b = newB
_, err := io.ReadFull(d.R, newB[n:])
if err != nil {
return "", err
}
} else if err != nil {
return "", err
}
return string(b), nil
}
func (d *Decoder) stringValue(value reflect.Value) error {
v, err := d.DecodeString()
if err != nil {
return err
}
value.SetString(v)
return nil
}
func (d *Decoder) DecodeSliceLen() (int, error) {
c, err := d.R.ReadByte()
if err != nil {
return 0, err
}
if c == nilCode {
return -1, nil
} else if c >= fixArrayLowCode && c <= fixArrayHighCode {
return int(c & fixArrayMask), nil
}
switch c {
case array16Code:
n, err := d.uint16()
return int(n), err
case array32Code:
n, err := d.uint32()
return int(n), err
}
return 0, fmt.Errorf("msgpack: invalid code %x decoding array length", c)
}
func (d *Decoder) decodeIntoStrings(sp *[]string) error {
n, err := d.DecodeSliceLen()
if err != nil {
return err
}
if n == -1 {
return nil
}
s := *sp
if s == nil || len(s) < n {
s = make([]string, n)
}
for i := 0; i < n; i++ {
v, err := d.DecodeString()
if err != nil {
return err
}
s[i] = v
}
*sp = s
return nil
}
func (d *Decoder) DecodeSlice() ([]interface{}, error) {
n, err := d.DecodeSliceLen()
if err != nil {
return nil, err
}
if n == -1 {
return nil, nil
}
s := make([]interface{}, n)
for i := 0; i < n; i++ {
v, err := d.DecodeInterface()
if err != nil {
return nil, err
}
s[i] = v
}
return s, nil
}
func (d *Decoder) sliceValue(v reflect.Value) error {
elemType := v.Type().Elem()
switch elemType.Kind() {
case reflect.Uint8:
b, err := d.DecodeBytes()
if err != nil {
return err
}
v.SetBytes(b)
return nil
}
n, err := d.DecodeSliceLen()
if err != nil {
return err
}
if v.Len() < n || (v.Kind() == reflect.Slice && v.IsNil()) {
v.Set(reflect.MakeSlice(v.Type(), n, n))
}
for i := 0; i < n; i++ {
sv := v.Index(i)
if err := d.DecodeValue(sv); err != nil {
return err
}
}
return nil
}

59
time.go Normal file
View File

@ -0,0 +1,59 @@
package msgpack
import (
"fmt"
"reflect"
"time"
)
var (
timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
)
func init() {
Register(timeType, encodeTime, decodeTime)
}
func (e *Encoder) EncodeTime(tm time.Time) error {
if err := e.W.WriteByte(0x92); err != nil {
return err
}
if err := e.EncodeInt64(tm.Unix()); err != nil {
return err
}
return e.EncodeInt(tm.Nanosecond())
}
func (d *Decoder) DecodeTime() (time.Time, error) {
b, err := d.R.ReadByte()
if err != nil {
return time.Time{}, err
}
if b != 0x92 {
return time.Time{}, fmt.Errorf("msgpack: invalid code %x decoding time", b)
}
sec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
nsec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
return time.Unix(sec, nsec), nil
}
func encodeTime(e *Encoder, v reflect.Value) error {
tm := v.Interface().(time.Time)
return e.EncodeTime(tm)
}
func decodeTime(d *Decoder, v reflect.Value) error {
tm, err := d.DecodeTime()
if err != nil {
return err
}
v.Set(reflect.ValueOf(tm))
return nil
}

277
typeinfo.go Normal file
View File

@ -0,0 +1,277 @@
package msgpack
import (
"reflect"
"strings"
"sync"
)
var structs = newStructCache()
//------------------------------------------------------------------------------
type field interface {
Name() string
EncodeValue(*Encoder, reflect.Value) error
DecodeValue(*Decoder, reflect.Value) error
}
type baseField struct {
idx []int
name string
}
func (f *baseField) Name() string {
return f.name
}
func (f *baseField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeValue(fv)
}
func (f *baseField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.DecodeValue(fv)
}
//------------------------------------------------------------------------------
type boolField struct {
*baseField
}
func (f *boolField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeBool(fv.Bool())
}
func (f *boolField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.boolValue(fv)
}
//------------------------------------------------------------------------------
type float32Field struct {
*baseField
}
func (f *float32Field) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeFloat32(float32(fv.Float()))
}
func (f *float32Field) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.float32Value(fv)
}
//------------------------------------------------------------------------------
type float64Field struct {
*baseField
}
func (f *float64Field) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeFloat64(fv.Float())
}
func (f *float64Field) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.float64Value(fv)
}
//------------------------------------------------------------------------------
type stringField struct {
*baseField
}
func (f *stringField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeString(fv.String())
}
func (f *stringField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.stringValue(fv)
}
//------------------------------------------------------------------------------
type bytesField struct {
*baseField
}
func (f *bytesField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeBytes(fv.Bytes())
}
func (f *bytesField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.bytesValue(fv)
}
//------------------------------------------------------------------------------
type intField struct {
*baseField
}
func (f *intField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeInt64(fv.Int())
}
func (f *intField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.int64Value(fv)
}
//------------------------------------------------------------------------------
type uintField struct {
*baseField
}
func (f *uintField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return e.EncodeUint64(fv.Uint())
}
func (f *uintField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return d.uint64Value(fv)
}
//------------------------------------------------------------------------------
type customField struct {
*baseField
encode encoderFunc
decode decoderFunc
}
func (f *customField) EncodeValue(e *Encoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return f.encode(e, fv)
}
func (f *customField) DecodeValue(d *Decoder, v reflect.Value) error {
fv := v.FieldByIndex(f.idx)
return f.decode(d, fv)
}
//------------------------------------------------------------------------------
type structCache struct {
l sync.RWMutex
m map[reflect.Type][]field
}
func newStructCache() *structCache {
return &structCache{
m: make(map[reflect.Type][]field),
}
}
func (m *structCache) Fields(typ reflect.Type) []field {
m.l.RLock()
fields, ok := m.m[typ]
m.l.RUnlock()
if ok {
return fields
}
numField := typ.NumField()
fields = make([]field, 0, numField)
for i := 0; i < numField; i++ {
f := typ.Field(i)
if f.PkgPath != "" {
continue
}
finfo := m.newStructField(typ, &f)
if finfo != nil {
fields = append(fields, finfo)
}
}
m.l.Lock()
m.m[typ] = fields
m.l.Unlock()
return fields
}
func (m *structCache) newStructField(typ reflect.Type, f *reflect.StructField) field {
tokens := strings.Split(f.Tag.Get("msgpack"), ",")
name := tokens[0]
if name == "-" {
return nil
} else if name == "" {
name = f.Name
}
baseField := &baseField{
idx: f.Index,
name: name,
}
ft := typ.FieldByIndex(f.Index).Type
if encodeFunc, ok := typEncMap[ft]; ok {
decodeFunc := typDecMap[ft]
return &customField{
encode: encodeFunc,
decode: decodeFunc,
baseField: baseField,
}
}
switch ft.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return &intField{
baseField: baseField,
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return &uintField{
baseField: baseField,
}
case reflect.Bool:
return &boolField{
baseField: baseField,
}
case reflect.Float32:
return &float32Field{
baseField: baseField,
}
case reflect.Float64:
return &float64Field{
baseField: baseField,
}
case reflect.Array, reflect.Slice:
if ft.Elem().Kind() == reflect.Uint8 {
return &bytesField{
baseField: baseField,
}
}
case reflect.String:
return &stringField{
baseField: baseField,
}
}
return baseField
}
func (m *structCache) Field(typ reflect.Type, name string) field {
// TODO(vmihailenco): binary search?
for _, f := range m.Fields(typ) {
if f.Name() == name {
return f
}
}
return nil
}