...

Source file src/github.com/pelletier/go-toml/marshal.go

Documentation: github.com/pelletier/go-toml

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

View as plain text