decode.go 14 KB

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