decode.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // Package toml encodes and decodes the TOML configuration format using reflection.
  2. //
  3. // This library is compatible with TOML version v0.4.0.
  4. package toml
  5. import (
  6. "encoding"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "reflect"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "github.com/naoina/toml/ast"
  15. )
  16. const (
  17. tableSeparator = '.'
  18. )
  19. var (
  20. escapeReplacer = strings.NewReplacer(
  21. "\b", "\\n",
  22. "\f", "\\f",
  23. "\n", "\\n",
  24. "\r", "\\r",
  25. "\t", "\\t",
  26. )
  27. underscoreReplacer = strings.NewReplacer(
  28. "_", "",
  29. )
  30. )
  31. var timeType = reflect.TypeOf(time.Time{})
  32. // Unmarshal parses the TOML data and stores the result in the value pointed to by v.
  33. //
  34. // Unmarshal will mapped to v that according to following rules:
  35. //
  36. // TOML strings to string
  37. // TOML integers to any int type
  38. // TOML floats to float32 or float64
  39. // TOML booleans to bool
  40. // TOML datetimes to time.Time
  41. // TOML arrays to any type of slice
  42. // TOML tables to struct or map
  43. // TOML array tables to slice of struct or map
  44. func (cfg *Config) Unmarshal(data []byte, v interface{}) error {
  45. table, err := Parse(data)
  46. if err != nil {
  47. return err
  48. }
  49. if err := cfg.UnmarshalTable(table, v); err != nil {
  50. return err
  51. }
  52. return nil
  53. }
  54. // A Decoder reads and decodes TOML from an input stream.
  55. type Decoder struct {
  56. r io.Reader
  57. cfg *Config
  58. }
  59. // NewDecoder returns a new Decoder that reads from r.
  60. // Note that it reads all from r before parsing it.
  61. func (cfg *Config) NewDecoder(r io.Reader) *Decoder {
  62. return &Decoder{r, cfg}
  63. }
  64. // Decode parses the TOML data from its input and stores it in the value pointed to by v.
  65. // See the documentation for Unmarshal for details about the conversion of TOML into a Go value.
  66. func (d *Decoder) Decode(v interface{}) error {
  67. b, err := ioutil.ReadAll(d.r)
  68. if err != nil {
  69. return err
  70. }
  71. return d.cfg.Unmarshal(b, v)
  72. }
  73. // UnmarshalerRec may be implemented by types to customize their behavior when being
  74. // unmarshaled from TOML. You can use it to implement custom validation or to set
  75. // unexported fields.
  76. //
  77. // UnmarshalTOML receives a function that can be called to unmarshal the original TOML
  78. // value into a field or variable. It is safe to call the function more than once if
  79. // necessary.
  80. type UnmarshalerRec interface {
  81. UnmarshalTOML(fn func(interface{}) error) error
  82. }
  83. // Unmarshaler can be used to capture and process raw TOML source of a table or value.
  84. // UnmarshalTOML must copy the input if it wishes to retain it after returning.
  85. //
  86. // Note: this interface is retained for backwards compatibility. You probably want
  87. // to implement encoding.TextUnmarshaler or UnmarshalerRec instead.
  88. type Unmarshaler interface {
  89. UnmarshalTOML(input []byte) error
  90. }
  91. // UnmarshalTable applies the contents of an ast.Table to the value pointed at by v.
  92. //
  93. // UnmarshalTable will mapped to v that according to following rules:
  94. //
  95. // TOML strings to string
  96. // TOML integers to any int type
  97. // TOML floats to float32 or float64
  98. // TOML booleans to bool
  99. // TOML datetimes to time.Time
  100. // TOML arrays to any type of slice
  101. // TOML tables to struct or map
  102. // TOML array tables to slice of struct or map
  103. func (cfg *Config) UnmarshalTable(t *ast.Table, v interface{}) error {
  104. rv := reflect.ValueOf(v)
  105. toplevelMap := rv.Kind() == reflect.Map
  106. if (!toplevelMap && rv.Kind() != reflect.Ptr) || rv.IsNil() {
  107. return &invalidUnmarshalError{reflect.TypeOf(v)}
  108. }
  109. return unmarshalTable(cfg, rv, t, toplevelMap)
  110. }
  111. // used for UnmarshalerRec.
  112. func unmarshalTableOrValue(cfg *Config, rv reflect.Value, av interface{}) error {
  113. if (rv.Kind() != reflect.Ptr && rv.Kind() != reflect.Map) || rv.IsNil() {
  114. return &invalidUnmarshalError{rv.Type()}
  115. }
  116. rv = indirect(rv)
  117. switch av.(type) {
  118. case *ast.KeyValue, *ast.Table, []*ast.Table:
  119. if err := unmarshalField(cfg, rv, av); err != nil {
  120. return lineError(fieldLineNumber(av), err)
  121. }
  122. return nil
  123. case ast.Value:
  124. return setValue(cfg, rv, av.(ast.Value))
  125. default:
  126. panic(fmt.Sprintf("BUG: unhandled AST node type %T", av))
  127. }
  128. }
  129. // unmarshalTable unmarshals the fields of a table into a struct or map.
  130. //
  131. // toplevelMap is true when rv is an (unadressable) map given to UnmarshalTable. In this
  132. // (special) case, the map is used as-is instead of creating a new map.
  133. func unmarshalTable(cfg *Config, rv reflect.Value, t *ast.Table, toplevelMap bool) error {
  134. rv = indirect(rv)
  135. if err, ok := setUnmarshaler(cfg, rv, t); ok {
  136. return lineError(t.Line, err)
  137. }
  138. switch {
  139. case rv.Kind() == reflect.Struct:
  140. fc := makeFieldCache(cfg, rv.Type())
  141. for key, fieldAst := range t.Fields {
  142. fv, fieldName, err := fc.findField(cfg, rv, key)
  143. if err != nil {
  144. return lineError(fieldLineNumber(fieldAst), err)
  145. }
  146. if fv.IsValid() {
  147. if err := unmarshalField(cfg, fv, fieldAst); err != nil {
  148. return lineErrorField(fieldLineNumber(fieldAst), rv.Type().String()+"."+fieldName, err)
  149. }
  150. }
  151. }
  152. case rv.Kind() == reflect.Map || isEface(rv):
  153. m := rv
  154. if !toplevelMap {
  155. if rv.Kind() == reflect.Interface {
  156. m = reflect.ValueOf(make(map[string]interface{}))
  157. } else {
  158. m = reflect.MakeMap(rv.Type())
  159. }
  160. }
  161. elemtyp := m.Type().Elem()
  162. for key, fieldAst := range t.Fields {
  163. kv, err := unmarshalMapKey(m.Type().Key(), key)
  164. if err != nil {
  165. return lineError(fieldLineNumber(fieldAst), err)
  166. }
  167. fv := reflect.New(elemtyp).Elem()
  168. if err := unmarshalField(cfg, fv, fieldAst); err != nil {
  169. return lineError(fieldLineNumber(fieldAst), err)
  170. }
  171. m.SetMapIndex(kv, fv)
  172. }
  173. if !toplevelMap {
  174. rv.Set(m)
  175. }
  176. default:
  177. return lineError(t.Line, &unmarshalTypeError{"table", "struct or map", rv.Type()})
  178. }
  179. return nil
  180. }
  181. func fieldLineNumber(fieldAst interface{}) int {
  182. switch av := fieldAst.(type) {
  183. case *ast.KeyValue:
  184. return av.Line
  185. case *ast.Table:
  186. return av.Line
  187. case []*ast.Table:
  188. return av[0].Line
  189. default:
  190. panic(fmt.Sprintf("BUG: unhandled node type %T", fieldAst))
  191. }
  192. }
  193. func unmarshalField(cfg *Config, rv reflect.Value, fieldAst interface{}) error {
  194. switch av := fieldAst.(type) {
  195. case *ast.KeyValue:
  196. return setValue(cfg, rv, av.Value)
  197. case *ast.Table:
  198. return unmarshalTable(cfg, rv, av, false)
  199. case []*ast.Table:
  200. rv = indirect(rv)
  201. if err, ok := setUnmarshaler(cfg, rv, fieldAst); ok {
  202. return err
  203. }
  204. var slice reflect.Value
  205. switch {
  206. case rv.Kind() == reflect.Slice:
  207. slice = reflect.MakeSlice(rv.Type(), len(av), len(av))
  208. case isEface(rv):
  209. slice = reflect.ValueOf(make([]interface{}, len(av)))
  210. default:
  211. return &unmarshalTypeError{"array table", "slice", rv.Type()}
  212. }
  213. for i, tbl := range av {
  214. vv := reflect.New(slice.Type().Elem()).Elem()
  215. if err := unmarshalTable(cfg, vv, tbl, false); err != nil {
  216. return err
  217. }
  218. slice.Index(i).Set(vv)
  219. }
  220. rv.Set(slice)
  221. default:
  222. panic(fmt.Sprintf("BUG: unhandled AST node type %T", av))
  223. }
  224. return nil
  225. }
  226. func unmarshalMapKey(typ reflect.Type, key string) (reflect.Value, error) {
  227. rv := reflect.New(typ).Elem()
  228. if u, ok := rv.Addr().Interface().(encoding.TextUnmarshaler); ok {
  229. return rv, u.UnmarshalText([]byte(key))
  230. }
  231. switch typ.Kind() {
  232. case reflect.String:
  233. rv.SetString(key)
  234. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  235. i, err := strconv.ParseInt(key, 10, int(typ.Size()*8))
  236. if err != nil {
  237. return rv, convertNumError(typ.Kind(), err)
  238. }
  239. rv.SetInt(i)
  240. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  241. i, err := strconv.ParseUint(key, 10, int(typ.Size()*8))
  242. if err != nil {
  243. return rv, convertNumError(typ.Kind(), err)
  244. }
  245. rv.SetUint(i)
  246. default:
  247. return rv, fmt.Errorf("invalid map key type %s", typ)
  248. }
  249. return rv, nil
  250. }
  251. func setValue(cfg *Config, lhs reflect.Value, val ast.Value) error {
  252. lhs = indirect(lhs)
  253. if err, ok := setUnmarshaler(cfg, lhs, val); ok {
  254. return err
  255. }
  256. if err, ok := setTextUnmarshaler(lhs, val); ok {
  257. return err
  258. }
  259. switch v := val.(type) {
  260. case *ast.Integer:
  261. return setInt(lhs, v)
  262. case *ast.Float:
  263. return setFloat(lhs, v)
  264. case *ast.String:
  265. return setString(lhs, v)
  266. case *ast.Boolean:
  267. return setBoolean(lhs, v)
  268. case *ast.Datetime:
  269. return setDatetime(lhs, v)
  270. case *ast.Array:
  271. return setArray(cfg, lhs, v)
  272. default:
  273. panic(fmt.Sprintf("BUG: unhandled node type %T", v))
  274. }
  275. }
  276. func indirect(rv reflect.Value) reflect.Value {
  277. for rv.Kind() == reflect.Ptr {
  278. if rv.IsNil() {
  279. rv.Set(reflect.New(rv.Type().Elem()))
  280. }
  281. rv = rv.Elem()
  282. }
  283. return rv
  284. }
  285. func setUnmarshaler(cfg *Config, lhs reflect.Value, av interface{}) (error, bool) {
  286. if lhs.CanAddr() {
  287. if u, ok := lhs.Addr().Interface().(UnmarshalerRec); ok {
  288. err := u.UnmarshalTOML(func(v interface{}) error {
  289. return unmarshalTableOrValue(cfg, reflect.ValueOf(v), av)
  290. })
  291. return err, true
  292. }
  293. if u, ok := lhs.Addr().Interface().(Unmarshaler); ok {
  294. return u.UnmarshalTOML(unmarshalerSource(av)), true
  295. }
  296. }
  297. return nil, false
  298. }
  299. func unmarshalerSource(av interface{}) []byte {
  300. var source []byte
  301. switch av := av.(type) {
  302. case []*ast.Table:
  303. for i, tab := range av {
  304. source = append(source, tab.Source()...)
  305. if i != len(av)-1 {
  306. source = append(source, '\n')
  307. }
  308. }
  309. case ast.Value:
  310. source = []byte(av.Source())
  311. default:
  312. panic(fmt.Sprintf("BUG: unhandled node type %T", av))
  313. }
  314. return source
  315. }
  316. func setTextUnmarshaler(lhs reflect.Value, val ast.Value) (error, bool) {
  317. if !lhs.CanAddr() {
  318. return nil, false
  319. }
  320. u, ok := lhs.Addr().Interface().(encoding.TextUnmarshaler)
  321. if !ok || lhs.Type() == timeType {
  322. return nil, false
  323. }
  324. var data string
  325. switch val := val.(type) {
  326. case *ast.Array:
  327. return &unmarshalTypeError{"array", "", lhs.Type()}, true
  328. case *ast.String:
  329. data = val.Value
  330. default:
  331. data = val.Source()
  332. }
  333. return u.UnmarshalText([]byte(data)), true
  334. }
  335. func setInt(fv reflect.Value, v *ast.Integer) error {
  336. k := fv.Kind()
  337. switch {
  338. case k >= reflect.Int && k <= reflect.Int64:
  339. i, err := strconv.ParseInt(v.Value, 10, int(fv.Type().Size()*8))
  340. if err != nil {
  341. return convertNumError(fv.Kind(), err)
  342. }
  343. fv.SetInt(i)
  344. case k >= reflect.Uint && k <= reflect.Uintptr:
  345. i, err := strconv.ParseUint(v.Value, 10, int(fv.Type().Size()*8))
  346. if err != nil {
  347. return convertNumError(fv.Kind(), err)
  348. }
  349. fv.SetUint(i)
  350. case isEface(fv):
  351. i, err := strconv.ParseInt(v.Value, 10, 64)
  352. if err != nil {
  353. return convertNumError(reflect.Int64, err)
  354. }
  355. fv.Set(reflect.ValueOf(i))
  356. default:
  357. return &unmarshalTypeError{"integer", "", fv.Type()}
  358. }
  359. return nil
  360. }
  361. func setFloat(fv reflect.Value, v *ast.Float) error {
  362. f, err := v.Float()
  363. if err != nil {
  364. return err
  365. }
  366. switch {
  367. case fv.Kind() == reflect.Float32 || fv.Kind() == reflect.Float64:
  368. if fv.OverflowFloat(f) {
  369. return &overflowError{fv.Kind(), v.Value}
  370. }
  371. fv.SetFloat(f)
  372. case isEface(fv):
  373. fv.Set(reflect.ValueOf(f))
  374. default:
  375. return &unmarshalTypeError{"float", "", fv.Type()}
  376. }
  377. return nil
  378. }
  379. func setString(fv reflect.Value, v *ast.String) error {
  380. switch {
  381. case fv.Kind() == reflect.String:
  382. fv.SetString(v.Value)
  383. case isEface(fv):
  384. fv.Set(reflect.ValueOf(v.Value))
  385. default:
  386. return &unmarshalTypeError{"string", "", fv.Type()}
  387. }
  388. return nil
  389. }
  390. func setBoolean(fv reflect.Value, v *ast.Boolean) error {
  391. b, _ := v.Boolean()
  392. switch {
  393. case fv.Kind() == reflect.Bool:
  394. fv.SetBool(b)
  395. case isEface(fv):
  396. fv.Set(reflect.ValueOf(b))
  397. default:
  398. return &unmarshalTypeError{"boolean", "", fv.Type()}
  399. }
  400. return nil
  401. }
  402. func setDatetime(rv reflect.Value, v *ast.Datetime) error {
  403. t, err := v.Time()
  404. if err != nil {
  405. return err
  406. }
  407. if !timeType.AssignableTo(rv.Type()) {
  408. return &unmarshalTypeError{"datetime", "", rv.Type()}
  409. }
  410. rv.Set(reflect.ValueOf(t))
  411. return nil
  412. }
  413. func setArray(cfg *Config, rv reflect.Value, v *ast.Array) error {
  414. var slicetyp reflect.Type
  415. switch {
  416. case rv.Kind() == reflect.Slice:
  417. slicetyp = rv.Type()
  418. case isEface(rv):
  419. slicetyp = reflect.SliceOf(rv.Type())
  420. default:
  421. return &unmarshalTypeError{"array", "slice", rv.Type()}
  422. }
  423. if len(v.Value) == 0 {
  424. // Ensure defined slices are always set to a non-nil value.
  425. rv.Set(reflect.MakeSlice(slicetyp, 0, 0))
  426. return nil
  427. }
  428. tomltyp := reflect.TypeOf(v.Value[0])
  429. slice := reflect.MakeSlice(slicetyp, len(v.Value), len(v.Value))
  430. typ := slicetyp.Elem()
  431. for i, vv := range v.Value {
  432. if i > 0 && tomltyp != reflect.TypeOf(vv) {
  433. return errArrayMultiType
  434. }
  435. tmp := reflect.New(typ).Elem()
  436. if err := setValue(cfg, tmp, vv); err != nil {
  437. return err
  438. }
  439. slice.Index(i).Set(tmp)
  440. }
  441. rv.Set(slice)
  442. return nil
  443. }
  444. func isEface(rv reflect.Value) bool {
  445. return rv.Kind() == reflect.Interface && rv.Type().NumMethod() == 0
  446. }