gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

encode.go (5274B)


      1 package msgpack
      2 
      3 import (
      4 	"bytes"
      5 	"io"
      6 	"reflect"
      7 	"sync"
      8 	"time"
      9 
     10 	"github.com/vmihailenco/msgpack/v5/msgpcode"
     11 )
     12 
     13 const (
     14 	sortMapKeysFlag uint32 = 1 << iota
     15 	arrayEncodedStructsFlag
     16 	useCompactIntsFlag
     17 	useCompactFloatsFlag
     18 	useInternedStringsFlag
     19 	omitEmptyFlag
     20 )
     21 
     22 type writer interface {
     23 	io.Writer
     24 	WriteByte(byte) error
     25 }
     26 
     27 type byteWriter struct {
     28 	io.Writer
     29 }
     30 
     31 func newByteWriter(w io.Writer) byteWriter {
     32 	return byteWriter{
     33 		Writer: w,
     34 	}
     35 }
     36 
     37 func (bw byteWriter) WriteByte(c byte) error {
     38 	_, err := bw.Write([]byte{c})
     39 	return err
     40 }
     41 
     42 //------------------------------------------------------------------------------
     43 
     44 var encPool = sync.Pool{
     45 	New: func() interface{} {
     46 		return NewEncoder(nil)
     47 	},
     48 }
     49 
     50 func GetEncoder() *Encoder {
     51 	return encPool.Get().(*Encoder)
     52 }
     53 
     54 func PutEncoder(enc *Encoder) {
     55 	enc.w = nil
     56 	encPool.Put(enc)
     57 }
     58 
     59 // Marshal returns the MessagePack encoding of v.
     60 func Marshal(v interface{}) ([]byte, error) {
     61 	enc := GetEncoder()
     62 
     63 	var buf bytes.Buffer
     64 	enc.Reset(&buf)
     65 
     66 	err := enc.Encode(v)
     67 	b := buf.Bytes()
     68 
     69 	PutEncoder(enc)
     70 
     71 	if err != nil {
     72 		return nil, err
     73 	}
     74 	return b, err
     75 }
     76 
     77 type Encoder struct {
     78 	w writer
     79 
     80 	buf     []byte
     81 	timeBuf []byte
     82 
     83 	dict map[string]int
     84 
     85 	flags     uint32
     86 	structTag string
     87 }
     88 
     89 // NewEncoder returns a new encoder that writes to w.
     90 func NewEncoder(w io.Writer) *Encoder {
     91 	e := &Encoder{
     92 		buf: make([]byte, 9),
     93 	}
     94 	e.Reset(w)
     95 	return e
     96 }
     97 
     98 // Writer returns the Encoder's writer.
     99 func (e *Encoder) Writer() io.Writer {
    100 	return e.w
    101 }
    102 
    103 // Reset discards any buffered data, resets all state, and switches the writer to write to w.
    104 func (e *Encoder) Reset(w io.Writer) {
    105 	e.ResetDict(w, nil)
    106 }
    107 
    108 // ResetDict is like Reset, but also resets the dict.
    109 func (e *Encoder) ResetDict(w io.Writer, dict map[string]int) {
    110 	e.resetWriter(w)
    111 	e.flags = 0
    112 	e.structTag = ""
    113 	e.dict = dict
    114 }
    115 
    116 func (e *Encoder) WithDict(dict map[string]int, fn func(*Encoder) error) error {
    117 	oldDict := e.dict
    118 	e.dict = dict
    119 	err := fn(e)
    120 	e.dict = oldDict
    121 	return err
    122 }
    123 
    124 func (e *Encoder) resetWriter(w io.Writer) {
    125 	if bw, ok := w.(writer); ok {
    126 		e.w = bw
    127 	} else {
    128 		e.w = newByteWriter(w)
    129 	}
    130 }
    131 
    132 // SetSortMapKeys causes the Encoder to encode map keys in increasing order.
    133 // Supported map types are:
    134 //   - map[string]string
    135 //   - map[string]interface{}
    136 func (e *Encoder) SetSortMapKeys(on bool) *Encoder {
    137 	if on {
    138 		e.flags |= sortMapKeysFlag
    139 	} else {
    140 		e.flags &= ^sortMapKeysFlag
    141 	}
    142 	return e
    143 }
    144 
    145 // SetCustomStructTag causes the Encoder to use a custom struct tag as
    146 // fallback option if there is no msgpack tag.
    147 func (e *Encoder) SetCustomStructTag(tag string) {
    148 	e.structTag = tag
    149 }
    150 
    151 // SetOmitEmpty causes the Encoder to omit empty values by default.
    152 func (e *Encoder) SetOmitEmpty(on bool) {
    153 	if on {
    154 		e.flags |= omitEmptyFlag
    155 	} else {
    156 		e.flags &= ^omitEmptyFlag
    157 	}
    158 }
    159 
    160 // UseArrayEncodedStructs causes the Encoder to encode Go structs as msgpack arrays.
    161 func (e *Encoder) UseArrayEncodedStructs(on bool) {
    162 	if on {
    163 		e.flags |= arrayEncodedStructsFlag
    164 	} else {
    165 		e.flags &= ^arrayEncodedStructsFlag
    166 	}
    167 }
    168 
    169 // UseCompactEncoding causes the Encoder to chose the most compact encoding.
    170 // For example, it allows to encode small Go int64 as msgpack int8 saving 7 bytes.
    171 func (e *Encoder) UseCompactInts(on bool) {
    172 	if on {
    173 		e.flags |= useCompactIntsFlag
    174 	} else {
    175 		e.flags &= ^useCompactIntsFlag
    176 	}
    177 }
    178 
    179 // UseCompactFloats causes the Encoder to chose a compact integer encoding
    180 // for floats that can be represented as integers.
    181 func (e *Encoder) UseCompactFloats(on bool) {
    182 	if on {
    183 		e.flags |= useCompactFloatsFlag
    184 	} else {
    185 		e.flags &= ^useCompactFloatsFlag
    186 	}
    187 }
    188 
    189 // UseInternedStrings causes the Encoder to intern strings.
    190 func (e *Encoder) UseInternedStrings(on bool) {
    191 	if on {
    192 		e.flags |= useInternedStringsFlag
    193 	} else {
    194 		e.flags &= ^useInternedStringsFlag
    195 	}
    196 }
    197 
    198 func (e *Encoder) Encode(v interface{}) error {
    199 	switch v := v.(type) {
    200 	case nil:
    201 		return e.EncodeNil()
    202 	case string:
    203 		return e.EncodeString(v)
    204 	case []byte:
    205 		return e.EncodeBytes(v)
    206 	case int:
    207 		return e.EncodeInt(int64(v))
    208 	case int64:
    209 		return e.encodeInt64Cond(v)
    210 	case uint:
    211 		return e.EncodeUint(uint64(v))
    212 	case uint64:
    213 		return e.encodeUint64Cond(v)
    214 	case bool:
    215 		return e.EncodeBool(v)
    216 	case float32:
    217 		return e.EncodeFloat32(v)
    218 	case float64:
    219 		return e.EncodeFloat64(v)
    220 	case time.Duration:
    221 		return e.encodeInt64Cond(int64(v))
    222 	case time.Time:
    223 		return e.EncodeTime(v)
    224 	}
    225 	return e.EncodeValue(reflect.ValueOf(v))
    226 }
    227 
    228 func (e *Encoder) EncodeMulti(v ...interface{}) error {
    229 	for _, vv := range v {
    230 		if err := e.Encode(vv); err != nil {
    231 			return err
    232 		}
    233 	}
    234 	return nil
    235 }
    236 
    237 func (e *Encoder) EncodeValue(v reflect.Value) error {
    238 	fn := getEncoder(v.Type())
    239 	return fn(e, v)
    240 }
    241 
    242 func (e *Encoder) EncodeNil() error {
    243 	return e.writeCode(msgpcode.Nil)
    244 }
    245 
    246 func (e *Encoder) EncodeBool(value bool) error {
    247 	if value {
    248 		return e.writeCode(msgpcode.True)
    249 	}
    250 	return e.writeCode(msgpcode.False)
    251 }
    252 
    253 func (e *Encoder) EncodeDuration(d time.Duration) error {
    254 	return e.EncodeInt(int64(d))
    255 }
    256 
    257 func (e *Encoder) writeCode(c byte) error {
    258 	return e.w.WriteByte(c)
    259 }
    260 
    261 func (e *Encoder) write(b []byte) error {
    262 	_, err := e.w.Write(b)
    263 	return err
    264 }
    265 
    266 func (e *Encoder) writeString(s string) error {
    267 	_, err := e.w.Write(stringToBytes(s))
    268 	return err
    269 }