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