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 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. package toml
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. "sort"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. tagFieldName = "toml"
  15. tagFieldComment = "comment"
  16. tagCommented = "commented"
  17. tagMultiline = "multiline"
  18. tagDefault = "default"
  19. )
  20. type tomlOpts struct {
  21. name string
  22. comment string
  23. commented bool
  24. multiline bool
  25. include bool
  26. omitempty bool
  27. defaultValue string
  28. }
  29. type encOpts struct {
  30. quoteMapKeys bool
  31. arraysOneElementPerLine bool
  32. }
  33. var encOptsDefaults = encOpts{
  34. quoteMapKeys: false,
  35. }
  36. type annotation struct {
  37. tag string
  38. comment string
  39. commented string
  40. multiline string
  41. defaultValue string
  42. }
  43. var annotationDefault = annotation{
  44. tag: tagFieldName,
  45. comment: tagFieldComment,
  46. commented: tagCommented,
  47. multiline: tagMultiline,
  48. defaultValue: tagDefault,
  49. }
  50. type marshalOrder int
  51. // Orders the Encoder can write the fields to the output stream.
  52. const (
  53. // Sort fields alphabetically.
  54. OrderAlphabetical marshalOrder = iota + 1
  55. // Preserve the order the fields are encountered. For example, the order of fields in
  56. // a struct.
  57. OrderPreserve
  58. )
  59. var timeType = reflect.TypeOf(time.Time{})
  60. var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
  61. // Check if the given marshal type maps to a Tree primitive
  62. func isPrimitive(mtype reflect.Type) bool {
  63. switch mtype.Kind() {
  64. case reflect.Ptr:
  65. return isPrimitive(mtype.Elem())
  66. case reflect.Bool:
  67. return true
  68. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  69. return true
  70. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  71. return true
  72. case reflect.Float32, reflect.Float64:
  73. return true
  74. case reflect.String:
  75. return true
  76. case reflect.Struct:
  77. return mtype == timeType || isCustomMarshaler(mtype)
  78. default:
  79. return false
  80. }
  81. }
  82. // Check if the given marshal type maps to a Tree slice
  83. func isTreeSlice(mtype reflect.Type) bool {
  84. switch mtype.Kind() {
  85. case reflect.Slice:
  86. return !isOtherSlice(mtype)
  87. default:
  88. return false
  89. }
  90. }
  91. // Check if the given marshal type maps to a non-Tree slice
  92. func isOtherSlice(mtype reflect.Type) bool {
  93. switch mtype.Kind() {
  94. case reflect.Ptr:
  95. return isOtherSlice(mtype.Elem())
  96. case reflect.Slice:
  97. return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem())
  98. default:
  99. return false
  100. }
  101. }
  102. // Check if the given marshal type maps to a Tree
  103. func isTree(mtype reflect.Type) bool {
  104. switch mtype.Kind() {
  105. case reflect.Map:
  106. return true
  107. case reflect.Struct:
  108. return !isPrimitive(mtype)
  109. default:
  110. return false
  111. }
  112. }
  113. func isCustomMarshaler(mtype reflect.Type) bool {
  114. return mtype.Implements(marshalerType)
  115. }
  116. func callCustomMarshaler(mval reflect.Value) ([]byte, error) {
  117. return mval.Interface().(Marshaler).MarshalTOML()
  118. }
  119. // Marshaler is the interface implemented by types that
  120. // can marshal themselves into valid TOML.
  121. type Marshaler interface {
  122. MarshalTOML() ([]byte, error)
  123. }
  124. /*
  125. Marshal returns the TOML encoding of v. Behavior is similar to the Go json
  126. encoder, except that there is no concept of a Marshaler interface or MarshalTOML
  127. function for sub-structs, and currently only definite types can be marshaled
  128. (i.e. no `interface{}`).
  129. The following struct annotations are supported:
  130. toml:"Field" Overrides the field's name to output.
  131. omitempty When set, empty values and groups are not emitted.
  132. comment:"comment" Emits a # comment on the same line. This supports new lines.
  133. commented:"true" Emits the value as commented.
  134. Note that pointers are automatically assigned the "omitempty" option, as TOML
  135. explicitly does not handle null values (saying instead the label should be
  136. dropped).
  137. Tree structural types and corresponding marshal types:
  138. *Tree (*)struct, (*)map[string]interface{}
  139. []*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
  140. []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
  141. interface{} (*)primitive
  142. Tree primitive types and corresponding marshal types:
  143. uint64 uint, uint8-uint64, pointers to same
  144. int64 int, int8-uint64, pointers to same
  145. float64 float32, float64, pointers to same
  146. string string, pointers to same
  147. bool bool, pointers to same
  148. time.Time time.Time{}, pointers to same
  149. For additional flexibility, use the Encoder API.
  150. */
  151. func Marshal(v interface{}) ([]byte, error) {
  152. return NewEncoder(nil).marshal(v)
  153. }
  154. // Encoder writes TOML values to an output stream.
  155. type Encoder struct {
  156. w io.Writer
  157. encOpts
  158. annotation
  159. line int
  160. col int
  161. order marshalOrder
  162. }
  163. // NewEncoder returns a new encoder that writes to w.
  164. func NewEncoder(w io.Writer) *Encoder {
  165. return &Encoder{
  166. w: w,
  167. encOpts: encOptsDefaults,
  168. annotation: annotationDefault,
  169. line: 0,
  170. col: 1,
  171. order: OrderAlphabetical,
  172. }
  173. }
  174. // Encode writes the TOML encoding of v to the stream.
  175. //
  176. // See the documentation for Marshal for details.
  177. func (e *Encoder) Encode(v interface{}) error {
  178. b, err := e.marshal(v)
  179. if err != nil {
  180. return err
  181. }
  182. if _, err := e.w.Write(b); err != nil {
  183. return err
  184. }
  185. return nil
  186. }
  187. // QuoteMapKeys sets up the encoder to encode
  188. // maps with string type keys with quoted TOML keys.
  189. //
  190. // This relieves the character limitations on map keys.
  191. func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
  192. e.quoteMapKeys = v
  193. return e
  194. }
  195. // ArraysWithOneElementPerLine sets up the encoder to encode arrays
  196. // with more than one element on multiple lines instead of one.
  197. //
  198. // For example:
  199. //
  200. // A = [1,2,3]
  201. //
  202. // Becomes
  203. //
  204. // A = [
  205. // 1,
  206. // 2,
  207. // 3,
  208. // ]
  209. func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
  210. e.arraysOneElementPerLine = v
  211. return e
  212. }
  213. // Order allows to change in which order fields will be written to the output stream.
  214. func (e *Encoder) Order(ord marshalOrder) *Encoder {
  215. e.order = ord
  216. return e
  217. }
  218. // SetTagName allows changing default tag "toml"
  219. func (e *Encoder) SetTagName(v string) *Encoder {
  220. e.tag = v
  221. return e
  222. }
  223. // SetTagComment allows changing default tag "comment"
  224. func (e *Encoder) SetTagComment(v string) *Encoder {
  225. e.comment = v
  226. return e
  227. }
  228. // SetTagCommented allows changing default tag "commented"
  229. func (e *Encoder) SetTagCommented(v string) *Encoder {
  230. e.commented = v
  231. return e
  232. }
  233. // SetTagMultiline allows changing default tag "multiline"
  234. func (e *Encoder) SetTagMultiline(v string) *Encoder {
  235. e.multiline = v
  236. return e
  237. }
  238. func (e *Encoder) marshal(v interface{}) ([]byte, error) {
  239. mtype := reflect.TypeOf(v)
  240. switch mtype.Kind() {
  241. case reflect.Struct, reflect.Map:
  242. case reflect.Ptr:
  243. if mtype.Elem().Kind() != reflect.Struct {
  244. return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML")
  245. }
  246. default:
  247. return []byte{}, errors.New("Only a struct or map can be marshaled to TOML")
  248. }
  249. sval := reflect.ValueOf(v)
  250. if isCustomMarshaler(mtype) {
  251. return callCustomMarshaler(sval)
  252. }
  253. t, err := e.valueToTree(mtype, sval)
  254. if err != nil {
  255. return []byte{}, err
  256. }
  257. var buf bytes.Buffer
  258. _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order)
  259. return buf.Bytes(), err
  260. }
  261. // Create next tree with a position based on Encoder.line
  262. func (e *Encoder) nextTree() *Tree {
  263. return newTreeWithPosition(Position{Line: e.line, Col: 1})
  264. }
  265. // Convert given marshal struct or map value to toml tree
  266. func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
  267. if mtype.Kind() == reflect.Ptr {
  268. return e.valueToTree(mtype.Elem(), mval.Elem())
  269. }
  270. tval := e.nextTree()
  271. switch mtype.Kind() {
  272. case reflect.Struct:
  273. for i := 0; i < mtype.NumField(); i++ {
  274. mtypef, mvalf := mtype.Field(i), mval.Field(i)
  275. opts := tomlOptions(mtypef, e.annotation)
  276. if opts.include && (!opts.omitempty || !isZero(mvalf)) {
  277. val, err := e.valueToToml(mtypef.Type, mvalf)
  278. if err != nil {
  279. return nil, err
  280. }
  281. tval.SetWithOptions(opts.name, SetOptions{
  282. Comment: opts.comment,
  283. Commented: opts.commented,
  284. Multiline: opts.multiline,
  285. }, val)
  286. }
  287. }
  288. case reflect.Map:
  289. keys := mval.MapKeys()
  290. if e.order == OrderPreserve && len(keys) > 0 {
  291. // Sorting []reflect.Value is not straight forward.
  292. //
  293. // OrderPreserve will support deterministic results when string is used
  294. // as the key to maps.
  295. typ := keys[0].Type()
  296. kind := keys[0].Kind()
  297. if kind == reflect.String {
  298. ikeys := make([]string, len(keys))
  299. for i := range keys {
  300. ikeys[i] = keys[i].Interface().(string)
  301. }
  302. sort.Strings(ikeys)
  303. for i := range ikeys {
  304. keys[i] = reflect.ValueOf(ikeys[i]).Convert(typ)
  305. }
  306. }
  307. }
  308. for _, key := range keys {
  309. mvalf := mval.MapIndex(key)
  310. val, err := e.valueToToml(mtype.Elem(), mvalf)
  311. if err != nil {
  312. return nil, err
  313. }
  314. if e.quoteMapKeys {
  315. keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine)
  316. if err != nil {
  317. return nil, err
  318. }
  319. tval.SetPath([]string{keyStr}, val)
  320. } else {
  321. tval.Set(key.String(), val)
  322. }
  323. }
  324. }
  325. return tval, nil
  326. }
  327. // Convert given marshal slice to slice of Toml trees
  328. func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
  329. tval := make([]*Tree, mval.Len(), mval.Len())
  330. for i := 0; i < mval.Len(); i++ {
  331. val, err := e.valueToTree(mtype.Elem(), mval.Index(i))
  332. if err != nil {
  333. return nil, err
  334. }
  335. tval[i] = val
  336. }
  337. return tval, nil
  338. }
  339. // Convert given marshal slice to slice of toml values
  340. func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
  341. tval := make([]interface{}, mval.Len(), mval.Len())
  342. for i := 0; i < mval.Len(); i++ {
  343. val, err := e.valueToToml(mtype.Elem(), mval.Index(i))
  344. if err != nil {
  345. return nil, err
  346. }
  347. tval[i] = val
  348. }
  349. return tval, nil
  350. }
  351. // Convert given marshal value to toml value
  352. func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
  353. e.line++
  354. if mtype.Kind() == reflect.Ptr {
  355. return e.valueToToml(mtype.Elem(), mval.Elem())
  356. }
  357. switch {
  358. case isCustomMarshaler(mtype):
  359. return callCustomMarshaler(mval)
  360. case isTree(mtype):
  361. return e.valueToTree(mtype, mval)
  362. case isTreeSlice(mtype):
  363. return e.valueToTreeSlice(mtype, mval)
  364. case isOtherSlice(mtype):
  365. return e.valueToOtherSlice(mtype, mval)
  366. default:
  367. switch mtype.Kind() {
  368. case reflect.Bool:
  369. return mval.Bool(), nil
  370. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  371. if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) {
  372. return fmt.Sprint(mval), nil
  373. }
  374. return mval.Int(), nil
  375. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  376. return mval.Uint(), nil
  377. case reflect.Float32, reflect.Float64:
  378. return mval.Float(), nil
  379. case reflect.String:
  380. return mval.String(), nil
  381. case reflect.Struct:
  382. return mval.Interface().(time.Time), nil
  383. default:
  384. return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind())
  385. }
  386. }
  387. }
  388. // Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
  389. // Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
  390. // sub-structs, and only definite types can be unmarshaled.
  391. func (t *Tree) Unmarshal(v interface{}) error {
  392. d := Decoder{tval: t, tagName: tagFieldName}
  393. return d.unmarshal(v)
  394. }
  395. // Marshal returns the TOML encoding of Tree.
  396. // See Marshal() documentation for types mapping table.
  397. func (t *Tree) Marshal() ([]byte, error) {
  398. var buf bytes.Buffer
  399. err := NewEncoder(&buf).Encode(t)
  400. return buf.Bytes(), err
  401. }
  402. // Unmarshal parses the TOML-encoded data and stores the result in the value
  403. // pointed to by v. Behavior is similar to the Go json encoder, except that there
  404. // is no concept of an Unmarshaler interface or UnmarshalTOML function for
  405. // sub-structs, and currently only definite types can be unmarshaled to (i.e. no
  406. // `interface{}`).
  407. //
  408. // The following struct annotations are supported:
  409. //
  410. // toml:"Field" Overrides the field's name to map to.
  411. // default:"foo" Provides a default value.
  412. //
  413. // For default values, only fields of the following types are supported:
  414. // * string
  415. // * bool
  416. // * int
  417. // * int64
  418. // * float64
  419. //
  420. // See Marshal() documentation for types mapping table.
  421. func Unmarshal(data []byte, v interface{}) error {
  422. t, err := LoadReader(bytes.NewReader(data))
  423. if err != nil {
  424. return err
  425. }
  426. return t.Unmarshal(v)
  427. }
  428. // Decoder reads and decodes TOML values from an input stream.
  429. type Decoder struct {
  430. r io.Reader
  431. tval *Tree
  432. encOpts
  433. tagName string
  434. }
  435. // NewDecoder returns a new decoder that reads from r.
  436. func NewDecoder(r io.Reader) *Decoder {
  437. return &Decoder{
  438. r: r,
  439. encOpts: encOptsDefaults,
  440. tagName: tagFieldName,
  441. }
  442. }
  443. // Decode reads a TOML-encoded value from it's input
  444. // and unmarshals it in the value pointed at by v.
  445. //
  446. // See the documentation for Marshal for details.
  447. func (d *Decoder) Decode(v interface{}) error {
  448. var err error
  449. d.tval, err = LoadReader(d.r)
  450. if err != nil {
  451. return err
  452. }
  453. return d.unmarshal(v)
  454. }
  455. // SetTagName allows changing default tag "toml"
  456. func (d *Decoder) SetTagName(v string) *Decoder {
  457. d.tagName = v
  458. return d
  459. }
  460. func (d *Decoder) unmarshal(v interface{}) error {
  461. mtype := reflect.TypeOf(v)
  462. if mtype.Kind() != reflect.Ptr {
  463. return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
  464. }
  465. elem := mtype.Elem()
  466. switch elem.Kind() {
  467. case reflect.Struct, reflect.Map:
  468. default:
  469. return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
  470. }
  471. sval, err := d.valueFromTree(elem, d.tval)
  472. if err != nil {
  473. return err
  474. }
  475. reflect.ValueOf(v).Elem().Set(sval)
  476. return nil
  477. }
  478. // Convert toml tree to marshal struct or map, using marshal type
  479. func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
  480. if mtype.Kind() == reflect.Ptr {
  481. return d.unwrapPointer(mtype, tval)
  482. }
  483. var mval reflect.Value
  484. switch mtype.Kind() {
  485. case reflect.Struct:
  486. mval = reflect.New(mtype).Elem()
  487. for i := 0; i < mtype.NumField(); i++ {
  488. mtypef := mtype.Field(i)
  489. an := annotation{tag: d.tagName}
  490. opts := tomlOptions(mtypef, an)
  491. if opts.include {
  492. baseKey := opts.name
  493. keysToTry := []string{
  494. baseKey,
  495. strings.ToLower(baseKey),
  496. strings.ToTitle(baseKey),
  497. strings.ToLower(string(baseKey[0])) + baseKey[1:],
  498. }
  499. found := false
  500. for _, key := range keysToTry {
  501. exists := tval.Has(key)
  502. if !exists {
  503. continue
  504. }
  505. val := tval.Get(key)
  506. mvalf, err := d.valueFromToml(mtypef.Type, val)
  507. if err != nil {
  508. return mval, formatError(err, tval.GetPosition(key))
  509. }
  510. mval.Field(i).Set(mvalf)
  511. found = true
  512. break
  513. }
  514. if !found && opts.defaultValue != "" {
  515. mvalf := mval.Field(i)
  516. var val interface{}
  517. var err error
  518. switch mvalf.Kind() {
  519. case reflect.Bool:
  520. val, err = strconv.ParseBool(opts.defaultValue)
  521. if err != nil {
  522. return mval.Field(i), err
  523. }
  524. case reflect.Int:
  525. val, err = strconv.Atoi(opts.defaultValue)
  526. if err != nil {
  527. return mval.Field(i), err
  528. }
  529. case reflect.String:
  530. val = opts.defaultValue
  531. case reflect.Int64:
  532. val, err = strconv.ParseInt(opts.defaultValue, 10, 64)
  533. if err != nil {
  534. return mval.Field(i), err
  535. }
  536. case reflect.Float64:
  537. val, err = strconv.ParseFloat(opts.defaultValue, 64)
  538. if err != nil {
  539. return mval.Field(i), err
  540. }
  541. default:
  542. return mval.Field(i), fmt.Errorf("unsuported field type for default option")
  543. }
  544. mval.Field(i).Set(reflect.ValueOf(val))
  545. }
  546. }
  547. }
  548. case reflect.Map:
  549. mval = reflect.MakeMap(mtype)
  550. for _, key := range tval.Keys() {
  551. // TODO: path splits key
  552. val := tval.GetPath([]string{key})
  553. mvalf, err := d.valueFromToml(mtype.Elem(), val)
  554. if err != nil {
  555. return mval, formatError(err, tval.GetPosition(key))
  556. }
  557. mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf)
  558. }
  559. }
  560. return mval, nil
  561. }
  562. // Convert toml value to marshal struct/map slice, using marshal type
  563. func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
  564. mval := reflect.MakeSlice(mtype, len(tval), len(tval))
  565. for i := 0; i < len(tval); i++ {
  566. val, err := d.valueFromTree(mtype.Elem(), tval[i])
  567. if err != nil {
  568. return mval, err
  569. }
  570. mval.Index(i).Set(val)
  571. }
  572. return mval, nil
  573. }
  574. // Convert toml value to marshal primitive slice, using marshal type
  575. func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) {
  576. mval := reflect.MakeSlice(mtype, len(tval), len(tval))
  577. for i := 0; i < len(tval); i++ {
  578. val, err := d.valueFromToml(mtype.Elem(), tval[i])
  579. if err != nil {
  580. return mval, err
  581. }
  582. mval.Index(i).Set(val)
  583. }
  584. return mval, nil
  585. }
  586. // Convert toml value to marshal value, using marshal type
  587. func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
  588. if mtype.Kind() == reflect.Ptr {
  589. return d.unwrapPointer(mtype, tval)
  590. }
  591. switch t := tval.(type) {
  592. case *Tree:
  593. if isTree(mtype) {
  594. return d.valueFromTree(mtype, t)
  595. }
  596. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval)
  597. case []*Tree:
  598. if isTreeSlice(mtype) {
  599. return d.valueFromTreeSlice(mtype, t)
  600. }
  601. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval)
  602. case []interface{}:
  603. if isOtherSlice(mtype) {
  604. return d.valueFromOtherSlice(mtype, t)
  605. }
  606. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval)
  607. default:
  608. switch mtype.Kind() {
  609. case reflect.Bool, reflect.Struct:
  610. val := reflect.ValueOf(tval)
  611. // if this passes for when mtype is reflect.Struct, tval is a time.Time
  612. if !val.Type().ConvertibleTo(mtype) {
  613. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  614. }
  615. return val.Convert(mtype), nil
  616. case reflect.String:
  617. val := reflect.ValueOf(tval)
  618. // stupidly, int64 is convertible to string. So special case this.
  619. if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 {
  620. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  621. }
  622. return val.Convert(mtype), nil
  623. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  624. val := reflect.ValueOf(tval)
  625. if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String {
  626. d, err := time.ParseDuration(val.String())
  627. if err != nil {
  628. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err)
  629. }
  630. return reflect.ValueOf(d), nil
  631. }
  632. if !val.Type().ConvertibleTo(mtype) {
  633. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  634. }
  635. if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(mtype).Int()) {
  636. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  637. }
  638. return val.Convert(mtype), nil
  639. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  640. val := reflect.ValueOf(tval)
  641. if !val.Type().ConvertibleTo(mtype) {
  642. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  643. }
  644. if val.Convert(reflect.TypeOf(int(1))).Int() < 0 {
  645. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
  646. }
  647. if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Convert(mtype).Uint())) {
  648. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  649. }
  650. return val.Convert(mtype), nil
  651. case reflect.Float32, reflect.Float64:
  652. val := reflect.ValueOf(tval)
  653. if !val.Type().ConvertibleTo(mtype) {
  654. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
  655. }
  656. if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(mtype).Float()) {
  657. return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String())
  658. }
  659. return val.Convert(mtype), nil
  660. default:
  661. return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind())
  662. }
  663. }
  664. }
  665. func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) {
  666. val, err := d.valueFromToml(mtype.Elem(), tval)
  667. if err != nil {
  668. return reflect.ValueOf(nil), err
  669. }
  670. mval := reflect.New(mtype.Elem())
  671. mval.Elem().Set(val)
  672. return mval, nil
  673. }
  674. func tomlOptions(vf reflect.StructField, an annotation) tomlOpts {
  675. tag := vf.Tag.Get(an.tag)
  676. parse := strings.Split(tag, ",")
  677. var comment string
  678. if c := vf.Tag.Get(an.comment); c != "" {
  679. comment = c
  680. }
  681. commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented))
  682. multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline))
  683. defaultValue := vf.Tag.Get(tagDefault)
  684. result := tomlOpts{
  685. name: vf.Name,
  686. comment: comment,
  687. commented: commented,
  688. multiline: multiline,
  689. include: true,
  690. omitempty: false,
  691. defaultValue: defaultValue,
  692. }
  693. if parse[0] != "" {
  694. if parse[0] == "-" && len(parse) == 1 {
  695. result.include = false
  696. } else {
  697. result.name = strings.Trim(parse[0], " ")
  698. }
  699. }
  700. if vf.PkgPath != "" {
  701. result.include = false
  702. }
  703. if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" {
  704. result.omitempty = true
  705. }
  706. if vf.Type.Kind() == reflect.Ptr {
  707. result.omitempty = true
  708. }
  709. return result
  710. }
  711. func isZero(val reflect.Value) bool {
  712. switch val.Type().Kind() {
  713. case reflect.Map:
  714. fallthrough
  715. case reflect.Array:
  716. fallthrough
  717. case reflect.Slice:
  718. return val.Len() == 0
  719. default:
  720. return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface())
  721. }
  722. }
  723. func formatError(err error, pos Position) error {
  724. if err.Error()[0] == '(' { // Error already contains position information
  725. return err
  726. }
  727. return fmt.Errorf("%s: %s", pos, err)
  728. }