toml.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. package paladin
  2. import (
  3. "reflect"
  4. "strconv"
  5. "github.com/naoina/toml"
  6. "github.com/pkg/errors"
  7. )
  8. // TOML is toml map.
  9. type TOML = Map
  10. // Set set the map by value.
  11. func (m *TOML) Set(text string) error {
  12. if err := m.UnmarshalText([]byte(text)); err != nil {
  13. return err
  14. }
  15. return nil
  16. }
  17. // UnmarshalText implemented toml.
  18. func (m *TOML) UnmarshalText(text []byte) error {
  19. raws := map[string]interface{}{}
  20. if err := toml.Unmarshal(text, &raws); err != nil {
  21. return err
  22. }
  23. values := map[string]*Value{}
  24. for k, v := range raws {
  25. k = keyNamed(k)
  26. rv := reflect.ValueOf(v)
  27. switch rv.Kind() {
  28. case reflect.Map:
  29. b, err := toml.Marshal(v)
  30. if err != nil {
  31. return err
  32. }
  33. // NOTE: value is map[string]interface{}
  34. values[k] = &Value{val: v, raw: string(b)}
  35. case reflect.Slice:
  36. raw := map[string]interface{}{
  37. k: v,
  38. }
  39. b, err := toml.Marshal(raw)
  40. if err != nil {
  41. return err
  42. }
  43. // NOTE: value is []interface{}
  44. values[k] = &Value{val: v, raw: string(b)}
  45. case reflect.Bool:
  46. b := v.(bool)
  47. values[k] = &Value{val: b, raw: strconv.FormatBool(b)}
  48. case reflect.Int64:
  49. i := v.(int64)
  50. values[k] = &Value{val: i, raw: strconv.FormatInt(i, 10)}
  51. case reflect.Float64:
  52. f := v.(float64)
  53. values[k] = &Value{val: f, raw: strconv.FormatFloat(f, 'f', -1, 64)}
  54. case reflect.String:
  55. s := v.(string)
  56. values[k] = &Value{val: s, raw: s}
  57. default:
  58. return errors.Errorf("UnmarshalTOML: unknown kind(%v)", rv.Kind())
  59. }
  60. }
  61. m.Store(values)
  62. return nil
  63. }