diff options
Diffstat (limited to 'vendor/github.com/vmihailenco/msgpack/types.go')
-rw-r--r-- | vendor/github.com/vmihailenco/msgpack/types.go | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/vendor/github.com/vmihailenco/msgpack/types.go b/vendor/github.com/vmihailenco/msgpack/types.go new file mode 100644 index 0000000..6a1bf7f --- /dev/null +++ b/vendor/github.com/vmihailenco/msgpack/types.go | |||
@@ -0,0 +1,310 @@ | |||
1 | package msgpack | ||
2 | |||
3 | import ( | ||
4 | "reflect" | ||
5 | "sync" | ||
6 | ) | ||
7 | |||
8 | var errorType = reflect.TypeOf((*error)(nil)).Elem() | ||
9 | |||
10 | var customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem() | ||
11 | var customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem() | ||
12 | |||
13 | var marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() | ||
14 | var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() | ||
15 | |||
16 | type encoderFunc func(*Encoder, reflect.Value) error | ||
17 | type decoderFunc func(*Decoder, reflect.Value) error | ||
18 | |||
19 | var typEncMap = make(map[reflect.Type]encoderFunc) | ||
20 | var typDecMap = make(map[reflect.Type]decoderFunc) | ||
21 | |||
22 | // Register registers encoder and decoder functions for a value. | ||
23 | // This is low level API and in most cases you should prefer implementing | ||
24 | // Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces. | ||
25 | func Register(value interface{}, enc encoderFunc, dec decoderFunc) { | ||
26 | typ := reflect.TypeOf(value) | ||
27 | if enc != nil { | ||
28 | typEncMap[typ] = enc | ||
29 | } | ||
30 | if dec != nil { | ||
31 | typDecMap[typ] = dec | ||
32 | } | ||
33 | } | ||
34 | |||
35 | //------------------------------------------------------------------------------ | ||
36 | |||
37 | var structs = newStructCache(false) | ||
38 | var jsonStructs = newStructCache(true) | ||
39 | |||
40 | type structCache struct { | ||
41 | mu sync.RWMutex | ||
42 | m map[reflect.Type]*fields | ||
43 | |||
44 | useJSONTag bool | ||
45 | } | ||
46 | |||
47 | func newStructCache(useJSONTag bool) *structCache { | ||
48 | return &structCache{ | ||
49 | m: make(map[reflect.Type]*fields), | ||
50 | |||
51 | useJSONTag: useJSONTag, | ||
52 | } | ||
53 | } | ||
54 | |||
55 | func (m *structCache) Fields(typ reflect.Type) *fields { | ||
56 | m.mu.RLock() | ||
57 | fs, ok := m.m[typ] | ||
58 | m.mu.RUnlock() | ||
59 | if ok { | ||
60 | return fs | ||
61 | } | ||
62 | |||
63 | m.mu.Lock() | ||
64 | fs, ok = m.m[typ] | ||
65 | if !ok { | ||
66 | fs = getFields(typ, m.useJSONTag) | ||
67 | m.m[typ] = fs | ||
68 | } | ||
69 | m.mu.Unlock() | ||
70 | |||
71 | return fs | ||
72 | } | ||
73 | |||
74 | //------------------------------------------------------------------------------ | ||
75 | |||
76 | type field struct { | ||
77 | name string | ||
78 | index []int | ||
79 | omitEmpty bool | ||
80 | encoder encoderFunc | ||
81 | decoder decoderFunc | ||
82 | } | ||
83 | |||
84 | func (f *field) value(v reflect.Value) reflect.Value { | ||
85 | return fieldByIndex(v, f.index) | ||
86 | } | ||
87 | |||
88 | func (f *field) Omit(strct reflect.Value) bool { | ||
89 | return f.omitEmpty && isEmptyValue(f.value(strct)) | ||
90 | } | ||
91 | |||
92 | func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error { | ||
93 | return f.encoder(e, f.value(strct)) | ||
94 | } | ||
95 | |||
96 | func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error { | ||
97 | return f.decoder(d, f.value(strct)) | ||
98 | } | ||
99 | |||
100 | //------------------------------------------------------------------------------ | ||
101 | |||
102 | type fields struct { | ||
103 | Table map[string]*field | ||
104 | List []*field | ||
105 | AsArray bool | ||
106 | |||
107 | hasOmitEmpty bool | ||
108 | } | ||
109 | |||
110 | func newFields(numField int) *fields { | ||
111 | return &fields{ | ||
112 | Table: make(map[string]*field, numField), | ||
113 | List: make([]*field, 0, numField), | ||
114 | } | ||
115 | } | ||
116 | |||
117 | func (fs *fields) Add(field *field) { | ||
118 | fs.Table[field.name] = field | ||
119 | fs.List = append(fs.List, field) | ||
120 | if field.omitEmpty { | ||
121 | fs.hasOmitEmpty = true | ||
122 | } | ||
123 | } | ||
124 | |||
125 | func (fs *fields) OmitEmpty(strct reflect.Value) []*field { | ||
126 | if !fs.hasOmitEmpty { | ||
127 | return fs.List | ||
128 | } | ||
129 | |||
130 | fields := make([]*field, 0, len(fs.List)) | ||
131 | for _, f := range fs.List { | ||
132 | if !f.Omit(strct) { | ||
133 | fields = append(fields, f) | ||
134 | } | ||
135 | } | ||
136 | return fields | ||
137 | } | ||
138 | |||
139 | func getFields(typ reflect.Type, useJSONTag bool) *fields { | ||
140 | numField := typ.NumField() | ||
141 | fs := newFields(numField) | ||
142 | |||
143 | var omitEmpty bool | ||
144 | for i := 0; i < numField; i++ { | ||
145 | f := typ.Field(i) | ||
146 | |||
147 | tag := f.Tag.Get("msgpack") | ||
148 | if useJSONTag && tag == "" { | ||
149 | tag = f.Tag.Get("json") | ||
150 | } | ||
151 | |||
152 | name, opt := parseTag(tag) | ||
153 | if name == "-" { | ||
154 | continue | ||
155 | } | ||
156 | |||
157 | if f.Name == "_msgpack" { | ||
158 | if opt.Contains("asArray") { | ||
159 | fs.AsArray = true | ||
160 | } | ||
161 | if opt.Contains("omitempty") { | ||
162 | omitEmpty = true | ||
163 | } | ||
164 | } | ||
165 | |||
166 | if f.PkgPath != "" && !f.Anonymous { | ||
167 | continue | ||
168 | } | ||
169 | |||
170 | field := &field{ | ||
171 | name: name, | ||
172 | index: f.Index, | ||
173 | omitEmpty: omitEmpty || opt.Contains("omitempty"), | ||
174 | encoder: getEncoder(f.Type), | ||
175 | decoder: getDecoder(f.Type), | ||
176 | } | ||
177 | |||
178 | if field.name == "" { | ||
179 | field.name = f.Name | ||
180 | } | ||
181 | |||
182 | if f.Anonymous && !opt.Contains("noinline") { | ||
183 | inline := opt.Contains("inline") | ||
184 | if inline { | ||
185 | inlineFields(fs, f.Type, field, useJSONTag) | ||
186 | } else { | ||
187 | inline = autoinlineFields(fs, f.Type, field, useJSONTag) | ||
188 | } | ||
189 | if inline { | ||
190 | fs.Table[field.name] = field | ||
191 | continue | ||
192 | } | ||
193 | } | ||
194 | |||
195 | fs.Add(field) | ||
196 | } | ||
197 | return fs | ||
198 | } | ||
199 | |||
200 | var encodeStructValuePtr uintptr | ||
201 | var decodeStructValuePtr uintptr | ||
202 | |||
203 | func init() { | ||
204 | encodeStructValuePtr = reflect.ValueOf(encodeStructValue).Pointer() | ||
205 | decodeStructValuePtr = reflect.ValueOf(decodeStructValue).Pointer() | ||
206 | } | ||
207 | |||
208 | func inlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) { | ||
209 | inlinedFields := getFields(typ, useJSONTag).List | ||
210 | for _, field := range inlinedFields { | ||
211 | if _, ok := fs.Table[field.name]; ok { | ||
212 | // Don't inline shadowed fields. | ||
213 | continue | ||
214 | } | ||
215 | field.index = append(f.index, field.index...) | ||
216 | fs.Add(field) | ||
217 | } | ||
218 | } | ||
219 | |||
220 | func autoinlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) bool { | ||
221 | var encoder encoderFunc | ||
222 | var decoder decoderFunc | ||
223 | |||
224 | if typ.Kind() == reflect.Struct { | ||
225 | encoder = f.encoder | ||
226 | decoder = f.decoder | ||
227 | } else { | ||
228 | for typ.Kind() == reflect.Ptr { | ||
229 | typ = typ.Elem() | ||
230 | encoder = getEncoder(typ) | ||
231 | decoder = getDecoder(typ) | ||
232 | } | ||
233 | if typ.Kind() != reflect.Struct { | ||
234 | return false | ||
235 | } | ||
236 | } | ||
237 | |||
238 | if reflect.ValueOf(encoder).Pointer() != encodeStructValuePtr { | ||
239 | return false | ||
240 | } | ||
241 | if reflect.ValueOf(decoder).Pointer() != decodeStructValuePtr { | ||
242 | return false | ||
243 | } | ||
244 | |||
245 | inlinedFields := getFields(typ, useJSONTag).List | ||
246 | for _, field := range inlinedFields { | ||
247 | if _, ok := fs.Table[field.name]; ok { | ||
248 | // Don't auto inline if there are shadowed fields. | ||
249 | return false | ||
250 | } | ||
251 | } | ||
252 | |||
253 | for _, field := range inlinedFields { | ||
254 | field.index = append(f.index, field.index...) | ||
255 | fs.Add(field) | ||
256 | } | ||
257 | return true | ||
258 | } | ||
259 | |||
260 | func isEmptyValue(v reflect.Value) bool { | ||
261 | switch v.Kind() { | ||
262 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: | ||
263 | return v.Len() == 0 | ||
264 | case reflect.Bool: | ||
265 | return !v.Bool() | ||
266 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
267 | return v.Int() == 0 | ||
268 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||
269 | return v.Uint() == 0 | ||
270 | case reflect.Float32, reflect.Float64: | ||
271 | return v.Float() == 0 | ||
272 | case reflect.Interface, reflect.Ptr: | ||
273 | return v.IsNil() | ||
274 | } | ||
275 | return false | ||
276 | } | ||
277 | |||
278 | func fieldByIndex(v reflect.Value, index []int) reflect.Value { | ||
279 | if len(index) == 1 { | ||
280 | return v.Field(index[0]) | ||
281 | } | ||
282 | for i, x := range index { | ||
283 | if i > 0 { | ||
284 | var ok bool | ||
285 | v, ok = indirectNew(v) | ||
286 | if !ok { | ||
287 | return v | ||
288 | } | ||
289 | } | ||
290 | v = v.Field(x) | ||
291 | } | ||
292 | return v | ||
293 | } | ||
294 | |||
295 | func indirectNew(v reflect.Value) (reflect.Value, bool) { | ||
296 | if v.Kind() == reflect.Ptr { | ||
297 | if v.IsNil() { | ||
298 | if !v.CanSet() { | ||
299 | return v, false | ||
300 | } | ||
301 | elemType := v.Type().Elem() | ||
302 | if elemType.Kind() != reflect.Struct { | ||
303 | return v, false | ||
304 | } | ||
305 | v.Set(reflect.New(elemType)) | ||
306 | } | ||
307 | v = v.Elem() | ||
308 | } | ||
309 | return v, true | ||
310 | } | ||