You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

marshal.go 35KB

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