1 package toml
2
3 import (
4 "bytes"
5 "encoding"
6 "encoding/json"
7 "fmt"
8 "io"
9 "io/ioutil"
10 "math"
11 "os"
12 "reflect"
13 "strconv"
14 "strings"
15 "time"
16 )
17
18
19
20 type Unmarshaler interface {
21 UnmarshalTOML(interface{}) error
22 }
23
24
25
26
27 func Unmarshal(data []byte, v interface{}) error {
28 _, err := NewDecoder(bytes.NewReader(data)).Decode(v)
29 return err
30 }
31
32
33
34
35 func Decode(data string, v interface{}) (MetaData, error) {
36 return NewDecoder(strings.NewReader(data)).Decode(v)
37 }
38
39
40 func DecodeFile(path string, v interface{}) (MetaData, error) {
41 fp, err := os.Open(path)
42 if err != nil {
43 return MetaData{}, err
44 }
45 defer fp.Close()
46 return NewDecoder(fp).Decode(v)
47 }
48
49
50
51
52
53
54
55
56
57
58
59
60 type Primitive struct {
61 undecoded interface{}
62 context Key
63 }
64
65
66
67 const (
68 maxSafeFloat32Int = 16777215
69 maxSafeFloat64Int = int64(9007199254740991)
70 )
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 type Decoder struct {
110 r io.Reader
111 }
112
113
114 func NewDecoder(r io.Reader) *Decoder {
115 return &Decoder{r: r}
116 }
117
118 var (
119 unmarshalToml = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
120 unmarshalText = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
121 primitiveType = reflect.TypeOf((*Primitive)(nil)).Elem()
122 )
123
124
125 func (dec *Decoder) Decode(v interface{}) (MetaData, error) {
126 rv := reflect.ValueOf(v)
127 if rv.Kind() != reflect.Ptr {
128 s := "%q"
129 if reflect.TypeOf(v) == nil {
130 s = "%v"
131 }
132
133 return MetaData{}, fmt.Errorf("toml: cannot decode to non-pointer "+s, reflect.TypeOf(v))
134 }
135 if rv.IsNil() {
136 return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v))
137 }
138
139
140
141 rv = indirect(rv)
142 rt := rv.Type()
143 if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map &&
144 !(rv.Kind() == reflect.Interface && rv.NumMethod() == 0) &&
145 !rt.Implements(unmarshalToml) && !rt.Implements(unmarshalText) {
146 return MetaData{}, fmt.Errorf("toml: cannot decode to type %s", rt)
147 }
148
149
150
151 data, err := ioutil.ReadAll(dec.r)
152 if err != nil {
153 return MetaData{}, err
154 }
155
156 p, err := parse(string(data))
157 if err != nil {
158 return MetaData{}, err
159 }
160
161 md := MetaData{
162 mapping: p.mapping,
163 keyInfo: p.keyInfo,
164 keys: p.ordered,
165 decoded: make(map[string]struct{}, len(p.ordered)),
166 context: nil,
167 data: data,
168 }
169 return md, md.unify(p.mapping, rv)
170 }
171
172
173
174
175
176
177
178
179
180
181
182 func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
183 md.context = primValue.context
184 defer func() { md.context = nil }()
185 return md.unify(primValue.undecoded, rvalue(v))
186 }
187
188
189
190
191
192
193 func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
194
195
196 if rv.Type() == primitiveType {
197
198
199 context := make(Key, len(md.context))
200 copy(context, md.context)
201 rv.Set(reflect.ValueOf(Primitive{
202 undecoded: data,
203 context: context,
204 }))
205 return nil
206 }
207
208 rvi := rv.Interface()
209 if v, ok := rvi.(Unmarshaler); ok {
210 return v.UnmarshalTOML(data)
211 }
212 if v, ok := rvi.(encoding.TextUnmarshaler); ok {
213 return md.unifyText(data, v)
214 }
215
216
217
218
219
220
221
222
223
224 k := rv.Kind()
225
226 if k >= reflect.Int && k <= reflect.Uint64 {
227 return md.unifyInt(data, rv)
228 }
229 switch k {
230 case reflect.Ptr:
231 elem := reflect.New(rv.Type().Elem())
232 err := md.unify(data, reflect.Indirect(elem))
233 if err != nil {
234 return err
235 }
236 rv.Set(elem)
237 return nil
238 case reflect.Struct:
239 return md.unifyStruct(data, rv)
240 case reflect.Map:
241 return md.unifyMap(data, rv)
242 case reflect.Array:
243 return md.unifyArray(data, rv)
244 case reflect.Slice:
245 return md.unifySlice(data, rv)
246 case reflect.String:
247 return md.unifyString(data, rv)
248 case reflect.Bool:
249 return md.unifyBool(data, rv)
250 case reflect.Interface:
251 if rv.NumMethod() > 0 {
252 return md.e("unsupported type %s", rv.Type())
253 }
254 return md.unifyAnything(data, rv)
255 case reflect.Float32, reflect.Float64:
256 return md.unifyFloat64(data, rv)
257 }
258 return md.e("unsupported type %s", rv.Kind())
259 }
260
261 func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
262 tmap, ok := mapping.(map[string]interface{})
263 if !ok {
264 if mapping == nil {
265 return nil
266 }
267 return md.e("type mismatch for %s: expected table but found %T",
268 rv.Type().String(), mapping)
269 }
270
271 for key, datum := range tmap {
272 var f *field
273 fields := cachedTypeFields(rv.Type())
274 for i := range fields {
275 ff := &fields[i]
276 if ff.name == key {
277 f = ff
278 break
279 }
280 if f == nil && strings.EqualFold(ff.name, key) {
281 f = ff
282 }
283 }
284 if f != nil {
285 subv := rv
286 for _, i := range f.index {
287 subv = indirect(subv.Field(i))
288 }
289
290 if isUnifiable(subv) {
291 md.decoded[md.context.add(key).String()] = struct{}{}
292 md.context = append(md.context, key)
293
294 err := md.unify(datum, subv)
295 if err != nil {
296 return err
297 }
298 md.context = md.context[0 : len(md.context)-1]
299 } else if f.name != "" {
300 return md.e("cannot write unexported field %s.%s", rv.Type().String(), f.name)
301 }
302 }
303 }
304 return nil
305 }
306
307 func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
308 keyType := rv.Type().Key().Kind()
309 if keyType != reflect.String && keyType != reflect.Interface {
310 return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)",
311 keyType, rv.Type())
312 }
313
314 tmap, ok := mapping.(map[string]interface{})
315 if !ok {
316 if tmap == nil {
317 return nil
318 }
319 return md.badtype("map", mapping)
320 }
321 if rv.IsNil() {
322 rv.Set(reflect.MakeMap(rv.Type()))
323 }
324 for k, v := range tmap {
325 md.decoded[md.context.add(k).String()] = struct{}{}
326 md.context = append(md.context, k)
327
328 rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
329
330 err := md.unify(v, indirect(rvval))
331 if err != nil {
332 return err
333 }
334 md.context = md.context[0 : len(md.context)-1]
335
336 rvkey := indirect(reflect.New(rv.Type().Key()))
337
338 switch keyType {
339 case reflect.Interface:
340 rvkey.Set(reflect.ValueOf(k))
341 case reflect.String:
342 rvkey.SetString(k)
343 }
344
345 rv.SetMapIndex(rvkey, rvval)
346 }
347 return nil
348 }
349
350 func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
351 datav := reflect.ValueOf(data)
352 if datav.Kind() != reflect.Slice {
353 if !datav.IsValid() {
354 return nil
355 }
356 return md.badtype("slice", data)
357 }
358 if l := datav.Len(); l != rv.Len() {
359 return md.e("expected array length %d; got TOML array of length %d", rv.Len(), l)
360 }
361 return md.unifySliceArray(datav, rv)
362 }
363
364 func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
365 datav := reflect.ValueOf(data)
366 if datav.Kind() != reflect.Slice {
367 if !datav.IsValid() {
368 return nil
369 }
370 return md.badtype("slice", data)
371 }
372 n := datav.Len()
373 if rv.IsNil() || rv.Cap() < n {
374 rv.Set(reflect.MakeSlice(rv.Type(), n, n))
375 }
376 rv.SetLen(n)
377 return md.unifySliceArray(datav, rv)
378 }
379
380 func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
381 l := data.Len()
382 for i := 0; i < l; i++ {
383 err := md.unify(data.Index(i).Interface(), indirect(rv.Index(i)))
384 if err != nil {
385 return err
386 }
387 }
388 return nil
389 }
390
391 func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
392 _, ok := rv.Interface().(json.Number)
393 if ok {
394 if i, ok := data.(int64); ok {
395 rv.SetString(strconv.FormatInt(i, 10))
396 } else if f, ok := data.(float64); ok {
397 rv.SetString(strconv.FormatFloat(f, 'f', -1, 64))
398 } else {
399 return md.badtype("string", data)
400 }
401 return nil
402 }
403
404 if s, ok := data.(string); ok {
405 rv.SetString(s)
406 return nil
407 }
408 return md.badtype("string", data)
409 }
410
411 func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
412 rvk := rv.Kind()
413
414 if num, ok := data.(float64); ok {
415 switch rvk {
416 case reflect.Float32:
417 if num < -math.MaxFloat32 || num > math.MaxFloat32 {
418 return md.parseErr(errParseRange{i: num, size: rvk.String()})
419 }
420 fallthrough
421 case reflect.Float64:
422 rv.SetFloat(num)
423 default:
424 panic("bug")
425 }
426 return nil
427 }
428
429 if num, ok := data.(int64); ok {
430 if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) ||
431 (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) {
432 return md.parseErr(errParseRange{i: num, size: rvk.String()})
433 }
434 rv.SetFloat(float64(num))
435 return nil
436 }
437
438 return md.badtype("float", data)
439 }
440
441 func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
442 _, ok := rv.Interface().(time.Duration)
443 if ok {
444
445
446 if s, ok := data.(string); ok {
447 dur, err := time.ParseDuration(s)
448 if err != nil {
449 return md.parseErr(errParseDuration{s})
450 }
451 rv.SetInt(int64(dur))
452 return nil
453 }
454 }
455
456 num, ok := data.(int64)
457 if !ok {
458 return md.badtype("integer", data)
459 }
460
461 rvk := rv.Kind()
462 switch {
463 case rvk >= reflect.Int && rvk <= reflect.Int64:
464 if (rvk == reflect.Int8 && (num < math.MinInt8 || num > math.MaxInt8)) ||
465 (rvk == reflect.Int16 && (num < math.MinInt16 || num > math.MaxInt16)) ||
466 (rvk == reflect.Int32 && (num < math.MinInt32 || num > math.MaxInt32)) {
467 return md.parseErr(errParseRange{i: num, size: rvk.String()})
468 }
469 rv.SetInt(num)
470 case rvk >= reflect.Uint && rvk <= reflect.Uint64:
471 unum := uint64(num)
472 if rvk == reflect.Uint8 && (num < 0 || unum > math.MaxUint8) ||
473 rvk == reflect.Uint16 && (num < 0 || unum > math.MaxUint16) ||
474 rvk == reflect.Uint32 && (num < 0 || unum > math.MaxUint32) {
475 return md.parseErr(errParseRange{i: num, size: rvk.String()})
476 }
477 rv.SetUint(unum)
478 default:
479 panic("unreachable")
480 }
481 return nil
482 }
483
484 func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
485 if b, ok := data.(bool); ok {
486 rv.SetBool(b)
487 return nil
488 }
489 return md.badtype("boolean", data)
490 }
491
492 func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
493 rv.Set(reflect.ValueOf(data))
494 return nil
495 }
496
497 func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error {
498 var s string
499 switch sdata := data.(type) {
500 case Marshaler:
501 text, err := sdata.MarshalTOML()
502 if err != nil {
503 return err
504 }
505 s = string(text)
506 case encoding.TextMarshaler:
507 text, err := sdata.MarshalText()
508 if err != nil {
509 return err
510 }
511 s = string(text)
512 case fmt.Stringer:
513 s = sdata.String()
514 case string:
515 s = sdata
516 case bool:
517 s = fmt.Sprintf("%v", sdata)
518 case int64:
519 s = fmt.Sprintf("%d", sdata)
520 case float64:
521 s = fmt.Sprintf("%f", sdata)
522 default:
523 return md.badtype("primitive (string-like)", data)
524 }
525 if err := v.UnmarshalText([]byte(s)); err != nil {
526 return err
527 }
528 return nil
529 }
530
531 func (md *MetaData) badtype(dst string, data interface{}) error {
532 return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst)
533 }
534
535 func (md *MetaData) parseErr(err error) error {
536 k := md.context.String()
537 return ParseError{
538 LastKey: k,
539 Position: md.keyInfo[k].pos,
540 Line: md.keyInfo[k].pos.Line,
541 err: err,
542 input: string(md.data),
543 }
544 }
545
546 func (md *MetaData) e(format string, args ...interface{}) error {
547 f := "toml: "
548 if len(md.context) > 0 {
549 f = fmt.Sprintf("toml: (last key %q): ", md.context)
550 p := md.keyInfo[md.context.String()].pos
551 if p.Line > 0 {
552 f = fmt.Sprintf("toml: line %d (last key %q): ", p.Line, md.context)
553 }
554 }
555 return fmt.Errorf(f+format, args...)
556 }
557
558
559 func rvalue(v interface{}) reflect.Value {
560 return indirect(reflect.ValueOf(v))
561 }
562
563
564
565
566
567
568
569
570 func indirect(v reflect.Value) reflect.Value {
571 if v.Kind() != reflect.Ptr {
572 if v.CanSet() {
573 pv := v.Addr()
574 pvi := pv.Interface()
575 if _, ok := pvi.(encoding.TextUnmarshaler); ok {
576 return pv
577 }
578 if _, ok := pvi.(Unmarshaler); ok {
579 return pv
580 }
581 }
582 return v
583 }
584 if v.IsNil() {
585 v.Set(reflect.New(v.Type().Elem()))
586 }
587 return indirect(reflect.Indirect(v))
588 }
589
590 func isUnifiable(rv reflect.Value) bool {
591 if rv.CanSet() {
592 return true
593 }
594 rvi := rv.Interface()
595 if _, ok := rvi.(encoding.TextUnmarshaler); ok {
596 return true
597 }
598 if _, ok := rvi.(Unmarshaler); ok {
599 return true
600 }
601 return false
602 }
603
View as plain text