diff options
author | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
---|---|---|
committer | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
commit | 107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch) | |
tree | ca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/go-ini/ini/struct.go | |
parent | 844b5a68d8af4791755b8f0ad293cc99f5959183 (diff) | |
download | terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip |
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/go-ini/ini/struct.go')
-rw-r--r-- | vendor/github.com/go-ini/ini/struct.go | 450 |
1 files changed, 0 insertions, 450 deletions
diff --git a/vendor/github.com/go-ini/ini/struct.go b/vendor/github.com/go-ini/ini/struct.go deleted file mode 100644 index 509c682..0000000 --- a/vendor/github.com/go-ini/ini/struct.go +++ /dev/null | |||
@@ -1,450 +0,0 @@ | |||
1 | // Copyright 2014 Unknwon | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may | ||
4 | // not use this file except in compliance with the License. You may obtain | ||
5 | // a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
12 | // License for the specific language governing permissions and limitations | ||
13 | // under the License. | ||
14 | |||
15 | package ini | ||
16 | |||
17 | import ( | ||
18 | "bytes" | ||
19 | "errors" | ||
20 | "fmt" | ||
21 | "reflect" | ||
22 | "strings" | ||
23 | "time" | ||
24 | "unicode" | ||
25 | ) | ||
26 | |||
27 | // NameMapper represents a ini tag name mapper. | ||
28 | type NameMapper func(string) string | ||
29 | |||
30 | // Built-in name getters. | ||
31 | var ( | ||
32 | // AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. | ||
33 | AllCapsUnderscore NameMapper = func(raw string) string { | ||
34 | newstr := make([]rune, 0, len(raw)) | ||
35 | for i, chr := range raw { | ||
36 | if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { | ||
37 | if i > 0 { | ||
38 | newstr = append(newstr, '_') | ||
39 | } | ||
40 | } | ||
41 | newstr = append(newstr, unicode.ToUpper(chr)) | ||
42 | } | ||
43 | return string(newstr) | ||
44 | } | ||
45 | // TitleUnderscore converts to format title_underscore. | ||
46 | TitleUnderscore NameMapper = func(raw string) string { | ||
47 | newstr := make([]rune, 0, len(raw)) | ||
48 | for i, chr := range raw { | ||
49 | if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { | ||
50 | if i > 0 { | ||
51 | newstr = append(newstr, '_') | ||
52 | } | ||
53 | chr -= ('A' - 'a') | ||
54 | } | ||
55 | newstr = append(newstr, chr) | ||
56 | } | ||
57 | return string(newstr) | ||
58 | } | ||
59 | ) | ||
60 | |||
61 | func (s *Section) parseFieldName(raw, actual string) string { | ||
62 | if len(actual) > 0 { | ||
63 | return actual | ||
64 | } | ||
65 | if s.f.NameMapper != nil { | ||
66 | return s.f.NameMapper(raw) | ||
67 | } | ||
68 | return raw | ||
69 | } | ||
70 | |||
71 | func parseDelim(actual string) string { | ||
72 | if len(actual) > 0 { | ||
73 | return actual | ||
74 | } | ||
75 | return "," | ||
76 | } | ||
77 | |||
78 | var reflectTime = reflect.TypeOf(time.Now()).Kind() | ||
79 | |||
80 | // setSliceWithProperType sets proper values to slice based on its type. | ||
81 | func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error { | ||
82 | var strs []string | ||
83 | if allowShadow { | ||
84 | strs = key.StringsWithShadows(delim) | ||
85 | } else { | ||
86 | strs = key.Strings(delim) | ||
87 | } | ||
88 | |||
89 | numVals := len(strs) | ||
90 | if numVals == 0 { | ||
91 | return nil | ||
92 | } | ||
93 | |||
94 | var vals interface{} | ||
95 | |||
96 | sliceOf := field.Type().Elem().Kind() | ||
97 | switch sliceOf { | ||
98 | case reflect.String: | ||
99 | vals = strs | ||
100 | case reflect.Int: | ||
101 | vals, _ = key.parseInts(strs, true, false) | ||
102 | case reflect.Int64: | ||
103 | vals, _ = key.parseInt64s(strs, true, false) | ||
104 | case reflect.Uint: | ||
105 | vals = key.Uints(delim) | ||
106 | case reflect.Uint64: | ||
107 | vals = key.Uint64s(delim) | ||
108 | case reflect.Float64: | ||
109 | vals = key.Float64s(delim) | ||
110 | case reflectTime: | ||
111 | vals = key.Times(delim) | ||
112 | default: | ||
113 | return fmt.Errorf("unsupported type '[]%s'", sliceOf) | ||
114 | } | ||
115 | |||
116 | slice := reflect.MakeSlice(field.Type(), numVals, numVals) | ||
117 | for i := 0; i < numVals; i++ { | ||
118 | switch sliceOf { | ||
119 | case reflect.String: | ||
120 | slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i])) | ||
121 | case reflect.Int: | ||
122 | slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i])) | ||
123 | case reflect.Int64: | ||
124 | slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i])) | ||
125 | case reflect.Uint: | ||
126 | slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i])) | ||
127 | case reflect.Uint64: | ||
128 | slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i])) | ||
129 | case reflect.Float64: | ||
130 | slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i])) | ||
131 | case reflectTime: | ||
132 | slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i])) | ||
133 | } | ||
134 | } | ||
135 | field.Set(slice) | ||
136 | return nil | ||
137 | } | ||
138 | |||
139 | // setWithProperType sets proper value to field based on its type, | ||
140 | // but it does not return error for failing parsing, | ||
141 | // because we want to use default value that is already assigned to strcut. | ||
142 | func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error { | ||
143 | switch t.Kind() { | ||
144 | case reflect.String: | ||
145 | if len(key.String()) == 0 { | ||
146 | return nil | ||
147 | } | ||
148 | field.SetString(key.String()) | ||
149 | case reflect.Bool: | ||
150 | boolVal, err := key.Bool() | ||
151 | if err != nil { | ||
152 | return nil | ||
153 | } | ||
154 | field.SetBool(boolVal) | ||
155 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
156 | durationVal, err := key.Duration() | ||
157 | // Skip zero value | ||
158 | if err == nil && int(durationVal) > 0 { | ||
159 | field.Set(reflect.ValueOf(durationVal)) | ||
160 | return nil | ||
161 | } | ||
162 | |||
163 | intVal, err := key.Int64() | ||
164 | if err != nil || intVal == 0 { | ||
165 | return nil | ||
166 | } | ||
167 | field.SetInt(intVal) | ||
168 | // byte is an alias for uint8, so supporting uint8 breaks support for byte | ||
169 | case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
170 | durationVal, err := key.Duration() | ||
171 | // Skip zero value | ||
172 | if err == nil && int(durationVal) > 0 { | ||
173 | field.Set(reflect.ValueOf(durationVal)) | ||
174 | return nil | ||
175 | } | ||
176 | |||
177 | uintVal, err := key.Uint64() | ||
178 | if err != nil { | ||
179 | return nil | ||
180 | } | ||
181 | field.SetUint(uintVal) | ||
182 | |||
183 | case reflect.Float32, reflect.Float64: | ||
184 | floatVal, err := key.Float64() | ||
185 | if err != nil { | ||
186 | return nil | ||
187 | } | ||
188 | field.SetFloat(floatVal) | ||
189 | case reflectTime: | ||
190 | timeVal, err := key.Time() | ||
191 | if err != nil { | ||
192 | return nil | ||
193 | } | ||
194 | field.Set(reflect.ValueOf(timeVal)) | ||
195 | case reflect.Slice: | ||
196 | return setSliceWithProperType(key, field, delim, allowShadow) | ||
197 | default: | ||
198 | return fmt.Errorf("unsupported type '%s'", t) | ||
199 | } | ||
200 | return nil | ||
201 | } | ||
202 | |||
203 | func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool) { | ||
204 | opts := strings.SplitN(tag, ",", 3) | ||
205 | rawName = opts[0] | ||
206 | if len(opts) > 1 { | ||
207 | omitEmpty = opts[1] == "omitempty" | ||
208 | } | ||
209 | if len(opts) > 2 { | ||
210 | allowShadow = opts[2] == "allowshadow" | ||
211 | } | ||
212 | return rawName, omitEmpty, allowShadow | ||
213 | } | ||
214 | |||
215 | func (s *Section) mapTo(val reflect.Value) error { | ||
216 | if val.Kind() == reflect.Ptr { | ||
217 | val = val.Elem() | ||
218 | } | ||
219 | typ := val.Type() | ||
220 | |||
221 | for i := 0; i < typ.NumField(); i++ { | ||
222 | field := val.Field(i) | ||
223 | tpField := typ.Field(i) | ||
224 | |||
225 | tag := tpField.Tag.Get("ini") | ||
226 | if tag == "-" { | ||
227 | continue | ||
228 | } | ||
229 | |||
230 | rawName, _, allowShadow := parseTagOptions(tag) | ||
231 | fieldName := s.parseFieldName(tpField.Name, rawName) | ||
232 | if len(fieldName) == 0 || !field.CanSet() { | ||
233 | continue | ||
234 | } | ||
235 | |||
236 | isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous | ||
237 | isStruct := tpField.Type.Kind() == reflect.Struct | ||
238 | if isAnonymous { | ||
239 | field.Set(reflect.New(tpField.Type.Elem())) | ||
240 | } | ||
241 | |||
242 | if isAnonymous || isStruct { | ||
243 | if sec, err := s.f.GetSection(fieldName); err == nil { | ||
244 | if err = sec.mapTo(field); err != nil { | ||
245 | return fmt.Errorf("error mapping field(%s): %v", fieldName, err) | ||
246 | } | ||
247 | continue | ||
248 | } | ||
249 | } | ||
250 | |||
251 | if key, err := s.GetKey(fieldName); err == nil { | ||
252 | delim := parseDelim(tpField.Tag.Get("delim")) | ||
253 | if err = setWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil { | ||
254 | return fmt.Errorf("error mapping field(%s): %v", fieldName, err) | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | return nil | ||
259 | } | ||
260 | |||
261 | // MapTo maps section to given struct. | ||
262 | func (s *Section) MapTo(v interface{}) error { | ||
263 | typ := reflect.TypeOf(v) | ||
264 | val := reflect.ValueOf(v) | ||
265 | if typ.Kind() == reflect.Ptr { | ||
266 | typ = typ.Elem() | ||
267 | val = val.Elem() | ||
268 | } else { | ||
269 | return errors.New("cannot map to non-pointer struct") | ||
270 | } | ||
271 | |||
272 | return s.mapTo(val) | ||
273 | } | ||
274 | |||
275 | // MapTo maps file to given struct. | ||
276 | func (f *File) MapTo(v interface{}) error { | ||
277 | return f.Section("").MapTo(v) | ||
278 | } | ||
279 | |||
280 | // MapTo maps data sources to given struct with name mapper. | ||
281 | func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { | ||
282 | cfg, err := Load(source, others...) | ||
283 | if err != nil { | ||
284 | return err | ||
285 | } | ||
286 | cfg.NameMapper = mapper | ||
287 | return cfg.MapTo(v) | ||
288 | } | ||
289 | |||
290 | // MapTo maps data sources to given struct. | ||
291 | func MapTo(v, source interface{}, others ...interface{}) error { | ||
292 | return MapToWithMapper(v, nil, source, others...) | ||
293 | } | ||
294 | |||
295 | // reflectSliceWithProperType does the opposite thing as setSliceWithProperType. | ||
296 | func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) error { | ||
297 | slice := field.Slice(0, field.Len()) | ||
298 | if field.Len() == 0 { | ||
299 | return nil | ||
300 | } | ||
301 | |||
302 | var buf bytes.Buffer | ||
303 | sliceOf := field.Type().Elem().Kind() | ||
304 | for i := 0; i < field.Len(); i++ { | ||
305 | switch sliceOf { | ||
306 | case reflect.String: | ||
307 | buf.WriteString(slice.Index(i).String()) | ||
308 | case reflect.Int, reflect.Int64: | ||
309 | buf.WriteString(fmt.Sprint(slice.Index(i).Int())) | ||
310 | case reflect.Uint, reflect.Uint64: | ||
311 | buf.WriteString(fmt.Sprint(slice.Index(i).Uint())) | ||
312 | case reflect.Float64: | ||
313 | buf.WriteString(fmt.Sprint(slice.Index(i).Float())) | ||
314 | case reflectTime: | ||
315 | buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339)) | ||
316 | default: | ||
317 | return fmt.Errorf("unsupported type '[]%s'", sliceOf) | ||
318 | } | ||
319 | buf.WriteString(delim) | ||
320 | } | ||
321 | key.SetValue(buf.String()[:buf.Len()-1]) | ||
322 | return nil | ||
323 | } | ||
324 | |||
325 | // reflectWithProperType does the opposite thing as setWithProperType. | ||
326 | func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error { | ||
327 | switch t.Kind() { | ||
328 | case reflect.String: | ||
329 | key.SetValue(field.String()) | ||
330 | case reflect.Bool: | ||
331 | key.SetValue(fmt.Sprint(field.Bool())) | ||
332 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
333 | key.SetValue(fmt.Sprint(field.Int())) | ||
334 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
335 | key.SetValue(fmt.Sprint(field.Uint())) | ||
336 | case reflect.Float32, reflect.Float64: | ||
337 | key.SetValue(fmt.Sprint(field.Float())) | ||
338 | case reflectTime: | ||
339 | key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339))) | ||
340 | case reflect.Slice: | ||
341 | return reflectSliceWithProperType(key, field, delim) | ||
342 | default: | ||
343 | return fmt.Errorf("unsupported type '%s'", t) | ||
344 | } | ||
345 | return nil | ||
346 | } | ||
347 | |||
348 | // CR: copied from encoding/json/encode.go with modifications of time.Time support. | ||
349 | // TODO: add more test coverage. | ||
350 | func isEmptyValue(v reflect.Value) bool { | ||
351 | switch v.Kind() { | ||
352 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: | ||
353 | return v.Len() == 0 | ||
354 | case reflect.Bool: | ||
355 | return !v.Bool() | ||
356 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
357 | return v.Int() == 0 | ||
358 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||
359 | return v.Uint() == 0 | ||
360 | case reflect.Float32, reflect.Float64: | ||
361 | return v.Float() == 0 | ||
362 | case reflectTime: | ||
363 | return v.Interface().(time.Time).IsZero() | ||
364 | case reflect.Interface, reflect.Ptr: | ||
365 | return v.IsNil() | ||
366 | } | ||
367 | return false | ||
368 | } | ||
369 | |||
370 | func (s *Section) reflectFrom(val reflect.Value) error { | ||
371 | if val.Kind() == reflect.Ptr { | ||
372 | val = val.Elem() | ||
373 | } | ||
374 | typ := val.Type() | ||
375 | |||
376 | for i := 0; i < typ.NumField(); i++ { | ||
377 | field := val.Field(i) | ||
378 | tpField := typ.Field(i) | ||
379 | |||
380 | tag := tpField.Tag.Get("ini") | ||
381 | if tag == "-" { | ||
382 | continue | ||
383 | } | ||
384 | |||
385 | opts := strings.SplitN(tag, ",", 2) | ||
386 | if len(opts) == 2 && opts[1] == "omitempty" && isEmptyValue(field) { | ||
387 | continue | ||
388 | } | ||
389 | |||
390 | fieldName := s.parseFieldName(tpField.Name, opts[0]) | ||
391 | if len(fieldName) == 0 || !field.CanSet() { | ||
392 | continue | ||
393 | } | ||
394 | |||
395 | if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) || | ||
396 | (tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") { | ||
397 | // Note: The only error here is section doesn't exist. | ||
398 | sec, err := s.f.GetSection(fieldName) | ||
399 | if err != nil { | ||
400 | // Note: fieldName can never be empty here, ignore error. | ||
401 | sec, _ = s.f.NewSection(fieldName) | ||
402 | } | ||
403 | if err = sec.reflectFrom(field); err != nil { | ||
404 | return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) | ||
405 | } | ||
406 | continue | ||
407 | } | ||
408 | |||
409 | // Note: Same reason as secion. | ||
410 | key, err := s.GetKey(fieldName) | ||
411 | if err != nil { | ||
412 | key, _ = s.NewKey(fieldName, "") | ||
413 | } | ||
414 | if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { | ||
415 | return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) | ||
416 | } | ||
417 | |||
418 | } | ||
419 | return nil | ||
420 | } | ||
421 | |||
422 | // ReflectFrom reflects secion from given struct. | ||
423 | func (s *Section) ReflectFrom(v interface{}) error { | ||
424 | typ := reflect.TypeOf(v) | ||
425 | val := reflect.ValueOf(v) | ||
426 | if typ.Kind() == reflect.Ptr { | ||
427 | typ = typ.Elem() | ||
428 | val = val.Elem() | ||
429 | } else { | ||
430 | return errors.New("cannot reflect from non-pointer struct") | ||
431 | } | ||
432 | |||
433 | return s.reflectFrom(val) | ||
434 | } | ||
435 | |||
436 | // ReflectFrom reflects file from given struct. | ||
437 | func (f *File) ReflectFrom(v interface{}) error { | ||
438 | return f.Section("").ReflectFrom(v) | ||
439 | } | ||
440 | |||
441 | // ReflectFrom reflects data sources from given struct with name mapper. | ||
442 | func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error { | ||
443 | cfg.NameMapper = mapper | ||
444 | return cfg.ReflectFrom(v) | ||
445 | } | ||
446 | |||
447 | // ReflectFrom reflects data sources from given struct. | ||
448 | func ReflectFrom(cfg *File, v interface{}) error { | ||
449 | return ReflectFromWithMapper(cfg, v, nil) | ||
450 | } | ||