marshaler.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package mapping
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. )
  7. const (
  8. emptyTag = ""
  9. tagKVSeparator = ":"
  10. )
  11. // Marshal marshals the given val and returns the map that contains the fields.
  12. // optional=another is not implemented, and it's hard to implement and not common used.
  13. func Marshal(val interface{}) (map[string]map[string]interface{}, error) {
  14. ret := make(map[string]map[string]interface{})
  15. tp := reflect.TypeOf(val)
  16. rv := reflect.ValueOf(val)
  17. for i := 0; i < tp.NumField(); i++ {
  18. field := tp.Field(i)
  19. value := rv.Field(i)
  20. if err := processMember(field, value, ret); err != nil {
  21. return nil, err
  22. }
  23. }
  24. return ret, nil
  25. }
  26. func getTag(field reflect.StructField) (string, bool) {
  27. tag := string(field.Tag)
  28. if i := strings.Index(tag, tagKVSeparator); i >= 0 {
  29. return strings.TrimSpace(tag[:i]), true
  30. }
  31. return strings.TrimSpace(tag), false
  32. }
  33. func processMember(field reflect.StructField, value reflect.Value,
  34. collector map[string]map[string]interface{}) error {
  35. var key string
  36. var opt *fieldOptions
  37. var err error
  38. tag, ok := getTag(field)
  39. if !ok {
  40. tag = emptyTag
  41. key = field.Name
  42. } else {
  43. key, opt, err = parseKeyAndOptions(tag, field)
  44. if err != nil {
  45. return err
  46. }
  47. if err = validate(field, value, opt); err != nil {
  48. return err
  49. }
  50. }
  51. val := value.Interface()
  52. if opt != nil && opt.FromString {
  53. val = fmt.Sprint(val)
  54. }
  55. m, ok := collector[tag]
  56. if ok {
  57. m[key] = val
  58. } else {
  59. m = map[string]interface{}{
  60. key: val,
  61. }
  62. }
  63. collector[tag] = m
  64. return nil
  65. }
  66. func validate(field reflect.StructField, value reflect.Value, opt *fieldOptions) error {
  67. if opt == nil || !opt.Optional {
  68. if err := validateOptional(field, value); err != nil {
  69. return err
  70. }
  71. }
  72. if opt == nil {
  73. return nil
  74. }
  75. if len(opt.Options) > 0 {
  76. if err := validateOptions(value, opt); err != nil {
  77. return err
  78. }
  79. }
  80. if opt.Range != nil {
  81. if err := validateRange(value, opt); err != nil {
  82. return err
  83. }
  84. }
  85. return nil
  86. }
  87. func validateOptional(field reflect.StructField, value reflect.Value) error {
  88. switch field.Type.Kind() {
  89. case reflect.Ptr:
  90. if value.IsNil() {
  91. return fmt.Errorf("field %q is nil", field.Name)
  92. }
  93. case reflect.Array, reflect.Slice, reflect.Map:
  94. if value.IsNil() || value.Len() == 0 {
  95. return fmt.Errorf("field %q is empty", field.Name)
  96. }
  97. }
  98. return nil
  99. }
  100. func validateOptions(value reflect.Value, opt *fieldOptions) error {
  101. var found bool
  102. val := fmt.Sprint(value.Interface())
  103. for i := range opt.Options {
  104. if opt.Options[i] == val {
  105. found = true
  106. break
  107. }
  108. }
  109. if !found {
  110. return fmt.Errorf("field %q not in options", val)
  111. }
  112. return nil
  113. }
  114. func validateRange(value reflect.Value, opt *fieldOptions) error {
  115. var val float64
  116. switch v := value.Interface().(type) {
  117. case int:
  118. val = float64(v)
  119. case int8:
  120. val = float64(v)
  121. case int16:
  122. val = float64(v)
  123. case int32:
  124. val = float64(v)
  125. case int64:
  126. val = float64(v)
  127. case uint:
  128. val = float64(v)
  129. case uint8:
  130. val = float64(v)
  131. case uint16:
  132. val = float64(v)
  133. case uint32:
  134. val = float64(v)
  135. case uint64:
  136. val = float64(v)
  137. case float32:
  138. val = float64(v)
  139. case float64:
  140. val = v
  141. default:
  142. return fmt.Errorf("unknown support type for range %q", value.Type().String())
  143. }
  144. // validates [left, right], [left, right), (left, right], (left, right)
  145. if val < opt.Range.left ||
  146. (!opt.Range.leftInclude && val == opt.Range.left) ||
  147. val > opt.Range.right ||
  148. (!opt.Range.rightInclude && val == opt.Range.right) {
  149. return fmt.Errorf("%v out of range", value.Interface())
  150. }
  151. return nil
  152. }