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.

561 lines
15 KiB

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