value.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package paladin
  2. import (
  3. "encoding"
  4. "reflect"
  5. "time"
  6. "github.com/BurntSushi/toml"
  7. "github.com/pkg/errors"
  8. )
  9. // ErrNotExist value key not exist.
  10. var (
  11. ErrNotExist = errors.New("paladin: value key not exist")
  12. ErrTypeAssertion = errors.New("paladin: value type assertion no match")
  13. ErrDifferentTypes = errors.New("paladin: value different types")
  14. )
  15. // Value is config value, maybe a json/toml/ini/string file.
  16. type Value struct {
  17. val interface{}
  18. slice interface{}
  19. raw string
  20. }
  21. // Bool return bool value.
  22. func (v *Value) Bool() (bool, error) {
  23. if v.val == nil {
  24. return false, ErrNotExist
  25. }
  26. b, ok := v.val.(bool)
  27. if !ok {
  28. return false, ErrTypeAssertion
  29. }
  30. return b, nil
  31. }
  32. // Int return int value.
  33. func (v *Value) Int() (int, error) {
  34. i, err := v.Int64()
  35. if err != nil {
  36. return 0, nil
  37. }
  38. return int(i), nil
  39. }
  40. // Int32 return int32 value.
  41. func (v *Value) Int32() (int32, error) {
  42. i, err := v.Int64()
  43. if err != nil {
  44. return 0, nil
  45. }
  46. return int32(i), nil
  47. }
  48. // Int64 return int64 value.
  49. func (v *Value) Int64() (int64, error) {
  50. if v.val == nil {
  51. return 0, ErrNotExist
  52. }
  53. i, ok := v.val.(int64)
  54. if !ok {
  55. return 0, ErrTypeAssertion
  56. }
  57. return i, nil
  58. }
  59. // Float32 return float32 value.
  60. func (v *Value) Float32() (float32, error) {
  61. f, err := v.Float64()
  62. if err != nil {
  63. return 0.0, err
  64. }
  65. return float32(f), nil
  66. }
  67. // Float64 return float64 value.
  68. func (v *Value) Float64() (float64, error) {
  69. if v.val == nil {
  70. return 0.0, ErrNotExist
  71. }
  72. f, ok := v.val.(float64)
  73. if !ok {
  74. return 0.0, ErrTypeAssertion
  75. }
  76. return f, nil
  77. }
  78. // String return string value.
  79. func (v *Value) String() (string, error) {
  80. if v.val == nil {
  81. return "", ErrNotExist
  82. }
  83. s, ok := v.val.(string)
  84. if !ok {
  85. return "", ErrTypeAssertion
  86. }
  87. return s, nil
  88. }
  89. // Duration parses a duration string. A duration string is a possibly signed sequence of decimal numbers
  90. // each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
  91. func (v *Value) Duration() (time.Duration, error) {
  92. s, err := v.String()
  93. if err != nil {
  94. return time.Duration(0), err
  95. }
  96. return time.ParseDuration(s)
  97. }
  98. // Raw return raw value.
  99. func (v *Value) Raw() (string, error) {
  100. if v.val == nil {
  101. return "", ErrNotExist
  102. }
  103. return v.raw, nil
  104. }
  105. // Slice scan a slcie interface.
  106. func (v *Value) Slice(dst interface{}) error {
  107. // NOTE: val is []interface{}, slice is []type
  108. if v.val == nil {
  109. return ErrNotExist
  110. }
  111. rv := reflect.ValueOf(dst)
  112. if rv.Kind() != reflect.Ptr || rv.Elem().Kind() != reflect.Slice {
  113. return ErrDifferentTypes
  114. }
  115. el := rv.Elem()
  116. kind := el.Type().Elem().Kind()
  117. if v.slice == nil {
  118. src, ok := v.val.([]interface{})
  119. if !ok {
  120. return ErrDifferentTypes
  121. }
  122. for _, s := range src {
  123. if reflect.TypeOf(s).Kind() != kind {
  124. return ErrTypeAssertion
  125. }
  126. el = reflect.Append(el, reflect.ValueOf(s))
  127. }
  128. v.slice = el.Interface()
  129. rv.Elem().Set(el)
  130. return nil
  131. }
  132. sv := reflect.ValueOf(v.slice)
  133. if sv.Type().Elem().Kind() != kind {
  134. return ErrTypeAssertion
  135. }
  136. rv.Elem().Set(sv)
  137. return nil
  138. }
  139. // Unmarshal is the interface implemented by an object that can unmarshal a textual representation of itself.
  140. func (v *Value) Unmarshal(un encoding.TextUnmarshaler) error {
  141. text, err := v.Raw()
  142. if err != nil {
  143. return err
  144. }
  145. return un.UnmarshalText([]byte(text))
  146. }
  147. // UnmarshalTOML unmarhsal toml to struct.
  148. func (v *Value) UnmarshalTOML(dst interface{}) error {
  149. text, err := v.Raw()
  150. if err != nil {
  151. return err
  152. }
  153. return toml.Unmarshal([]byte(text), dst)
  154. }