本站源代码
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.

510 lines
14KB

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