You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
2.6 KiB

package msgpack
import (
"bytes"
"io"
"reflect"
"time"
"github.com/vmihailenco/msgpack/codes"
)
type writer interface {
io.Writer
WriteByte(byte) error
WriteString(string) (int, error)
}
type byteWriter struct {
io.Writer
}
func (w byteWriter) WriteByte(b byte) error {
_, err := w.Write([]byte{b})
return err
}
func (w byteWriter) WriteString(s string) (int, error) {
return w.Write([]byte(s))
}
// Marshal returns the MessagePack encoding of v.
func Marshal(v ...interface{}) ([]byte, error) {
var buf bytes.Buffer
err := NewEncoder(&buf).Encode(v...)
return buf.Bytes(), err
}
type Encoder struct {
w writer
buf []byte
sortMapKeys bool
structAsArray bool
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
bw, ok := w.(writer)
if !ok {
bw = byteWriter{Writer: w}
}
return &Encoder{
w: bw,
buf: make([]byte, 9),
}
}
// SortMapKeys causes the Encoder to encode map keys in increasing order.
// Supported map types are:
// - map[string]string
// - map[string]interface{}
func (e *Encoder) SortMapKeys(v bool) *Encoder {
e.sortMapKeys = v
return e
}
// StructAsArray causes the Encoder to encode Go structs as MessagePack arrays.
func (e *Encoder) StructAsArray(v bool) *Encoder {
e.structAsArray = v
return e
}
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(v interface{}) error {
switch v := v.(type) {
case nil:
return e.EncodeNil()
case string:
return e.EncodeString(v)
case []byte:
return e.EncodeBytes(v)
case int:
return e.EncodeInt(int64(v))
case int64:
return e.EncodeInt(v)
case uint:
return e.EncodeUint(uint64(v))
case uint64:
return e.EncodeUint(v)
case bool:
return e.EncodeBool(v)
case float32:
return e.EncodeFloat32(v)
case float64:
return e.EncodeFloat64(v)
case time.Duration:
return e.EncodeInt(int64(v))
case time.Time:
return e.EncodeTime(v)
}
return e.EncodeValue(reflect.ValueOf(v))
}
func (e *Encoder) EncodeValue(v reflect.Value) error {
encode := getEncoder(v.Type())
return encode(e, v)
}
func (e *Encoder) EncodeNil() error {
return e.writeCode(codes.Nil)
}
func (e *Encoder) EncodeBool(value bool) error {
if value {
return e.writeCode(codes.True)
}
return e.writeCode(codes.False)
}
func (e *Encoder) writeCode(c codes.Code) error {
return e.w.WriteByte(byte(c))
}
func (e *Encoder) write(b []byte) error {
_, err := e.w.Write(b)
return err
}
func (e *Encoder) writeString(s string) error {
_, err := e.w.WriteString(s)
return err
}