setter.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. package ginutil
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "kpt-tmr-group/pkg/xerr"
  10. )
  11. var _ setter = camelFormSource(nil)
  12. var emptyField = reflect.StructField{}
  13. // setter tries to set value on a walking by fields of a struct
  14. type setter interface {
  15. TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error)
  16. }
  17. type setOptions struct {
  18. isDefaultExists bool
  19. defaultValue string
  20. }
  21. func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error {
  22. return mappingByPtr(ptr, camelFormSource(form), tag)
  23. }
  24. func mappingByPtr(ptr interface{}, setter setter, tag string) error {
  25. _, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag)
  26. return err
  27. }
  28. func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
  29. var vKind = value.Kind()
  30. if vKind == reflect.Ptr {
  31. var isNew bool
  32. vPtr := value
  33. if value.IsNil() {
  34. isNew = true
  35. vPtr = reflect.New(value.Type().Elem())
  36. }
  37. isSetted, err := mapping(vPtr.Elem(), field, setter, tag)
  38. if err != nil {
  39. return false, err
  40. }
  41. if isNew && isSetted {
  42. value.Set(vPtr)
  43. }
  44. return isSetted, nil
  45. }
  46. ok, err := tryToSetValue(value, field, setter, tag)
  47. if err != nil {
  48. return false, err
  49. }
  50. if ok {
  51. return true, nil
  52. }
  53. if vKind == reflect.Struct {
  54. tValue := value.Type()
  55. var isSetted bool
  56. for i := 0; i < value.NumField(); i++ {
  57. if !value.Field(i).CanSet() {
  58. continue
  59. }
  60. ok, err := mapping(value.Field(i), tValue.Field(i), setter, tag)
  61. if err != nil {
  62. return false, err
  63. }
  64. isSetted = isSetted || ok
  65. }
  66. return isSetted, nil
  67. }
  68. return false, nil
  69. }
  70. func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
  71. var tagValue string
  72. var setOpt setOptions
  73. tagValue = field.Tag.Get(tag)
  74. tagValue, opts := head(tagValue, ",")
  75. if tagValue == "-" { // just ignoring this field
  76. return false, nil
  77. }
  78. if tagValue == "" { // when field is "emptyField" variable
  79. return false, nil
  80. }
  81. var opt string
  82. for len(opts) > 0 {
  83. opt, opts = head(opts, ",")
  84. k, v := head(opt, "=")
  85. switch k {
  86. case "default":
  87. setOpt.isDefaultExists = true
  88. setOpt.defaultValue = v
  89. }
  90. }
  91. return setter.TrySet(value, field, tagValue, setOpt)
  92. }
  93. func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSetted bool, err error) {
  94. vs, ok := form[tagValue]
  95. if !ok && !opt.isDefaultExists {
  96. return false, nil
  97. }
  98. switch value.Kind() {
  99. case reflect.Slice:
  100. if !ok {
  101. vs = []string{opt.defaultValue}
  102. }
  103. return true, setSlice(vs, value, field)
  104. case reflect.Array:
  105. if !ok {
  106. vs = []string{opt.defaultValue}
  107. }
  108. if len(vs) != value.Len() {
  109. return false, xerr.Errorf("%q is not valid value for %s", vs, value.Type().String())
  110. }
  111. return true, setArray(vs, value, field)
  112. default:
  113. var val string
  114. if !ok {
  115. val = opt.defaultValue
  116. }
  117. if len(vs) > 0 {
  118. val = vs[0]
  119. }
  120. return true, setWithProperType(val, value, field)
  121. }
  122. }
  123. var errUnknownType = errors.New("unknown type")
  124. func setWithProperType(val string, value reflect.Value, field reflect.StructField) error {
  125. switch value.Kind() {
  126. case reflect.Int:
  127. return setIntField(val, 0, value)
  128. case reflect.Int8:
  129. return setIntField(val, 8, value)
  130. case reflect.Int16:
  131. return setIntField(val, 16, value)
  132. case reflect.Int32:
  133. return setIntField(val, 32, value)
  134. case reflect.Int64:
  135. switch value.Interface().(type) {
  136. case time.Duration:
  137. return setTimeDuration(val, value, field)
  138. }
  139. return setIntField(val, 64, value)
  140. case reflect.Uint:
  141. return setUintField(val, 0, value)
  142. case reflect.Uint8:
  143. return setUintField(val, 8, value)
  144. case reflect.Uint16:
  145. return setUintField(val, 16, value)
  146. case reflect.Uint32:
  147. return setUintField(val, 32, value)
  148. case reflect.Uint64:
  149. return setUintField(val, 64, value)
  150. case reflect.Bool:
  151. return setBoolField(val, value)
  152. case reflect.Float32:
  153. return setFloatField(val, 32, value)
  154. case reflect.Float64:
  155. return setFloatField(val, 64, value)
  156. case reflect.String:
  157. value.SetString(val)
  158. case reflect.Struct:
  159. switch value.Interface().(type) {
  160. case time.Time:
  161. return setTimeField(val, field, value)
  162. }
  163. return json.Unmarshal([]byte(val), value.Addr().Interface())
  164. case reflect.Map:
  165. return json.Unmarshal([]byte(val), value.Addr().Interface())
  166. default:
  167. return errUnknownType
  168. }
  169. return nil
  170. }
  171. func setIntField(val string, bitSize int, field reflect.Value) error {
  172. if val == "" {
  173. val = "0"
  174. }
  175. intVal, err := strconv.ParseInt(val, 10, bitSize)
  176. if err == nil {
  177. field.SetInt(intVal)
  178. }
  179. return xerr.WithStack(err)
  180. }
  181. func setUintField(val string, bitSize int, field reflect.Value) error {
  182. if val == "" {
  183. val = "0"
  184. }
  185. uintVal, err := strconv.ParseUint(val, 10, bitSize)
  186. if err == nil {
  187. field.SetUint(uintVal)
  188. }
  189. return xerr.WithStack(err)
  190. }
  191. func setBoolField(val string, field reflect.Value) error {
  192. if val == "" {
  193. val = "false"
  194. }
  195. boolVal, err := strconv.ParseBool(val)
  196. if err == nil {
  197. field.SetBool(boolVal)
  198. }
  199. return xerr.WithStack(err)
  200. }
  201. func setFloatField(val string, bitSize int, field reflect.Value) error {
  202. if val == "" {
  203. val = "0.0"
  204. }
  205. floatVal, err := strconv.ParseFloat(val, bitSize)
  206. if err == nil {
  207. field.SetFloat(floatVal)
  208. }
  209. return xerr.WithStack(err)
  210. }
  211. func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
  212. timeFormat := structField.Tag.Get("time_format")
  213. if timeFormat == "" {
  214. timeFormat = time.RFC3339
  215. }
  216. if val == "" {
  217. value.Set(reflect.ValueOf(time.Time{}))
  218. return nil
  219. }
  220. l := time.Local
  221. if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
  222. l = time.UTC
  223. }
  224. if locTag := structField.Tag.Get("time_location"); locTag != "" {
  225. loc, err := time.LoadLocation(locTag)
  226. if err != nil {
  227. return xerr.WithStack(err)
  228. }
  229. l = loc
  230. }
  231. var (
  232. t time.Time
  233. err error
  234. )
  235. if isTS, _ := strconv.ParseBool(structField.Tag.Get("time_ts")); isTS {
  236. sec, e := strconv.ParseInt(val, 10, 64)
  237. if e != nil {
  238. return xerr.WithStack(e)
  239. }
  240. t = time.Unix(sec, 0).In(l)
  241. } else {
  242. t, err = time.ParseInLocation(timeFormat, val, l)
  243. }
  244. if err != nil {
  245. return xerr.WithStack(err)
  246. }
  247. value.Set(reflect.ValueOf(t))
  248. return nil
  249. }
  250. // TODO: should support array case. eg. myArray[]=a&myArray[]=b
  251. func setArray(vals []string, value reflect.Value, field reflect.StructField) error {
  252. for i, s := range vals {
  253. err := setWithProperType(s, value.Index(i), field)
  254. if err != nil {
  255. return xerr.WithStack(err)
  256. }
  257. }
  258. return nil
  259. }
  260. func setSlice(vals []string, value reflect.Value, field reflect.StructField) error {
  261. slice := reflect.MakeSlice(value.Type(), len(vals), len(vals))
  262. err := setArray(vals, slice, field)
  263. if err != nil {
  264. return xerr.WithStack(err)
  265. }
  266. value.Set(slice)
  267. return nil
  268. }
  269. func setTimeDuration(val string, value reflect.Value, _ reflect.StructField) error {
  270. d, err := time.ParseDuration(val)
  271. if err != nil {
  272. return xerr.WithStack(err)
  273. }
  274. value.Set(reflect.ValueOf(d))
  275. return nil
  276. }
  277. func head(str, sep string) (head string, tail string) {
  278. idx := strings.Index(str, sep)
  279. if idx < 0 {
  280. return str, ""
  281. }
  282. return str[:idx], str[idx+len(sep):]
  283. }