1package toml
2
3import (
4	"bytes"
5	"errors"
6	"fmt"
7	"io"
8	"reflect"
9	"sort"
10	"strconv"
11	"strings"
12	"time"
13)
14
15const (
16	tagFieldName    = "toml"
17	tagFieldComment = "comment"
18	tagCommented    = "commented"
19	tagMultiline    = "multiline"
20	tagDefault      = "default"
21)
22
23type tomlOpts struct {
24	name         string
25	comment      string
26	commented    bool
27	multiline    bool
28	include      bool
29	omitempty    bool
30	defaultValue string
31}
32
33type encOpts struct {
34	quoteMapKeys            bool
35	arraysOneElementPerLine bool
36}
37
38var encOptsDefaults = encOpts{
39	quoteMapKeys: false,
40}
41
42type annotation struct {
43	tag          string
44	comment      string
45	commented    string
46	multiline    string
47	defaultValue string
48}
49
50var annotationDefault = annotation{
51	tag:          tagFieldName,
52	comment:      tagFieldComment,
53	commented:    tagCommented,
54	multiline:    tagMultiline,
55	defaultValue: tagDefault,
56}
57
58type marshalOrder int
59
60// Orders the Encoder can write the fields to the output stream.
61const (
62	// Sort fields alphabetically.
63	OrderAlphabetical marshalOrder = iota + 1
64	// Preserve the order the fields are encountered. For example, the order of fields in
65	// a struct.
66	OrderPreserve
67)
68
69var timeType = reflect.TypeOf(time.Time{})
70var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
71
72// Check if the given marshal type maps to a Tree primitive
73func isPrimitive(mtype reflect.Type) bool {
74	switch mtype.Kind() {
75	case reflect.Ptr:
76		return isPrimitive(mtype.Elem())
77	case reflect.Bool:
78		return true
79	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
80		return true
81	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
82		return true
83	case reflect.Float32, reflect.Float64:
84		return true
85	case reflect.String:
86		return true
87	case reflect.Struct:
88		return mtype == timeType || isCustomMarshaler(mtype)
89	default:
90		return false
91	}
92}
93
94// Check if the given marshal type maps to a Tree slice
95func isTreeSlice(mtype reflect.Type) bool {
96	switch mtype.Kind() {
97	case reflect.Slice:
98		return !isOtherSlice(mtype)
99	default:
100		return false
101	}
102}
103
104// Check if the given marshal type maps to a non-Tree slice
105func isOtherSlice(mtype reflect.Type) bool {
106	switch mtype.Kind() {
107	case reflect.Ptr:
108		return isOtherSlice(mtype.Elem())
109	case reflect.Slice:
110		return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem())
111	default:
112		return false
113	}
114}
115
116// Check if the given marshal type maps to a Tree
117func isTree(mtype reflect.Type) bool {
118	switch mtype.Kind() {
119	case reflect.Map:
120		return true
121	case reflect.Struct:
122		return !isPrimitive(mtype)
123	default:
124		return false
125	}
126}
127
128func isCustomMarshaler(mtype reflect.Type) bool {
129	return mtype.Implements(marshalerType)
130}
131
132func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
133	return mval.Interface().(Marshaler).MarshalTOML()
134}
135
136// Marshaler is the interface implemented by types that
137// can marshal themselves into valid TOML.
138type Marshaler interface {
139	MarshalTOML() ([]byte, error)
140}
141
142/*
143Marshal returns the TOML encoding of v.  Behavior is similar to the Go json
144encoder, except that there is no concept of a Marshaler interface or MarshalTOML
145function for sub-structs, and currently only definite types can be marshaled
146(i.e. no `interface{}`).
147
148The following struct annotations are supported:
149
150  toml:"Field"      Overrides the field's name to output.
151  omitempty         When set, empty values and groups are not emitted.
152  comment:"comment" Emits a # comment on the same line. This supports new lines.
153  commented:"true"  Emits the value as commented.
154
155Note that pointers are automatically assigned the "omitempty" option, as TOML
156explicitly does not handle null values (saying instead the label should be
157dropped).
158
159Tree structural types and corresponding marshal types:
160
161  *Tree                            (*)struct, (*)map[string]interface{}
162  []*Tree                          (*)[](*)struct, (*)[](*)map[string]interface{}
163  []interface{} (as interface{})   (*)[]primitive, (*)[]([]interface{})
164  interface{}                      (*)primitive
165
166Tree primitive types and corresponding marshal types:
167
168  uint64     uint, uint8-uint64, pointers to same
169  int64      int, int8-uint64, pointers to same
170  float64    float32, float64, pointers to same
171  string     string, pointers to same
172  bool       bool, pointers to same
173  time.Time  time.Time{}, pointers to same
174
175For additional flexibility, use the Encoder API.
176*/
177func Marshal(v interface{}) ([]byte, error) {
178	return NewEncoder(nil).marshal(v)
179}
180
181// Encoder writes TOML values to an output stream.
182type Encoder struct {
183	w io.Writer
184	encOpts
185	annotation
186	line  int
187	col   int
188	order marshalOrder
189}
190
191// NewEncoder returns a new encoder that writes to w.
192func NewEncoder(w io.Writer) *Encoder {
193	return &Encoder{
194		w:          w,
195		encOpts:    encOptsDefaults,
196		annotation: annotationDefault,
197		line:       0,
198		col:        1,
199		order:      OrderAlphabetical,
200	}
201}
202
203// Encode writes the TOML encoding of v to the stream.
204//
205// See the documentation for Marshal for details.
206func (e *Encoder) Encode(v interface{}) error {
207	b, err := e.marshal(v)
208	if err != nil {
209		return err
210	}
211	if _, err := e.w.Write(b); err != nil {
212		return err
213	}
214	return nil
215}
216
217// QuoteMapKeys sets up the encoder to encode
218// maps with string type keys with quoted TOML keys.
219//
220// This relieves the character limitations on map keys.
221func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
222	e.quoteMapKeys = v
223	return e
224}
225
226// ArraysWithOneElementPerLine sets up the encoder to encode arrays
227// with more than one element on multiple lines instead of one.
228//
229// For example:
230//
231//   A = [1,2,3]
232//
233// Becomes
234//
235//   A = [
236//     1,
237//     2,
238//     3,
239//   ]
240func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
241	e.arraysOneElementPerLine = v
242	return e
243}
244
245// Order allows to change in which order fields will be written to the output stream.
246func (e *Encoder) Order(ord marshalOrder) *Encoder {
247	e.order = ord
248	return e
249}
250
251// SetTagName allows changing default tag "toml"
252func (e *Encoder) SetTagName(v string) *Encoder {
253	e.tag = v
254	return e
255}
256
257// SetTagComment allows changing default tag "comment"
258func (e *Encoder) SetTagComment(v string) *Encoder {
259	e.comment = v
260	return e
261}
262
263// SetTagCommented allows changing default tag "commented"
264func (e *Encoder) SetTagCommented(v string) *Encoder {
265	e.commented = v
266	return e
267}
268
269// SetTagMultiline allows changing default tag "multiline"
270func (e *Encoder) SetTagMultiline(v string) *Encoder {
271	e.multiline = v
272	return e
273}
274
275func (e *Encoder) marshal(v interface{}) ([]byte, error) {
276	mtype := reflect.TypeOf(v)
277
278	switch mtype.Kind() {
279	case reflect.Struct, reflect.Map:
280	case reflect.Ptr:
281		if mtype.Elem().Kind() != reflect.Struct {
282			return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML")
283		}
284	default:
285		return []byte{}, errors.New("Only a struct or map can be marshaled to TOML")
286	}
287
288	sval := reflect.ValueOf(v)
289	if isCustomMarshaler(mtype) {
290		return callCustomMarshaler(sval)
291	}
292	t, err := e.valueToTree(mtype, sval)
293	if err != nil {
294		return []byte{}, err
295	}
296
297	var buf bytes.Buffer
298	_, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order)
299
300	return buf.Bytes(), err
301}
302
303// Create next tree with a position based on Encoder.line
304func (e *Encoder) nextTree() *Tree {
305	return newTreeWithPosition(Position{Line: e.line, Col: 1})
306}
307
308// Convert given marshal struct or map value to toml tree
309func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
310	if mtype.Kind() == reflect.Ptr {
311		return e.valueToTree(mtype.Elem(), mval.Elem())
312	}
313	tval := e.nextTree()
314	switch mtype.Kind() {
315	case reflect.Struct:
316		for i := 0; i < mtype.NumField(); i++ {
317			mtypef, mvalf := mtype.Field(i), mval.Field(i)
318			opts := tomlOptions(mtypef, e.annotation)
319			if opts.include && (!opts.omitempty || !isZero(mvalf)) {
320				val, err := e.valueToToml(mtypef.Type, mvalf)
321				if err != nil {
322					return nil, err
323				}
324
325				tval.SetWithOptions(opts.name, SetOptions{
326					Comment:   opts.comment,
327					Commented: opts.commented,
328					Multiline: opts.multiline,
329				}, val)
330			}
331		}
332	case reflect.Map:
333		keys := mval.MapKeys()
334		if e.order == OrderPreserve && len(keys) > 0 {
335			// Sorting []reflect.Value is not straight forward.
336			//
337			// OrderPreserve will support deterministic results when string is used
338			// as the key to maps.
339			typ := keys[0].Type()
340			kind := keys[0].Kind()
341			if kind == reflect.String {
342				ikeys := make([]string, len(keys))
343				for i := range keys {
344					ikeys[i] = keys[i].Interface().(string)
345				}
346				sort.Strings(ikeys)
347				for i := range ikeys {
348					keys[i] = reflect.ValueOf(ikeys[i]).Convert(typ)
349				}
350			}
351		}
352		for _, key := range keys {
353			mvalf := mval.MapIndex(key)
354			val, err := e.valueToToml(mtype.Elem(), mvalf)
355			if err != nil {
356				return nil, err
357			}
358			if e.quoteMapKeys {
359				keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine)
360				if err != nil {
361					return nil, err
362				}
363				tval.SetPath([]string{keyStr}, val)
364			} else {
365				tval.Set(key.String(), val)
366			}
367		}
368	}
369	return tval, nil
370}
371
372// Convert given marshal slice to slice of Toml trees
373func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
374	tval := make([]*Tree, mval.Len(), mval.Len())
375	for i := 0; i < mval.Len(); i++ {
376		val, err := e.valueToTree(mtype.Elem(), mval.Index(i))
377		if err != nil {
378			return nil, err
379		}
380		tval[i] = val
381	}
382	return tval, nil
383}
384
385// Convert given marshal slice to slice of toml values
386func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
387	tval := make([]interface{}, mval.Len(), mval.Len())
388	for i := 0; i < mval.Len(); i++ {
389		val, err := e.valueToToml(mtype.Elem(), mval.Index(i))
390		if err != nil {
391			return nil, err
392		}
393		tval[i] = val
394	}
395	return tval, nil
396}
397
398// Convert given marshal value to toml value
399func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
400	e.line++
401	if mtype.Kind() == reflect.Ptr {
402		return e.valueToToml(mtype.Elem(), mval.Elem())
403	}
404	switch {
405	case isCustomMarshaler(mtype):
406		return callCustomMarshaler(mval)
407	case isTree(mtype):
408		return e.valueToTree(mtype, mval)
409	case isTreeSlice(mtype):
410		return e.valueToTreeSlice(mtype, mval)
411	case isOtherSlice(mtype):
412		return e.valueToOtherSlice(mtype, mval)
413	default:
414		switch mtype.Kind() {
415		case reflect.Bool:
416			return mval.Bool(), nil
417		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
418			if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) {
419				return fmt.Sprint(mval), nil
420			}
421			return mval.Int(), nil
422		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
423			return mval.Uint(), nil
424		case reflect.Float32, reflect.Float64:
425			return mval.Float(), nil
426		case reflect.String:
427			return mval.String(), nil
428		case reflect.Struct:
429			return mval.Interface().(time.Time), nil
430		default:
431			return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
432		}
433	}
434}
435
436// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
437// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
438// sub-structs, and only definite types can be unmarshaled.
439func (t *Tree) Unmarshal(v interface{}) error {
440	d := Decoder{tval: t, tagName: tagFieldName}
441	return d.unmarshal(v)
442}
443
444// Marshal returns the TOML encoding of Tree.
445// See Marshal() documentation for types mapping table.
446func (t *Tree) Marshal() ([]byte, error) {
447	var buf bytes.Buffer
448	err := NewEncoder(&buf).Encode(t)
449	return buf.Bytes(), err
450}
451
452// Unmarshal parses the TOML-encoded data and stores the result in the value
453// pointed to by v. Behavior is similar to the Go json encoder, except that there
454// is no concept of an Unmarshaler interface or UnmarshalTOML function for
455// sub-structs, and currently only definite types can be unmarshaled to (i.e. no
456// `interface{}`).
457//
458// The following struct annotations are supported:
459//
460//   toml:"Field" Overrides the field's name to map to.
461//   default:"foo" Provides a default value.
462//
463// For default values, only fields of the following types are supported:
464//   * string
465//   * bool
466//   * int
467//   * int64
468//   * float64
469//
470// See Marshal() documentation for types mapping table.
471func Unmarshal(data []byte, v interface{}) error {
472	t, err := LoadReader(bytes.NewReader(data))
473	if err != nil {
474		return err
475	}
476	return t.Unmarshal(v)
477}
478
479// Decoder reads and decodes TOML values from an input stream.
480type Decoder struct {
481	r    io.Reader
482	tval *Tree
483	encOpts
484	tagName string
485}
486
487// NewDecoder returns a new decoder that reads from r.
488func NewDecoder(r io.Reader) *Decoder {
489	return &Decoder{
490		r:       r,
491		encOpts: encOptsDefaults,
492		tagName: tagFieldName,
493	}
494}
495
496// Decode reads a TOML-encoded value from it's input
497// and unmarshals it in the value pointed at by v.
498//
499// See the documentation for Marshal for details.
500func (d *Decoder) Decode(v interface{}) error {
501	var err error
502	d.tval, err = LoadReader(d.r)
503	if err != nil {
504		return err
505	}
506	return d.unmarshal(v)
507}
508
509// SetTagName allows changing default tag "toml"
510func (d *Decoder) SetTagName(v string) *Decoder {
511	d.tagName = v
512	return d
513}
514
515func (d *Decoder) unmarshal(v interface{}) error {
516	mtype := reflect.TypeOf(v)
517	if mtype.Kind() != reflect.Ptr {
518		return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
519	}
520
521	elem := mtype.Elem()
522
523	switch elem.Kind() {
524	case reflect.Struct, reflect.Map:
525	default:
526		return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
527	}
528
529	sval, err := d.valueFromTree(elem, d.tval)
530	if err != nil {
531		return err
532	}
533	reflect.ValueOf(v).Elem().Set(sval)
534	return nil
535}
536
537// Convert toml tree to marshal struct or map, using marshal type
538func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
539	if mtype.Kind() == reflect.Ptr {
540		return d.unwrapPointer(mtype, tval)
541	}
542	var mval reflect.Value
543	switch mtype.Kind() {
544	case reflect.Struct:
545		mval = reflect.New(mtype).Elem()
546		for i := 0; i < mtype.NumField(); i++ {
547			mtypef := mtype.Field(i)
548			an := annotation{tag: d.tagName}
549			opts := tomlOptions(mtypef, an)
550			if opts.include {
551				baseKey := opts.name
552				keysToTry := []string{
553					baseKey,
554					strings.ToLower(baseKey),
555					strings.ToTitle(baseKey),
556					strings.ToLower(string(baseKey[0])) + baseKey[1:],
557				}
558
559				found := false
560				for _, key := range keysToTry {
561					exists := tval.Has(key)
562					if !exists {
563						continue
564					}
565					val := tval.Get(key)
566					mvalf, err := d.valueFromToml(mtypef.Type, val)
567					if err != nil {
568						return mval, formatError(err, tval.GetPosition(key))
569					}
570					mval.Field(i).Set(mvalf)
571					found = true
572					break
573				}
574
575				if !found && opts.defaultValue != "" {
576					mvalf := mval.Field(i)
577					var val interface{}
578					var err error
579					switch mvalf.Kind() {
580					case reflect.Bool:
581						val, err = strconv.ParseBool(opts.defaultValue)
582						if err != nil {
583							return mval.Field(i), err
584						}
585					case reflect.Int:
586						val, err = strconv.Atoi(opts.defaultValue)
587						if err != nil {
588							return mval.Field(i), err
589						}
590					case reflect.String:
591						val = opts.defaultValue
592					case reflect.Int64:
593						val, err = strconv.ParseInt(opts.defaultValue, 10, 64)
594						if err != nil {
595							return mval.Field(i), err
596						}
597					case reflect.Float64:
598						val, err = strconv.ParseFloat(opts.defaultValue, 64)
599						if err != nil {
600							return mval.Field(i), err
601						}
602					default:
603						return mval.Field(i), fmt.Errorf("unsuported field type for default option")
604					}
605					mval.Field(i).Set(reflect.ValueOf(val))
606				}
607			}
608		}
609	case reflect.Map:
610		mval = reflect.MakeMap(mtype)
611		for _, key := range tval.Keys() {
612			// TODO: path splits key
613			val := tval.GetPath([]string{key})
614			mvalf, err := d.valueFromToml(mtype.Elem(), val)
615			if err != nil {
616				return mval, formatError(err, tval.GetPosition(key))
617			}
618			mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf)
619		}
620	}
621	return mval, nil
622}
623
624// Convert toml value to marshal struct/map slice, using marshal type
625func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
626	mval := reflect.MakeSlice(mtype, len(tval), len(tval))
627	for i := 0; i < len(tval); i++ {
628		val, err := d.valueFromTree(mtype.Elem(), tval[i])
629		if err != nil {
630			return mval, err
631		}
632		mval.Index(i).Set(val)
633	}
634	return mval, nil
635}
636
637// Convert toml value to marshal primitive slice, using marshal type
638func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
639	mval := reflect.MakeSlice(mtype, len(tval), len(tval))
640	for i := 0; i < len(tval); i++ {
641		val, err := d.valueFromToml(mtype.Elem(), tval[i])
642		if err != nil {
643			return mval, err
644		}
645		mval.Index(i).Set(val)
646	}
647	return mval, nil
648}
649
650// Convert toml value to marshal value, using marshal type
651func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
652	if mtype.Kind() == reflect.Ptr {
653		return d.unwrapPointer(mtype, tval)
654	}
655
656	switch t := tval.(type) {
657	case *Tree:
658		if isTree(mtype) {
659			return d.valueFromTree(mtype, t)
660		}
661		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
662	case []*Tree:
663		if isTreeSlice(mtype) {
664			return d.valueFromTreeSlice(mtype, t)
665		}
666		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
667	case []interface{}:
668		if isOtherSlice(mtype) {
669			return d.valueFromOtherSlice(mtype, t)
670		}
671		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
672	default:
673		switch mtype.Kind() {
674		case reflect.Bool, reflect.Struct:
675			val := reflect.ValueOf(tval)
676			// if this passes for when mtype is reflect.Struct, tval is a time.Time
677			if !val.Type().ConvertibleTo(mtype) {
678				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
679			}
680
681			return val.Convert(mtype), nil
682		case reflect.String:
683			val := reflect.ValueOf(tval)
684			// stupidly, int64 is convertible to string. So special case this.
685			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 {
686				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
687			}
688
689			return val.Convert(mtype), nil
690		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
691			val := reflect.ValueOf(tval)
692			if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String {
693				d, err := time.ParseDuration(val.String())
694				if err != nil {
695					return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err)
696				}
697				return reflect.ValueOf(d), nil
698			}
699			if !val.Type().ConvertibleTo(mtype) {
700				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
701			}
702			if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(mtype).Int()) {
703				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
704			}
705
706			return val.Convert(mtype), nil
707		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
708			val := reflect.ValueOf(tval)
709			if !val.Type().ConvertibleTo(mtype) {
710				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
711			}
712
713			if val.Convert(reflect.TypeOf(int(1))).Int() < 0 {
714				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
715			}
716			if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Convert(mtype).Uint())) {
717				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
718			}
719
720			return val.Convert(mtype), nil
721		case reflect.Float32, reflect.Float64:
722			val := reflect.ValueOf(tval)
723			if !val.Type().ConvertibleTo(mtype) {
724				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
725			}
726			if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(mtype).Float()) {
727				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
728			}
729
730			return val.Convert(mtype), nil
731		default:
732			return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
733		}
734	}
735}
736
737func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
738	val, err := d.valueFromToml(mtype.Elem(), tval)
739	if err != nil {
740		return reflect.ValueOf(nil), err
741	}
742	mval := reflect.New(mtype.Elem())
743	mval.Elem().Set(val)
744	return mval, nil
745}
746
747func tomlOptions(vf reflect.StructField, an annotation) tomlOpts {
748	tag := vf.Tag.Get(an.tag)
749	parse := strings.Split(tag, ",")
750	var comment string
751	if c := vf.Tag.Get(an.comment); c != "" {
752		comment = c
753	}
754	commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented))
755	multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline))
756	defaultValue := vf.Tag.Get(tagDefault)
757	result := tomlOpts{
758		name:         vf.Name,
759		comment:      comment,
760		commented:    commented,
761		multiline:    multiline,
762		include:      true,
763		omitempty:    false,
764		defaultValue: defaultValue,
765	}
766	if parse[0] != "" {
767		if parse[0] == "-" && len(parse) == 1 {
768			result.include = false
769		} else {
770			result.name = strings.Trim(parse[0], " ")
771		}
772	}
773	if vf.PkgPath != "" {
774		result.include = false
775	}
776	if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
777		result.omitempty = true
778	}
779	if vf.Type.Kind() == reflect.Ptr {
780		result.omitempty = true
781	}
782	return result
783}
784
785func isZero(val reflect.Value) bool {
786	switch val.Type().Kind() {
787	case reflect.Map:
788		fallthrough
789	case reflect.Array:
790		fallthrough
791	case reflect.Slice:
792		return val.Len() == 0
793	default:
794		return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
795	}
796}
797
798func formatError(err error, pos Position) error {
799	if err.Error()[0] == '(' { // Error already contains position information
800		return err
801	}
802	return fmt.Errorf("%s: %s", pos, err)
803}
804