decode.go 14 KB

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