decode.go 15 KB

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