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