1package toml
2
3import (
4	"bytes"
5	"encoding"
6	"errors"
7	"fmt"
8	"io"
9	"reflect"
10	"sort"
11	"strconv"
12	"strings"
13	"time"
14)
15
16const (
17	tagFieldName    = "toml"
18	tagFieldComment = "comment"
19	tagCommented    = "commented"
20	tagMultiline    = "multiline"
21	tagDefault      = "default"
22)
23
24type tomlOpts struct {
25	name         string
26	nameFromTag  bool
27	comment      string
28	commented    bool
29	multiline    bool
30	include      bool
31	omitempty    bool
32	defaultValue string
33}
34
35type encOpts struct {
36	quoteMapKeys            bool
37	arraysOneElementPerLine bool
38}
39
40var encOptsDefaults = encOpts{
41	quoteMapKeys: false,
42}
43
44type annotation struct {
45	tag          string
46	comment      string
47	commented    string
48	multiline    string
49	defaultValue string
50}
51
52var annotationDefault = annotation{
53	tag:          tagFieldName,
54	comment:      tagFieldComment,
55	commented:    tagCommented,
56	multiline:    tagMultiline,
57	defaultValue: tagDefault,
58}
59
60type marshalOrder int
61
62// Orders the Encoder can write the fields to the output stream.
63const (
64	// Sort fields alphabetically.
65	OrderAlphabetical marshalOrder = iota + 1
66	// Preserve the order the fields are encountered. For example, the order of fields in
67	// a struct.
68	OrderPreserve
69)
70
71var timeType = reflect.TypeOf(time.Time{})
72var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
73var unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem()
74var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
75var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
76var localDateType = reflect.TypeOf(LocalDate{})
77var localTimeType = reflect.TypeOf(LocalTime{})
78var localDateTimeType = reflect.TypeOf(LocalDateTime{})
79var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
80
81// Check if the given marshal type maps to a Tree primitive
82func isPrimitive(mtype reflect.Type) bool {
83	switch mtype.Kind() {
84	case reflect.Ptr:
85		return isPrimitive(mtype.Elem())
86	case reflect.Bool:
87		return true
88	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
89		return true
90	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
91		return true
92	case reflect.Float32, reflect.Float64:
93		return true
94	case reflect.String:
95		return true
96	case reflect.Struct:
97		return isTimeType(mtype)
98	default:
99		return false
100	}
101}
102
103func isTimeType(mtype reflect.Type) bool {
104	return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType
105}
106
107// Check if the given marshal type maps to a Tree slice or array
108func isTreeSequence(mtype reflect.Type) bool {
109	switch mtype.Kind() {
110	case reflect.Ptr:
111		return isTreeSequence(mtype.Elem())
112	case reflect.Slice, reflect.Array:
113		return isTree(mtype.Elem())
114	default:
115		return false
116	}
117}
118
119// Check if the given marshal type maps to a slice or array of a custom marshaler type
120func isCustomMarshalerSequence(mtype reflect.Type) bool {
121	switch mtype.Kind() {
122	case reflect.Ptr:
123		return isCustomMarshalerSequence(mtype.Elem())
124	case reflect.Slice, reflect.Array:
125		return isCustomMarshaler(mtype.Elem()) || isCustomMarshaler(reflect.New(mtype.Elem()).Type())
126	default:
127		return false
128	}
129}
130
131// Check if the given marshal type maps to a slice or array of a text marshaler type
132func isTextMarshalerSequence(mtype reflect.Type) bool {
133	switch mtype.Kind() {
134	case reflect.Ptr:
135		return isTextMarshalerSequence(mtype.Elem())
136	case reflect.Slice, reflect.Array:
137		return isTextMarshaler(mtype.Elem()) || isTextMarshaler(reflect.New(mtype.Elem()).Type())
138	default:
139		return false
140	}
141}
142
143// Check if the given marshal type maps to a non-Tree slice or array
144func isOtherSequence(mtype reflect.Type) bool {
145	switch mtype.Kind() {
146	case reflect.Ptr:
147		return isOtherSequence(mtype.Elem())
148	case reflect.Slice, reflect.Array:
149		return !isTreeSequence(mtype)
150	default:
151		return false
152	}
153}
154
155// Check if the given marshal type maps to a Tree
156func isTree(mtype reflect.Type) bool {
157	switch mtype.Kind() {
158	case reflect.Ptr:
159		return isTree(mtype.Elem())
160	case reflect.Map:
161		return true
162	case reflect.Struct:
163		return !isPrimitive(mtype)
164	default:
165		return false
166	}
167}
168
169func isCustomMarshaler(mtype reflect.Type) bool {
170	return mtype.Implements(marshalerType)
171}
172
173func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
174	return mval.Interface().(Marshaler).MarshalTOML()
175}
176
177func isTextMarshaler(mtype reflect.Type) bool {
178	return mtype.Implements(textMarshalerType) && !isTimeType(mtype)
179}
180
181func callTextMarshaler(mval reflect.Value) ([]byte, error) {
182	return mval.Interface().(encoding.TextMarshaler).MarshalText()
183}
184
185func isCustomUnmarshaler(mtype reflect.Type) bool {
186	return mtype.Implements(unmarshalerType)
187}
188
189func callCustomUnmarshaler(mval reflect.Value, tval interface{}) error {
190	return mval.Interface().(Unmarshaler).UnmarshalTOML(tval)
191}
192
193func isTextUnmarshaler(mtype reflect.Type) bool {
194	return mtype.Implements(textUnmarshalerType)
195}
196
197func callTextUnmarshaler(mval reflect.Value, text []byte) error {
198	return mval.Interface().(encoding.TextUnmarshaler).UnmarshalText(text)
199}
200
201// Marshaler is the interface implemented by types that
202// can marshal themselves into valid TOML.
203type Marshaler interface {
204	MarshalTOML() ([]byte, error)
205}
206
207// Unmarshaler is the interface implemented by types that
208// can unmarshal a TOML description of themselves.
209type Unmarshaler interface {
210	UnmarshalTOML(interface{}) error
211}
212
213/*
214Marshal returns the TOML encoding of v.  Behavior is similar to the Go json
215encoder, except that there is no concept of a Marshaler interface or MarshalTOML
216function for sub-structs, and currently only definite types can be marshaled
217(i.e. no `interface{}`).
218
219The following struct annotations are supported:
220
221  toml:"Field"      Overrides the field's name to output.
222  omitempty         When set, empty values and groups are not emitted.
223  comment:"comment" Emits a # comment on the same line. This supports new lines.
224  commented:"true"  Emits the value as commented.
225
226Note that pointers are automatically assigned the "omitempty" option, as TOML
227explicitly does not handle null values (saying instead the label should be
228dropped).
229
230Tree structural types and corresponding marshal types:
231
232  *Tree                            (*)struct, (*)map[string]interface{}
233  []*Tree                          (*)[](*)struct, (*)[](*)map[string]interface{}
234  []interface{} (as interface{})   (*)[]primitive, (*)[]([]interface{})
235  interface{}                      (*)primitive
236
237Tree primitive types and corresponding marshal types:
238
239  uint64     uint, uint8-uint64, pointers to same
240  int64      int, int8-uint64, pointers to same
241  float64    float32, float64, pointers to same
242  string     string, pointers to same
243  bool       bool, pointers to same
244  time.LocalTime  time.LocalTime{}, pointers to same
245
246For additional flexibility, use the Encoder API.
247*/
248func Marshal(v interface{}) ([]byte, error) {
249	return NewEncoder(nil).marshal(v)
250}
251
252// Encoder writes TOML values to an output stream.
253type Encoder struct {
254	w io.Writer
255	encOpts
256	annotation
257	line        int
258	col         int
259	order       marshalOrder
260	promoteAnon bool
261	indentation string
262}
263
264// NewEncoder returns a new encoder that writes to w.
265func NewEncoder(w io.Writer) *Encoder {
266	return &Encoder{
267		w:           w,
268		encOpts:     encOptsDefaults,
269		annotation:  annotationDefault,
270		line:        0,
271		col:         1,
272		order:       OrderAlphabetical,
273		indentation: "  ",
274	}
275}
276
277// Encode writes the TOML encoding of v to the stream.
278//
279// See the documentation for Marshal for details.
280func (e *Encoder) Encode(v interface{}) error {
281	b, err := e.marshal(v)
282	if err != nil {
283		return err
284	}
285	if _, err := e.w.Write(b); err != nil {
286		return err
287	}
288	return nil
289}
290
291// QuoteMapKeys sets up the encoder to encode
292// maps with string type keys with quoted TOML keys.
293//
294// This relieves the character limitations on map keys.
295func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
296	e.quoteMapKeys = v
297	return e
298}
299
300// ArraysWithOneElementPerLine sets up the encoder to encode arrays
301// with more than one element on multiple lines instead of one.
302//
303// For example:
304//
305//   A = [1,2,3]
306//
307// Becomes
308//
309//   A = [
310//     1,
311//     2,
312//     3,
313//   ]
314func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
315	e.arraysOneElementPerLine = v
316	return e
317}
318
319// Order allows to change in which order fields will be written to the output stream.
320func (e *Encoder) Order(ord marshalOrder) *Encoder {
321	e.order = ord
322	return e
323}
324
325// Indentation allows to change indentation when marshalling.
326func (e *Encoder) Indentation(indent string) *Encoder {
327	e.indentation = indent
328	return e
329}
330
331// SetTagName allows changing default tag "toml"
332func (e *Encoder) SetTagName(v string) *Encoder {
333	e.tag = v
334	return e
335}
336
337// SetTagComment allows changing default tag "comment"
338func (e *Encoder) SetTagComment(v string) *Encoder {
339	e.comment = v
340	return e
341}
342
343// SetTagCommented allows changing default tag "commented"
344func (e *Encoder) SetTagCommented(v string) *Encoder {
345	e.commented = v
346	return e
347}
348
349// SetTagMultiline allows changing default tag "multiline"
350func (e *Encoder) SetTagMultiline(v string) *Encoder {
351	e.multiline = v
352	return e
353}
354
355// PromoteAnonymous allows to change how anonymous struct fields are marshaled.
356// Usually, they are marshaled as if the inner exported fields were fields in
357// the outer struct. However, if an anonymous struct field is given a name in
358// its TOML tag, it is treated like a regular struct field with that name.
359// rather than being anonymous.
360//
361// In case anonymous promotion is enabled, all anonymous structs are promoted
362// and treated like regular struct fields.
363func (e *Encoder) PromoteAnonymous(promote bool) *Encoder {
364	e.promoteAnon = promote
365	return e
366}
367
368func (e *Encoder) marshal(v interface{}) ([]byte, error) {
369	// Check if indentation is valid
370	for _, char := range e.indentation {
371		if !isSpace(char) {
372			return []byte{}, fmt.Errorf("invalid indentation: must only contains space or tab characters")
373		}
374	}
375
376	mtype := reflect.TypeOf(v)
377	if mtype == nil {
378		return []byte{}, errors.New("nil cannot be marshaled to TOML")
379	}
380
381	switch mtype.Kind() {
382	case reflect.Struct, reflect.Map:
383	case reflect.Ptr:
384		if mtype.Elem().Kind() != reflect.Struct {
385			return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML")
386		}
387		if reflect.ValueOf(v).IsNil() {
388			return []byte{}, errors.New("nil pointer cannot be marshaled to TOML")
389		}
390	default:
391		return []byte{}, errors.New("Only a struct or map can be marshaled to TOML")
392	}
393
394	sval := reflect.ValueOf(v)
395	if isCustomMarshaler(mtype) {
396		return callCustomMarshaler(sval)
397	}
398	if isTextMarshaler(mtype) {
399		return callTextMarshaler(sval)
400	}
401	t, err := e.valueToTree(mtype, sval)
402	if err != nil {
403		return []byte{}, err
404	}
405
406	var buf bytes.Buffer
407	_, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order, e.indentation, false)
408
409	return buf.Bytes(), err
410}
411
412// Create next tree with a position based on Encoder.line
413func (e *Encoder) nextTree() *Tree {
414	return newTreeWithPosition(Position{Line: e.line, Col: 1})
415}
416
417// Convert given marshal struct or map value to toml tree
418func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
419	if mtype.Kind() == reflect.Ptr {
420		return e.valueToTree(mtype.Elem(), mval.Elem())
421	}
422	tval := e.nextTree()
423	switch mtype.Kind() {
424	case reflect.Struct:
425		switch mval.Interface().(type) {
426		case Tree:
427			reflect.ValueOf(tval).Elem().Set(mval)
428		default:
429			for i := 0; i < mtype.NumField(); i++ {
430				mtypef, mvalf := mtype.Field(i), mval.Field(i)
431				opts := tomlOptions(mtypef, e.annotation)
432				if opts.include && ((mtypef.Type.Kind() != reflect.Interface && !opts.omitempty) || !isZero(mvalf)) {
433					val, err := e.valueToToml(mtypef.Type, mvalf)
434					if err != nil {
435						return nil, err
436					}
437					if tree, ok := val.(*Tree); ok && mtypef.Anonymous && !opts.nameFromTag && !e.promoteAnon {
438						e.appendTree(tval, tree)
439					} else {
440						val = e.wrapTomlValue(val, tval)
441						tval.SetPathWithOptions([]string{opts.name}, SetOptions{
442							Comment:   opts.comment,
443							Commented: opts.commented,
444							Multiline: opts.multiline,
445						}, val)
446					}
447				}
448			}
449		}
450	case reflect.Map:
451		keys := mval.MapKeys()
452		if e.order == OrderPreserve && len(keys) > 0 {
453			// Sorting []reflect.Value is not straight forward.
454			//
455			// OrderPreserve will support deterministic results when string is used
456			// as the key to maps.
457			typ := keys[0].Type()
458			kind := keys[0].Kind()
459			if kind == reflect.String {
460				ikeys := make([]string, len(keys))
461				for i := range keys {
462					ikeys[i] = keys[i].Interface().(string)
463				}
464				sort.Strings(ikeys)
465				for i := range ikeys {
466					keys[i] = reflect.ValueOf(ikeys[i]).Convert(typ)
467				}
468			}
469		}
470		for _, key := range keys {
471			mvalf := mval.MapIndex(key)
472			if (mtype.Elem().Kind() == reflect.Ptr || mtype.Elem().Kind() == reflect.Interface) && mvalf.IsNil() {
473				continue
474			}
475			val, err := e.valueToToml(mtype.Elem(), mvalf)
476			if err != nil {
477				return nil, err
478			}
479			val = e.wrapTomlValue(val, tval)
480			if e.quoteMapKeys {
481				keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.order, e.arraysOneElementPerLine)
482				if err != nil {
483					return nil, err
484				}
485				tval.SetPath([]string{keyStr}, val)
486			} else {
487				tval.SetPath([]string{key.String()}, val)
488			}
489		}
490	}
491	return tval, nil
492}
493
494// Convert given marshal slice to slice of Toml trees
495func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
496	tval := make([]*Tree, mval.Len(), mval.Len())
497	for i := 0; i < mval.Len(); i++ {
498		val, err := e.valueToTree(mtype.Elem(), mval.Index(i))
499		if err != nil {
500			return nil, err
501		}
502		tval[i] = val
503	}
504	return tval, nil
505}
506
507// Convert given marshal slice to slice of toml values
508func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
509	tval := make([]interface{}, mval.Len(), mval.Len())
510	for i := 0; i < mval.Len(); i++ {
511		val, err := e.valueToToml(mtype.Elem(), mval.Index(i))
512		if err != nil {
513			return nil, err
514		}
515		tval[i] = val
516	}
517	return tval, nil
518}
519
520// Convert given marshal value to toml value
521func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
522	if mtype.Kind() == reflect.Ptr {
523		switch {
524		case isCustomMarshaler(mtype):
525			return callCustomMarshaler(mval)
526		case isTextMarshaler(mtype):
527			b, err := callTextMarshaler(mval)
528			return string(b), err
529		default:
530			return e.valueToToml(mtype.Elem(), mval.Elem())
531		}
532	}
533	if mtype.Kind() == reflect.Interface {
534		return e.valueToToml(mval.Elem().Type(), mval.Elem())
535	}
536	switch {
537	case isCustomMarshaler(mtype):
538		return callCustomMarshaler(mval)
539	case isTextMarshaler(mtype):
540		b, err := callTextMarshaler(mval)
541		return string(b), err
542	case isTree(mtype):
543		return e.valueToTree(mtype, mval)
544	case isOtherSequence(mtype), isCustomMarshalerSequence(mtype), isTextMarshalerSequence(mtype):
545		return e.valueToOtherSlice(mtype, mval)
546	case isTreeSequence(mtype):
547		return e.valueToTreeSlice(mtype, mval)
548	default:
549		switch mtype.Kind() {
550		case reflect.Bool:
551			return mval.Bool(), nil
552		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
553			if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) {
554				return fmt.Sprint(mval), nil
555			}
556			return mval.Int(), nil
557		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
558			return mval.Uint(), nil
559		case reflect.Float32, reflect.Float64:
560			return mval.Float(), nil
561		case reflect.String:
562			return mval.String(), nil
563		case reflect.Struct:
564			return mval.Interface(), nil
565		default:
566			return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
567		}
568	}
569}
570
571func (e *Encoder) appendTree(t, o *Tree) error {
572	for key, value := range o.values {
573		if _, ok := t.values[key]; ok {
574			continue
575		}
576		if tomlValue, ok := value.(*tomlValue); ok {
577			tomlValue.position.Col = t.position.Col
578		}
579		t.values[key] = value
580	}
581	return nil
582}
583
584// Create a toml value with the current line number as the position line
585func (e *Encoder) wrapTomlValue(val interface{}, parent *Tree) interface{} {
586	_, isTree := val.(*Tree)
587	_, isTreeS := val.([]*Tree)
588	if isTree || isTreeS {
589		return val
590	}
591
592	ret := &tomlValue{
593		value: val,
594		position: Position{
595			e.line,
596			parent.position.Col,
597		},
598	}
599	e.line++
600	return ret
601}
602
603// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
604// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
605// sub-structs, and only definite types can be unmarshaled.
606func (t *Tree) Unmarshal(v interface{}) error {
607	d := Decoder{tval: t, tagName: tagFieldName}
608	return d.unmarshal(v)
609}
610
611// Marshal returns the TOML encoding of Tree.
612// See Marshal() documentation for types mapping table.
613func (t *Tree) Marshal() ([]byte, error) {
614	var buf bytes.Buffer
615	_, err := t.WriteTo(&buf)
616	if err != nil {
617		return nil, err
618	}
619	return buf.Bytes(), nil
620}
621
622// Unmarshal parses the TOML-encoded data and stores the result in the value
623// pointed to by v. Behavior is similar to the Go json encoder, except that there
624// is no concept of an Unmarshaler interface or UnmarshalTOML function for
625// sub-structs, and currently only definite types can be unmarshaled to (i.e. no
626// `interface{}`).
627//
628// The following struct annotations are supported:
629//
630//   toml:"Field" Overrides the field's name to map to.
631//   default:"foo" Provides a default value.
632//
633// For default values, only fields of the following types are supported:
634//   * string
635//   * bool
636//   * int
637//   * int64
638//   * float64
639//
640// See Marshal() documentation for types mapping table.
641func Unmarshal(data []byte, v interface{}) error {
642	t, err := LoadReader(bytes.NewReader(data))
643	if err != nil {
644		return err
645	}
646	return t.Unmarshal(v)
647}
648
649// Decoder reads and decodes TOML values from an input stream.
650type Decoder struct {
651	r    io.Reader
652	tval *Tree
653	encOpts
654	tagName string
655	strict  bool
656	visitor visitorState
657}
658
659// NewDecoder returns a new decoder that reads from r.
660func NewDecoder(r io.Reader) *Decoder {
661	return &Decoder{
662		r:       r,
663		encOpts: encOptsDefaults,
664		tagName: tagFieldName,
665	}
666}
667
668// Decode reads a TOML-encoded value from it's input
669// and unmarshals it in the value pointed at by v.
670//
671// See the documentation for Marshal for details.
672func (d *Decoder) Decode(v interface{}) error {
673	var err error
674	d.tval, err = LoadReader(d.r)
675	if err != nil {
676		return err
677	}
678	return d.unmarshal(v)
679}
680
681// SetTagName allows changing default tag "toml"
682func (d *Decoder) SetTagName(v string) *Decoder {
683	d.tagName = v
684	return d
685}
686
687// Strict allows changing to strict decoding. Any fields that are found in the
688// input data and do not have a corresponding struct member cause an error.
689func (d *Decoder) Strict(strict bool) *Decoder {
690	d.strict = strict
691	return d
692}
693
694func (d *Decoder) unmarshal(v interface{}) error {
695	mtype := reflect.TypeOf(v)
696	if mtype == nil {
697		return errors.New("nil cannot be unmarshaled from TOML")
698	}
699	if mtype.Kind() != reflect.Ptr {
700		return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
701	}
702
703	elem := mtype.Elem()
704
705	switch elem.Kind() {
706	case reflect.Struct, reflect.Map:
707	case reflect.Interface:
708		elem = mapStringInterfaceType
709	default:
710		return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
711	}
712
713	if reflect.ValueOf(v).IsNil() {
714		return errors.New("nil pointer cannot be unmarshaled from TOML")
715	}
716
717	vv := reflect.ValueOf(v).Elem()
718
719	if d.strict {
720		d.visitor = newVisitorState(d.tval)
721	}
722
723	sval, err := d.valueFromTree(elem, d.tval, &vv)
724	if err != nil {
725		return err
726	}
727	if err := d.visitor.validate(); err != nil {
728		return err
729	}
730	reflect.ValueOf(v).Elem().Set(sval)
731	return nil
732}
733
734// Convert toml tree to marshal struct or map, using marshal type. When mval1
735// is non-nil, merge fields into the given value instead of allocating a new one.
736func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.Value) (reflect.Value, error) {
737	if mtype.Kind() == reflect.Ptr {
738		return d.unwrapPointer(mtype, tval, mval1)
739	}
740
741	// Check if pointer to value implements the Unmarshaler interface.
742	if mvalPtr := reflect.New(mtype); isCustomUnmarshaler(mvalPtr.Type()) {
743		d.visitor.visitAll()
744
745		if tval == nil {
746			return mvalPtr.Elem(), nil
747		}
748
749		if err := callCustomUnmarshaler(mvalPtr, tval.ToMap()); err != nil {
750			return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err)
751		}
752		return mvalPtr.Elem(), nil
753	}
754
755	var mval reflect.Value
756	switch mtype.Kind() {
757	case reflect.Struct:
758		if mval1 != nil {
759			mval = *mval1
760		} else {
761			mval = reflect.New(mtype).Elem()
762		}
763
764		switch mval.Interface().(type) {
765		case Tree:
766			mval.Set(reflect.ValueOf(tval).Elem())
767		default:
768			for i := 0; i < mtype.NumField(); i++ {
769				mtypef := mtype.Field(i)
770				an := annotation{tag: d.tagName}
771				opts := tomlOptions(mtypef, an)
772				if !opts.include {
773					continue
774				}
775				baseKey := opts.name
776				keysToTry := []string{
777					baseKey,
778					strings.ToLower(baseKey),
779					strings.ToTitle(baseKey),
780					strings.ToLower(string(baseKey[0])) + baseKey[1:],
781				}
782
783				found := false
784				if tval != nil {
785					for _, key := range keysToTry {
786						exists := tval.HasPath([]string{key})
787						if !exists {
788							continue
789						}
790
791						d.visitor.push(key)
792						val := tval.GetPath([]string{key})
793						fval := mval.Field(i)
794						mvalf, err := d.valueFromToml(mtypef.Type, val, &fval)
795						if err != nil {
796							return mval, formatError(err, tval.GetPositionPath([]string{key}))
797						}
798						mval.Field(i).Set(mvalf)
799						found = true
800						d.visitor.pop()
801						break
802					}
803				}
804
805				if !found && opts.defaultValue != "" {
806					mvalf := mval.Field(i)
807					var val interface{}
808					var err error
809					switch mvalf.Kind() {
810					case reflect.String:
811						val = opts.defaultValue
812					case reflect.Bool:
813						val, err = strconv.ParseBool(opts.defaultValue)
814					case reflect.Uint:
815						val, err = strconv.ParseUint(opts.defaultValue, 10, 0)
816					case reflect.Uint8:
817						val, err = strconv.ParseUint(opts.defaultValue, 10, 8)
818					case reflect.Uint16:
819						val, err = strconv.ParseUint(opts.defaultValue, 10, 16)
820					case reflect.Uint32:
821						val, err = strconv.ParseUint(opts.defaultValue, 10, 32)
822					case reflect.Uint64:
823						val, err = strconv.ParseUint(opts.defaultValue, 10, 64)
824					case reflect.Int:
825						val, err = strconv.ParseInt(opts.defaultValue, 10, 0)
826					case reflect.Int8:
827						val, err = strconv.ParseInt(opts.defaultValue, 10, 8)
828					case reflect.Int16:
829						val, err = strconv.ParseInt(opts.defaultValue, 10, 16)
830					case reflect.Int32:
831						val, err = strconv.ParseInt(opts.defaultValue, 10, 32)
832					case reflect.Int64:
833						val, err = strconv.ParseInt(opts.defaultValue, 10, 64)
834					case reflect.Float32:
835						val, err = strconv.ParseFloat(opts.defaultValue, 32)
836					case reflect.Float64:
837						val, err = strconv.ParseFloat(opts.defaultValue, 64)
838					default:
839						return mvalf, fmt.Errorf("unsupported field type for default option")
840					}
841
842					if err != nil {
843						return mvalf, err
844					}
845					mvalf.Set(reflect.ValueOf(val).Convert(mvalf.Type()))
846				}
847
848				// save the old behavior above and try to check structs
849				if !found && opts.defaultValue == "" && mtypef.Type.Kind() == reflect.Struct {
850					tmpTval := tval
851					if !mtypef.Anonymous {
852						tmpTval = nil
853					}
854					fval := mval.Field(i)
855					v, err := d.valueFromTree(mtypef.Type, tmpTval, &fval)
856					if err != nil {
857						return v, err
858					}
859					mval.Field(i).Set(v)
860				}
861			}
862		}
863	case reflect.Map:
864		mval = reflect.MakeMap(mtype)
865		for _, key := range tval.Keys() {
866			d.visitor.push(key)
867			// TODO: path splits key
868			val := tval.GetPath([]string{key})
869			mvalf, err := d.valueFromToml(mtype.Elem(), val, nil)
870			if err != nil {
871				return mval, formatError(err, tval.GetPositionPath([]string{key}))
872			}
873			mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf)
874			d.visitor.pop()
875		}
876	}
877	return mval, nil
878}
879
880// Convert toml value to marshal struct/map slice, using marshal type
881func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
882	mval, err := makeSliceOrArray(mtype, len(tval))
883	if err != nil {
884		return mval, err
885	}
886
887	for i := 0; i < len(tval); i++ {
888		d.visitor.push(strconv.Itoa(i))
889		val, err := d.valueFromTree(mtype.Elem(), tval[i], nil)
890		if err != nil {
891			return mval, err
892		}
893		mval.Index(i).Set(val)
894		d.visitor.pop()
895	}
896	return mval, nil
897}
898
899// Convert toml value to marshal primitive slice, using marshal type
900func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
901	mval, err := makeSliceOrArray(mtype, len(tval))
902	if err != nil {
903		return mval, err
904	}
905
906	for i := 0; i < len(tval); i++ {
907		val, err := d.valueFromToml(mtype.Elem(), tval[i], nil)
908		if err != nil {
909			return mval, err
910		}
911		mval.Index(i).Set(val)
912	}
913	return mval, nil
914}
915
916// Convert toml value to marshal primitive slice, using marshal type
917func (d *Decoder) valueFromOtherSliceI(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
918	val := reflect.ValueOf(tval)
919	length := val.Len()
920
921	mval, err := makeSliceOrArray(mtype, length)
922	if err != nil {
923		return mval, err
924	}
925
926	for i := 0; i < length; i++ {
927		val, err := d.valueFromToml(mtype.Elem(), val.Index(i).Interface(), nil)
928		if err != nil {
929			return mval, err
930		}
931		mval.Index(i).Set(val)
932	}
933	return mval, nil
934}
935
936// Create a new slice or a new array with specified length
937func makeSliceOrArray(mtype reflect.Type, tLength int) (reflect.Value, error) {
938	var mval reflect.Value
939	switch mtype.Kind() {
940	case reflect.Slice:
941		mval = reflect.MakeSlice(mtype, tLength, tLength)
942	case reflect.Array:
943		mval = reflect.New(reflect.ArrayOf(mtype.Len(), mtype.Elem())).Elem()
944		if tLength > mtype.Len() {
945			return mval, fmt.Errorf("unmarshal: TOML array length (%v) exceeds destination array length (%v)", tLength, mtype.Len())
946		}
947	}
948	return mval, nil
949}
950
951// Convert toml value to marshal value, using marshal type. When mval1 is non-nil
952// and the given type is a struct value, merge fields into it.
953func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) {
954	if mtype.Kind() == reflect.Ptr {
955		return d.unwrapPointer(mtype, tval, mval1)
956	}
957
958	switch t := tval.(type) {
959	case *Tree:
960		var mval11 *reflect.Value
961		if mtype.Kind() == reflect.Struct {
962			mval11 = mval1
963		}
964
965		if isTree(mtype) {
966			return d.valueFromTree(mtype, t, mval11)
967		}
968
969		if mtype.Kind() == reflect.Interface {
970			if mval1 == nil || mval1.IsNil() {
971				return d.valueFromTree(reflect.TypeOf(map[string]interface{}{}), t, nil)
972			} else {
973				return d.valueFromToml(mval1.Elem().Type(), t, nil)
974			}
975		}
976
977		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
978	case []*Tree:
979		if isTreeSequence(mtype) {
980			return d.valueFromTreeSlice(mtype, t)
981		}
982		if mtype.Kind() == reflect.Interface {
983			if mval1 == nil || mval1.IsNil() {
984				return d.valueFromTreeSlice(reflect.TypeOf([]map[string]interface{}{}), t)
985			} else {
986				ival := mval1.Elem()
987				return d.valueFromToml(mval1.Elem().Type(), t, &ival)
988			}
989		}
990		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
991	case []interface{}:
992		d.visitor.visit()
993		if isOtherSequence(mtype) {
994			return d.valueFromOtherSlice(mtype, t)
995		}
996		if mtype.Kind() == reflect.Interface {
997			if mval1 == nil || mval1.IsNil() {
998				return d.valueFromOtherSlice(reflect.TypeOf([]interface{}{}), t)
999			} else {
1000				ival := mval1.Elem()
1001				return d.valueFromToml(mval1.Elem().Type(), t, &ival)
1002			}
1003		}
1004		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
1005	default:
1006		d.visitor.visit()
1007		// Check if pointer to value implements the encoding.TextUnmarshaler.
1008		if mvalPtr := reflect.New(mtype); isTextUnmarshaler(mvalPtr.Type()) && !isTimeType(mtype) {
1009			if err := d.unmarshalText(tval, mvalPtr); err != nil {
1010				return reflect.ValueOf(nil), fmt.Errorf("unmarshal text: %v", err)
1011			}
1012			return mvalPtr.Elem(), nil
1013		}
1014
1015		switch mtype.Kind() {
1016		case reflect.Bool, reflect.Struct:
1017			val := reflect.ValueOf(tval)
1018
1019			switch val.Type() {
1020			case localDateType:
1021				localDate := val.Interface().(LocalDate)
1022				switch mtype {
1023				case timeType:
1024					return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil
1025				}
1026			case localDateTimeType:
1027				localDateTime := val.Interface().(LocalDateTime)
1028				switch mtype {
1029				case timeType:
1030					return reflect.ValueOf(time.Date(
1031						localDateTime.Date.Year,
1032						localDateTime.Date.Month,
1033						localDateTime.Date.Day,
1034						localDateTime.Time.Hour,
1035						localDateTime.Time.Minute,
1036						localDateTime.Time.Second,
1037						localDateTime.Time.Nanosecond,
1038						time.Local)), nil
1039				}
1040			}
1041
1042			// if this passes for when mtype is reflect.Struct, tval is a time.LocalTime
1043			if !val.Type().ConvertibleTo(mtype) {
1044				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
1045			}
1046
1047			return val.Convert(mtype), nil
1048		case reflect.String:
1049			val := reflect.ValueOf(tval)
1050			// stupidly, int64 is convertible to string. So special case this.
1051			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 {
1052				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
1053			}
1054
1055			return val.Convert(mtype), nil
1056		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1057			val := reflect.ValueOf(tval)
1058			if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String {
1059				d, err := time.ParseDuration(val.String())
1060				if err != nil {
1061					return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err)
1062				}
1063				return reflect.ValueOf(d), nil
1064			}
1065			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 {
1066				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
1067			}
1068			if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(reflect.TypeOf(int64(0))).Int()) {
1069				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
1070			}
1071
1072			return val.Convert(mtype), nil
1073		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1074			val := reflect.ValueOf(tval)
1075			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 {
1076				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
1077			}
1078
1079			if val.Convert(reflect.TypeOf(int(1))).Int() < 0 {
1080				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
1081			}
1082			if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) {
1083				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
1084			}
1085
1086			return val.Convert(mtype), nil
1087		case reflect.Float32, reflect.Float64:
1088			val := reflect.ValueOf(tval)
1089			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 {
1090				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
1091			}
1092			if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(reflect.TypeOf(float64(0))).Float()) {
1093				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
1094			}
1095
1096			return val.Convert(mtype), nil
1097		case reflect.Interface:
1098			if mval1 == nil || mval1.IsNil() {
1099				return reflect.ValueOf(tval), nil
1100			} else {
1101				ival := mval1.Elem()
1102				return d.valueFromToml(mval1.Elem().Type(), t, &ival)
1103			}
1104		case reflect.Slice, reflect.Array:
1105			if isOtherSequence(mtype) && isOtherSequence(reflect.TypeOf(t)) {
1106				return d.valueFromOtherSliceI(mtype, t)
1107			}
1108			return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
1109		default:
1110			return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
1111		}
1112	}
1113}
1114
1115func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) {
1116	var melem *reflect.Value
1117
1118	if mval1 != nil && !mval1.IsNil() && (mtype.Elem().Kind() == reflect.Struct || mtype.Elem().Kind() == reflect.Interface) {
1119		elem := mval1.Elem()
1120		melem = &elem
1121	}
1122
1123	val, err := d.valueFromToml(mtype.Elem(), tval, melem)
1124	if err != nil {
1125		return reflect.ValueOf(nil), err
1126	}
1127	mval := reflect.New(mtype.Elem())
1128	mval.Elem().Set(val)
1129	return mval, nil
1130}
1131
1132func (d *Decoder) unmarshalText(tval interface{}, mval reflect.Value) error {
1133	var buf bytes.Buffer
1134	fmt.Fprint(&buf, tval)
1135	return callTextUnmarshaler(mval, buf.Bytes())
1136}
1137
1138func tomlOptions(vf reflect.StructField, an annotation) tomlOpts {
1139	tag := vf.Tag.Get(an.tag)
1140	parse := strings.Split(tag, ",")
1141	var comment string
1142	if c := vf.Tag.Get(an.comment); c != "" {
1143		comment = c
1144	}
1145	commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented))
1146	multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline))
1147	defaultValue := vf.Tag.Get(tagDefault)
1148	result := tomlOpts{
1149		name:         vf.Name,
1150		nameFromTag:  false,
1151		comment:      comment,
1152		commented:    commented,
1153		multiline:    multiline,
1154		include:      true,
1155		omitempty:    false,
1156		defaultValue: defaultValue,
1157	}
1158	if parse[0] != "" {
1159		if parse[0] == "-" && len(parse) == 1 {
1160			result.include = false
1161		} else {
1162			result.name = strings.Trim(parse[0], " ")
1163			result.nameFromTag = true
1164		}
1165	}
1166	if vf.PkgPath != "" {
1167		result.include = false
1168	}
1169	if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
1170		result.omitempty = true
1171	}
1172	if vf.Type.Kind() == reflect.Ptr {
1173		result.omitempty = true
1174	}
1175	return result
1176}
1177
1178func isZero(val reflect.Value) bool {
1179	switch val.Type().Kind() {
1180	case reflect.Slice, reflect.Array, reflect.Map:
1181		return val.Len() == 0
1182	default:
1183		return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
1184	}
1185}
1186
1187func formatError(err error, pos Position) error {
1188	if err.Error()[0] == '(' { // Error already contains position information
1189		return err
1190	}
1191	return fmt.Errorf("%s: %s", pos, err)
1192}
1193
1194// visitorState keeps track of which keys were unmarshaled.
1195type visitorState struct {
1196	tree   *Tree
1197	path   []string
1198	keys   map[string]struct{}
1199	active bool
1200}
1201
1202func newVisitorState(tree *Tree) visitorState {
1203	path, result := []string{}, map[string]struct{}{}
1204	insertKeys(path, result, tree)
1205	return visitorState{
1206		tree:   tree,
1207		path:   path[:0],
1208		keys:   result,
1209		active: true,
1210	}
1211}
1212
1213func (s *visitorState) push(key string) {
1214	if s.active {
1215		s.path = append(s.path, key)
1216	}
1217}
1218
1219func (s *visitorState) pop() {
1220	if s.active {
1221		s.path = s.path[:len(s.path)-1]
1222	}
1223}
1224
1225func (s *visitorState) visit() {
1226	if s.active {
1227		delete(s.keys, strings.Join(s.path, "."))
1228	}
1229}
1230
1231func (s *visitorState) visitAll() {
1232	if s.active {
1233		for k := range s.keys {
1234			if strings.HasPrefix(k, strings.Join(s.path, ".")) {
1235				delete(s.keys, k)
1236			}
1237		}
1238	}
1239}
1240
1241func (s *visitorState) validate() error {
1242	if !s.active {
1243		return nil
1244	}
1245	undecoded := make([]string, 0, len(s.keys))
1246	for key := range s.keys {
1247		undecoded = append(undecoded, key)
1248	}
1249	sort.Strings(undecoded)
1250	if len(undecoded) > 0 {
1251		return fmt.Errorf("undecoded keys: %q", undecoded)
1252	}
1253	return nil
1254}
1255
1256func insertKeys(path []string, m map[string]struct{}, tree *Tree) {
1257	for k, v := range tree.values {
1258		switch node := v.(type) {
1259		case []*Tree:
1260			for i, item := range node {
1261				insertKeys(append(path, k, strconv.Itoa(i)), m, item)
1262			}
1263		case *Tree:
1264			insertKeys(append(path, k), m, node)
1265		case *tomlValue:
1266			m[strings.Join(append(path, k), ".")] = struct{}{}
1267		}
1268	}
1269}
1270