decode.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. package toml
  2. import (
  3. "bytes"
  4. "encoding"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "math"
  10. "os"
  11. "reflect"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. // Unmarshaler is the interface implemented by objects that can unmarshal a
  17. // TOML description of themselves.
  18. type Unmarshaler interface {
  19. UnmarshalTOML(interface{}) error
  20. }
  21. // Unmarshal decodes the contents of data in TOML format into a pointer v.
  22. //
  23. // See [Decoder] for a description of the decoding process.
  24. func Unmarshal(data []byte, v interface{}) error {
  25. _, err := NewDecoder(bytes.NewReader(data)).Decode(v)
  26. return err
  27. }
  28. // Decode the TOML data in to the pointer v.
  29. //
  30. // See [Decoder] for a description of the decoding process.
  31. func Decode(data string, v interface{}) (MetaData, error) {
  32. return NewDecoder(strings.NewReader(data)).Decode(v)
  33. }
  34. // DecodeFile reads the contents of a file and decodes it with [Decode].
  35. func DecodeFile(path string, v interface{}) (MetaData, error) {
  36. fp, err := os.Open(path)
  37. if err != nil {
  38. return MetaData{}, err
  39. }
  40. defer fp.Close()
  41. return NewDecoder(fp).Decode(v)
  42. }
  43. // Primitive is a TOML value that hasn't been decoded into a Go value.
  44. //
  45. // This type can be used for any value, which will cause decoding to be delayed.
  46. // You can use [PrimitiveDecode] to "manually" decode these values.
  47. //
  48. // NOTE: The underlying representation of a `Primitive` value is subject to
  49. // change. Do not rely on it.
  50. //
  51. // NOTE: Primitive values are still parsed, so using them will only avoid the
  52. // overhead of reflection. They can be useful when you don't know the exact type
  53. // of TOML data until runtime.
  54. type Primitive struct {
  55. undecoded interface{}
  56. context Key
  57. }
  58. // The significand precision for float32 and float64 is 24 and 53 bits; this is
  59. // the range a natural number can be stored in a float without loss of data.
  60. const (
  61. maxSafeFloat32Int = 16777215 // 2^24-1
  62. maxSafeFloat64Int = int64(9007199254740991) // 2^53-1
  63. )
  64. // Decoder decodes TOML data.
  65. //
  66. // TOML tables correspond to Go structs or maps; they can be used
  67. // interchangeably, but structs offer better type safety.
  68. //
  69. // TOML table arrays correspond to either a slice of structs or a slice of maps.
  70. //
  71. // TOML datetimes correspond to [time.Time]. Local datetimes are parsed in the
  72. // local timezone.
  73. //
  74. // [time.Duration] types are treated as nanoseconds if the TOML value is an
  75. // integer, or they're parsed with time.ParseDuration() if they're strings.
  76. //
  77. // All other TOML types (float, string, int, bool and array) correspond to the
  78. // obvious Go types.
  79. //
  80. // An exception to the above rules is if a type implements the TextUnmarshaler
  81. // interface, in which case any primitive TOML value (floats, strings, integers,
  82. // booleans, datetimes) will be converted to a []byte and given to the value's
  83. // UnmarshalText method. See the Unmarshaler example for a demonstration with
  84. // email addresses.
  85. //
  86. // # Key mapping
  87. //
  88. // TOML keys can map to either keys in a Go map or field names in a Go struct.
  89. // The special `toml` struct tag can be used to map TOML keys to struct fields
  90. // that don't match the key name exactly (see the example). A case insensitive
  91. // match to struct names will be tried if an exact match can't be found.
  92. //
  93. // The mapping between TOML values and Go values is loose. That is, there may
  94. // exist TOML values that cannot be placed into your representation, and there
  95. // may be parts of your representation that do not correspond to TOML values.
  96. // This loose mapping can be made stricter by using the IsDefined and/or
  97. // Undecoded methods on the MetaData returned.
  98. //
  99. // This decoder does not handle cyclic types. Decode will not terminate if a
  100. // cyclic type is passed.
  101. type Decoder struct {
  102. r io.Reader
  103. }
  104. // NewDecoder creates a new Decoder.
  105. func NewDecoder(r io.Reader) *Decoder {
  106. return &Decoder{r: r}
  107. }
  108. var (
  109. unmarshalToml = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
  110. unmarshalText = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
  111. primitiveType = reflect.TypeOf((*Primitive)(nil)).Elem()
  112. )
  113. // Decode TOML data in to the pointer `v`.
  114. func (dec *Decoder) Decode(v interface{}) (MetaData, error) {
  115. rv := reflect.ValueOf(v)
  116. if rv.Kind() != reflect.Ptr {
  117. s := "%q"
  118. if reflect.TypeOf(v) == nil {
  119. s = "%v"
  120. }
  121. return MetaData{}, fmt.Errorf("toml: cannot decode to non-pointer "+s, reflect.TypeOf(v))
  122. }
  123. if rv.IsNil() {
  124. return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v))
  125. }
  126. // Check if this is a supported type: struct, map, interface{}, or something
  127. // that implements UnmarshalTOML or UnmarshalText.
  128. rv = indirect(rv)
  129. rt := rv.Type()
  130. if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map &&
  131. !(rv.Kind() == reflect.Interface && rv.NumMethod() == 0) &&
  132. !rt.Implements(unmarshalToml) && !rt.Implements(unmarshalText) {
  133. return MetaData{}, fmt.Errorf("toml: cannot decode to type %s", rt)
  134. }
  135. // TODO: parser should read from io.Reader? Or at the very least, make it
  136. // read from []byte rather than string
  137. data, err := ioutil.ReadAll(dec.r)
  138. if err != nil {
  139. return MetaData{}, err
  140. }
  141. p, err := parse(string(data))
  142. if err != nil {
  143. return MetaData{}, err
  144. }
  145. md := MetaData{
  146. mapping: p.mapping,
  147. keyInfo: p.keyInfo,
  148. keys: p.ordered,
  149. decoded: make(map[string]struct{}, len(p.ordered)),
  150. context: nil,
  151. data: data,
  152. }
  153. return md, md.unify(p.mapping, rv)
  154. }
  155. // PrimitiveDecode is just like the other Decode* functions, except it decodes a
  156. // TOML value that has already been parsed. Valid primitive values can *only* be
  157. // obtained from values filled by the decoder functions, including this method.
  158. // (i.e., v may contain more [Primitive] values.)
  159. //
  160. // Meta data for primitive values is included in the meta data returned by the
  161. // Decode* functions with one exception: keys returned by the Undecoded method
  162. // will only reflect keys that were decoded. Namely, any keys hidden behind a
  163. // Primitive will be considered undecoded. Executing this method will update the
  164. // undecoded keys in the meta data. (See the example.)
  165. func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
  166. md.context = primValue.context
  167. defer func() { md.context = nil }()
  168. return md.unify(primValue.undecoded, rvalue(v))
  169. }
  170. // unify performs a sort of type unification based on the structure of `rv`,
  171. // which is the client representation.
  172. //
  173. // Any type mismatch produces an error. Finding a type that we don't know
  174. // how to handle produces an unsupported type error.
  175. func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
  176. // Special case. Look for a `Primitive` value.
  177. // TODO: #76 would make this superfluous after implemented.
  178. if rv.Type() == primitiveType {
  179. // Save the undecoded data and the key context into the primitive
  180. // value.
  181. context := make(Key, len(md.context))
  182. copy(context, md.context)
  183. rv.Set(reflect.ValueOf(Primitive{
  184. undecoded: data,
  185. context: context,
  186. }))
  187. return nil
  188. }
  189. rvi := rv.Interface()
  190. if v, ok := rvi.(Unmarshaler); ok {
  191. return v.UnmarshalTOML(data)
  192. }
  193. if v, ok := rvi.(encoding.TextUnmarshaler); ok {
  194. return md.unifyText(data, v)
  195. }
  196. // TODO:
  197. // The behavior here is incorrect whenever a Go type satisfies the
  198. // encoding.TextUnmarshaler interface but also corresponds to a TOML hash or
  199. // array. In particular, the unmarshaler should only be applied to primitive
  200. // TOML values. But at this point, it will be applied to all kinds of values
  201. // and produce an incorrect error whenever those values are hashes or arrays
  202. // (including arrays of tables).
  203. k := rv.Kind()
  204. if k >= reflect.Int && k <= reflect.Uint64 {
  205. return md.unifyInt(data, rv)
  206. }
  207. switch k {
  208. case reflect.Ptr:
  209. elem := reflect.New(rv.Type().Elem())
  210. err := md.unify(data, reflect.Indirect(elem))
  211. if err != nil {
  212. return err
  213. }
  214. rv.Set(elem)
  215. return nil
  216. case reflect.Struct:
  217. return md.unifyStruct(data, rv)
  218. case reflect.Map:
  219. return md.unifyMap(data, rv)
  220. case reflect.Array:
  221. return md.unifyArray(data, rv)
  222. case reflect.Slice:
  223. return md.unifySlice(data, rv)
  224. case reflect.String:
  225. return md.unifyString(data, rv)
  226. case reflect.Bool:
  227. return md.unifyBool(data, rv)
  228. case reflect.Interface:
  229. if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
  230. return md.e("unsupported type %s", rv.Type())
  231. }
  232. return md.unifyAnything(data, rv)
  233. case reflect.Float32, reflect.Float64:
  234. return md.unifyFloat64(data, rv)
  235. }
  236. return md.e("unsupported type %s", rv.Kind())
  237. }
  238. func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
  239. tmap, ok := mapping.(map[string]interface{})
  240. if !ok {
  241. if mapping == nil {
  242. return nil
  243. }
  244. return md.e("type mismatch for %s: expected table but found %T",
  245. rv.Type().String(), mapping)
  246. }
  247. for key, datum := range tmap {
  248. var f *field
  249. fields := cachedTypeFields(rv.Type())
  250. for i := range fields {
  251. ff := &fields[i]
  252. if ff.name == key {
  253. f = ff
  254. break
  255. }
  256. if f == nil && strings.EqualFold(ff.name, key) {
  257. f = ff
  258. }
  259. }
  260. if f != nil {
  261. subv := rv
  262. for _, i := range f.index {
  263. subv = indirect(subv.Field(i))
  264. }
  265. if isUnifiable(subv) {
  266. md.decoded[md.context.add(key).String()] = struct{}{}
  267. md.context = append(md.context, key)
  268. err := md.unify(datum, subv)
  269. if err != nil {
  270. return err
  271. }
  272. md.context = md.context[0 : len(md.context)-1]
  273. } else if f.name != "" {
  274. return md.e("cannot write unexported field %s.%s", rv.Type().String(), f.name)
  275. }
  276. }
  277. }
  278. return nil
  279. }
  280. func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
  281. keyType := rv.Type().Key().Kind()
  282. if keyType != reflect.String && keyType != reflect.Interface {
  283. return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)",
  284. keyType, rv.Type())
  285. }
  286. tmap, ok := mapping.(map[string]interface{})
  287. if !ok {
  288. if tmap == nil {
  289. return nil
  290. }
  291. return md.badtype("map", mapping)
  292. }
  293. if rv.IsNil() {
  294. rv.Set(reflect.MakeMap(rv.Type()))
  295. }
  296. for k, v := range tmap {
  297. md.decoded[md.context.add(k).String()] = struct{}{}
  298. md.context = append(md.context, k)
  299. rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
  300. err := md.unify(v, indirect(rvval))
  301. if err != nil {
  302. return err
  303. }
  304. md.context = md.context[0 : len(md.context)-1]
  305. rvkey := indirect(reflect.New(rv.Type().Key()))
  306. switch keyType {
  307. case reflect.Interface:
  308. rvkey.Set(reflect.ValueOf(k))
  309. case reflect.String:
  310. rvkey.SetString(k)
  311. }
  312. rv.SetMapIndex(rvkey, rvval)
  313. }
  314. return nil
  315. }
  316. func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
  317. datav := reflect.ValueOf(data)
  318. if datav.Kind() != reflect.Slice {
  319. if !datav.IsValid() {
  320. return nil
  321. }
  322. return md.badtype("slice", data)
  323. }
  324. if l := datav.Len(); l != rv.Len() {
  325. return md.e("expected array length %d; got TOML array of length %d", rv.Len(), l)
  326. }
  327. return md.unifySliceArray(datav, rv)
  328. }
  329. func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
  330. datav := reflect.ValueOf(data)
  331. if datav.Kind() != reflect.Slice {
  332. if !datav.IsValid() {
  333. return nil
  334. }
  335. return md.badtype("slice", data)
  336. }
  337. n := datav.Len()
  338. if rv.IsNil() || rv.Cap() < n {
  339. rv.Set(reflect.MakeSlice(rv.Type(), n, n))
  340. }
  341. rv.SetLen(n)
  342. return md.unifySliceArray(datav, rv)
  343. }
  344. func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
  345. l := data.Len()
  346. for i := 0; i < l; i++ {
  347. err := md.unify(data.Index(i).Interface(), indirect(rv.Index(i)))
  348. if err != nil {
  349. return err
  350. }
  351. }
  352. return nil
  353. }
  354. func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
  355. _, ok := rv.Interface().(json.Number)
  356. if ok {
  357. if i, ok := data.(int64); ok {
  358. rv.SetString(strconv.FormatInt(i, 10))
  359. } else if f, ok := data.(float64); ok {
  360. rv.SetString(strconv.FormatFloat(f, 'f', -1, 64))
  361. } else {
  362. return md.badtype("string", data)
  363. }
  364. return nil
  365. }
  366. if s, ok := data.(string); ok {
  367. rv.SetString(s)
  368. return nil
  369. }
  370. return md.badtype("string", data)
  371. }
  372. func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
  373. rvk := rv.Kind()
  374. if num, ok := data.(float64); ok {
  375. switch rvk {
  376. case reflect.Float32:
  377. if num < -math.MaxFloat32 || num > math.MaxFloat32 {
  378. return md.parseErr(errParseRange{i: num, size: rvk.String()})
  379. }
  380. fallthrough
  381. case reflect.Float64:
  382. rv.SetFloat(num)
  383. default:
  384. panic("bug")
  385. }
  386. return nil
  387. }
  388. if num, ok := data.(int64); ok {
  389. if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) ||
  390. (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) {
  391. return md.parseErr(errParseRange{i: num, size: rvk.String()})
  392. }
  393. rv.SetFloat(float64(num))
  394. return nil
  395. }
  396. return md.badtype("float", data)
  397. }
  398. func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
  399. _, ok := rv.Interface().(time.Duration)
  400. if ok {
  401. // Parse as string duration, and fall back to regular integer parsing
  402. // (as nanosecond) if this is not a string.
  403. if s, ok := data.(string); ok {
  404. dur, err := time.ParseDuration(s)
  405. if err != nil {
  406. return md.parseErr(errParseDuration{s})
  407. }
  408. rv.SetInt(int64(dur))
  409. return nil
  410. }
  411. }
  412. num, ok := data.(int64)
  413. if !ok {
  414. return md.badtype("integer", data)
  415. }
  416. rvk := rv.Kind()
  417. switch {
  418. case rvk >= reflect.Int && rvk <= reflect.Int64:
  419. if (rvk == reflect.Int8 && (num < math.MinInt8 || num > math.MaxInt8)) ||
  420. (rvk == reflect.Int16 && (num < math.MinInt16 || num > math.MaxInt16)) ||
  421. (rvk == reflect.Int32 && (num < math.MinInt32 || num > math.MaxInt32)) {
  422. return md.parseErr(errParseRange{i: num, size: rvk.String()})
  423. }
  424. rv.SetInt(num)
  425. case rvk >= reflect.Uint && rvk <= reflect.Uint64:
  426. unum := uint64(num)
  427. if rvk == reflect.Uint8 && (num < 0 || unum > math.MaxUint8) ||
  428. rvk == reflect.Uint16 && (num < 0 || unum > math.MaxUint16) ||
  429. rvk == reflect.Uint32 && (num < 0 || unum > math.MaxUint32) {
  430. return md.parseErr(errParseRange{i: num, size: rvk.String()})
  431. }
  432. rv.SetUint(unum)
  433. default:
  434. panic("unreachable")
  435. }
  436. return nil
  437. }
  438. func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
  439. if b, ok := data.(bool); ok {
  440. rv.SetBool(b)
  441. return nil
  442. }
  443. return md.badtype("boolean", data)
  444. }
  445. func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
  446. rv.Set(reflect.ValueOf(data))
  447. return nil
  448. }
  449. func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error {
  450. var s string
  451. switch sdata := data.(type) {
  452. case Marshaler:
  453. text, err := sdata.MarshalTOML()
  454. if err != nil {
  455. return err
  456. }
  457. s = string(text)
  458. case encoding.TextMarshaler:
  459. text, err := sdata.MarshalText()
  460. if err != nil {
  461. return err
  462. }
  463. s = string(text)
  464. case fmt.Stringer:
  465. s = sdata.String()
  466. case string:
  467. s = sdata
  468. case bool:
  469. s = fmt.Sprintf("%v", sdata)
  470. case int64:
  471. s = fmt.Sprintf("%d", sdata)
  472. case float64:
  473. s = fmt.Sprintf("%f", sdata)
  474. default:
  475. return md.badtype("primitive (string-like)", data)
  476. }
  477. if err := v.UnmarshalText([]byte(s)); err != nil {
  478. return err
  479. }
  480. return nil
  481. }
  482. func (md *MetaData) badtype(dst string, data interface{}) error {
  483. return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst)
  484. }
  485. func (md *MetaData) parseErr(err error) error {
  486. k := md.context.String()
  487. return ParseError{
  488. LastKey: k,
  489. Position: md.keyInfo[k].pos,
  490. Line: md.keyInfo[k].pos.Line,
  491. err: err,
  492. input: string(md.data),
  493. }
  494. }
  495. func (md *MetaData) e(format string, args ...interface{}) error {
  496. f := "toml: "
  497. if len(md.context) > 0 {
  498. f = fmt.Sprintf("toml: (last key %q): ", md.context)
  499. p := md.keyInfo[md.context.String()].pos
  500. if p.Line > 0 {
  501. f = fmt.Sprintf("toml: line %d (last key %q): ", p.Line, md.context)
  502. }
  503. }
  504. return fmt.Errorf(f+format, args...)
  505. }
  506. // rvalue returns a reflect.Value of `v`. All pointers are resolved.
  507. func rvalue(v interface{}) reflect.Value {
  508. return indirect(reflect.ValueOf(v))
  509. }
  510. // indirect returns the value pointed to by a pointer.
  511. //
  512. // Pointers are followed until the value is not a pointer. New values are
  513. // allocated for each nil pointer.
  514. //
  515. // An exception to this rule is if the value satisfies an interface of interest
  516. // to us (like encoding.TextUnmarshaler).
  517. func indirect(v reflect.Value) reflect.Value {
  518. if v.Kind() != reflect.Ptr {
  519. if v.CanSet() {
  520. pv := v.Addr()
  521. pvi := pv.Interface()
  522. if _, ok := pvi.(encoding.TextUnmarshaler); ok {
  523. return pv
  524. }
  525. if _, ok := pvi.(Unmarshaler); ok {
  526. return pv
  527. }
  528. }
  529. return v
  530. }
  531. if v.IsNil() {
  532. v.Set(reflect.New(v.Type().Elem()))
  533. }
  534. return indirect(reflect.Indirect(v))
  535. }
  536. func isUnifiable(rv reflect.Value) bool {
  537. if rv.CanSet() {
  538. return true
  539. }
  540. rvi := rv.Interface()
  541. if _, ok := rvi.(encoding.TextUnmarshaler); ok {
  542. return true
  543. }
  544. if _, ok := rvi.(Unmarshaler); ok {
  545. return true
  546. }
  547. return false
  548. }