]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/vmihailenco/msgpack/types.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / vmihailenco / msgpack / types.go
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 }