utils.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. package mapping
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "github.com/tal-tech/go-zero/core/stringx"
  12. )
  13. const (
  14. defaultOption = "default"
  15. stringOption = "string"
  16. optionalOption = "optional"
  17. optionsOption = "options"
  18. rangeOption = "range"
  19. optionSeparator = "|"
  20. equalToken = "="
  21. )
  22. var (
  23. errUnsupportedType = errors.New("unsupported type on setting field value")
  24. errNumberRange = errors.New("wrong number range setting")
  25. optionsCache = make(map[string]optionsCacheValue)
  26. cacheLock sync.RWMutex
  27. structRequiredCache = make(map[reflect.Type]requiredCacheValue)
  28. structCacheLock sync.RWMutex
  29. )
  30. type (
  31. optionsCacheValue struct {
  32. key string
  33. options *fieldOptions
  34. err error
  35. }
  36. requiredCacheValue struct {
  37. required bool
  38. err error
  39. }
  40. )
  41. func Deref(t reflect.Type) reflect.Type {
  42. if t.Kind() == reflect.Ptr {
  43. t = t.Elem()
  44. }
  45. return t
  46. }
  47. func Repr(v interface{}) string {
  48. if v == nil {
  49. return ""
  50. }
  51. // if func (v *Type) String() string, we can't use Elem()
  52. switch vt := v.(type) {
  53. case fmt.Stringer:
  54. return vt.String()
  55. }
  56. val := reflect.ValueOf(v)
  57. if val.Kind() == reflect.Ptr && !val.IsNil() {
  58. val = val.Elem()
  59. }
  60. return reprOfValue(val)
  61. }
  62. func ValidatePtr(v *reflect.Value) error {
  63. // sequence is very important, IsNil must be called after checking Kind() with reflect.Ptr,
  64. // panic otherwise
  65. if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
  66. return fmt.Errorf("not a valid pointer: %v", v)
  67. }
  68. return nil
  69. }
  70. func convertType(kind reflect.Kind, str string) (interface{}, error) {
  71. switch kind {
  72. case reflect.Bool:
  73. return str == "1" || strings.ToLower(str) == "true", nil
  74. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  75. intValue, err := strconv.ParseInt(str, 10, 64)
  76. if err != nil {
  77. return 0, fmt.Errorf("the value %q cannot parsed as int", str)
  78. }
  79. return intValue, nil
  80. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  81. uintValue, err := strconv.ParseUint(str, 10, 64)
  82. if err != nil {
  83. return 0, fmt.Errorf("the value %q cannot parsed as uint", str)
  84. }
  85. return uintValue, nil
  86. case reflect.Float32, reflect.Float64:
  87. floatValue, err := strconv.ParseFloat(str, 64)
  88. if err != nil {
  89. return 0, fmt.Errorf("the value %q cannot parsed as float", str)
  90. }
  91. return floatValue, nil
  92. case reflect.String:
  93. return str, nil
  94. default:
  95. return nil, errUnsupportedType
  96. }
  97. }
  98. func doParseKeyAndOptions(field reflect.StructField, value string) (string, *fieldOptions, error) {
  99. segments := strings.Split(value, ",")
  100. key := strings.TrimSpace(segments[0])
  101. options := segments[1:]
  102. if len(options) == 0 {
  103. return key, nil, nil
  104. }
  105. var fieldOpts fieldOptions
  106. for _, segment := range options {
  107. option := strings.TrimSpace(segment)
  108. if err := parseOption(&fieldOpts, field.Name, option); err != nil {
  109. return "", nil, err
  110. }
  111. }
  112. return key, &fieldOpts, nil
  113. }
  114. func implicitValueRequiredStruct(tag string, tp reflect.Type) (bool, error) {
  115. numFields := tp.NumField()
  116. for i := 0; i < numFields; i++ {
  117. childField := tp.Field(i)
  118. if usingDifferentKeys(tag, childField) {
  119. return true, nil
  120. }
  121. _, opts, err := parseKeyAndOptions(tag, childField)
  122. if err != nil {
  123. return false, err
  124. }
  125. if opts == nil {
  126. if childField.Type.Kind() != reflect.Struct {
  127. return true, nil
  128. }
  129. if required, err := implicitValueRequiredStruct(tag, childField.Type); err != nil {
  130. return false, err
  131. } else if required {
  132. return true, nil
  133. }
  134. } else if !opts.Optional && len(opts.Default) == 0 {
  135. return true, nil
  136. } else if len(opts.OptionalDep) > 0 && opts.OptionalDep[0] == notSymbol {
  137. return true, nil
  138. }
  139. }
  140. return false, nil
  141. }
  142. func maybeNewValue(field reflect.StructField, value reflect.Value) {
  143. if field.Type.Kind() == reflect.Ptr && value.IsNil() {
  144. value.Set(reflect.New(value.Type().Elem()))
  145. }
  146. }
  147. // don't modify returned fieldOptions, it's cached and shared among different calls.
  148. func parseKeyAndOptions(tagName string, field reflect.StructField) (string, *fieldOptions, error) {
  149. value := field.Tag.Get(tagName)
  150. if len(value) == 0 {
  151. return field.Name, nil, nil
  152. }
  153. cacheLock.RLock()
  154. cache, ok := optionsCache[value]
  155. cacheLock.RUnlock()
  156. if ok {
  157. return stringx.TakeOne(cache.key, field.Name), cache.options, cache.err
  158. }
  159. key, options, err := doParseKeyAndOptions(field, value)
  160. cacheLock.Lock()
  161. optionsCache[value] = optionsCacheValue{
  162. key: key,
  163. options: options,
  164. err: err,
  165. }
  166. cacheLock.Unlock()
  167. return stringx.TakeOne(key, field.Name), options, err
  168. }
  169. // support below notations:
  170. // [:5] (:5] [:5) (:5)
  171. // [1:] [1:) (1:] (1:)
  172. // [1:5] [1:5) (1:5] (1:5)
  173. func parseNumberRange(str string) (*numberRange, error) {
  174. if len(str) == 0 {
  175. return nil, errNumberRange
  176. }
  177. var leftInclude bool
  178. switch str[0] {
  179. case '[':
  180. leftInclude = true
  181. case '(':
  182. leftInclude = false
  183. default:
  184. return nil, errNumberRange
  185. }
  186. str = str[1:]
  187. if len(str) == 0 {
  188. return nil, errNumberRange
  189. }
  190. var rightInclude bool
  191. switch str[len(str)-1] {
  192. case ']':
  193. rightInclude = true
  194. case ')':
  195. rightInclude = false
  196. default:
  197. return nil, errNumberRange
  198. }
  199. str = str[:len(str)-1]
  200. fields := strings.Split(str, ":")
  201. if len(fields) != 2 {
  202. return nil, errNumberRange
  203. }
  204. if len(fields[0]) == 0 && len(fields[1]) == 0 {
  205. return nil, errNumberRange
  206. }
  207. var left float64
  208. if len(fields[0]) > 0 {
  209. var err error
  210. if left, err = strconv.ParseFloat(fields[0], 64); err != nil {
  211. return nil, err
  212. }
  213. } else {
  214. left = -math.MaxFloat64
  215. }
  216. var right float64
  217. if len(fields[1]) > 0 {
  218. var err error
  219. if right, err = strconv.ParseFloat(fields[1], 64); err != nil {
  220. return nil, err
  221. }
  222. } else {
  223. right = math.MaxFloat64
  224. }
  225. return &numberRange{
  226. left: left,
  227. leftInclude: leftInclude,
  228. right: right,
  229. rightInclude: rightInclude,
  230. }, nil
  231. }
  232. func parseOption(fieldOpts *fieldOptions, fieldName string, option string) error {
  233. switch {
  234. case option == stringOption:
  235. fieldOpts.FromString = true
  236. case strings.HasPrefix(option, optionalOption):
  237. segs := strings.Split(option, equalToken)
  238. switch len(segs) {
  239. case 1:
  240. fieldOpts.Optional = true
  241. case 2:
  242. fieldOpts.Optional = true
  243. fieldOpts.OptionalDep = segs[1]
  244. default:
  245. return fmt.Errorf("field %s has wrong optional", fieldName)
  246. }
  247. case option == optionalOption:
  248. fieldOpts.Optional = true
  249. case strings.HasPrefix(option, optionsOption):
  250. segs := strings.Split(option, equalToken)
  251. if len(segs) != 2 {
  252. return fmt.Errorf("field %s has wrong options", fieldName)
  253. }
  254. fieldOpts.Options = strings.Split(segs[1], optionSeparator)
  255. case strings.HasPrefix(option, defaultOption):
  256. segs := strings.Split(option, equalToken)
  257. if len(segs) != 2 {
  258. return fmt.Errorf("field %s has wrong default option", fieldName)
  259. }
  260. fieldOpts.Default = strings.TrimSpace(segs[1])
  261. case strings.HasPrefix(option, rangeOption):
  262. segs := strings.Split(option, equalToken)
  263. if len(segs) != 2 {
  264. return fmt.Errorf("field %s has wrong range", fieldName)
  265. }
  266. nr, err := parseNumberRange(segs[1])
  267. if err != nil {
  268. return err
  269. }
  270. fieldOpts.Range = nr
  271. }
  272. return nil
  273. }
  274. func reprOfValue(val reflect.Value) string {
  275. switch vt := val.Interface().(type) {
  276. case bool:
  277. return strconv.FormatBool(vt)
  278. case error:
  279. return vt.Error()
  280. case float32:
  281. return strconv.FormatFloat(float64(vt), 'f', -1, 32)
  282. case float64:
  283. return strconv.FormatFloat(vt, 'f', -1, 64)
  284. case fmt.Stringer:
  285. return vt.String()
  286. case int:
  287. return strconv.Itoa(vt)
  288. case int8:
  289. return strconv.Itoa(int(vt))
  290. case int16:
  291. return strconv.Itoa(int(vt))
  292. case int32:
  293. return strconv.Itoa(int(vt))
  294. case int64:
  295. return strconv.FormatInt(vt, 10)
  296. case string:
  297. return vt
  298. case uint:
  299. return strconv.FormatUint(uint64(vt), 10)
  300. case uint8:
  301. return strconv.FormatUint(uint64(vt), 10)
  302. case uint16:
  303. return strconv.FormatUint(uint64(vt), 10)
  304. case uint32:
  305. return strconv.FormatUint(uint64(vt), 10)
  306. case uint64:
  307. return strconv.FormatUint(vt, 10)
  308. case []byte:
  309. return string(vt)
  310. default:
  311. return fmt.Sprint(val.Interface())
  312. }
  313. }
  314. func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v interface{}) error {
  315. switch kind {
  316. case reflect.Bool:
  317. value.SetBool(v.(bool))
  318. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  319. value.SetInt(v.(int64))
  320. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  321. value.SetUint(v.(uint64))
  322. case reflect.Float32, reflect.Float64:
  323. value.SetFloat(v.(float64))
  324. case reflect.String:
  325. value.SetString(v.(string))
  326. default:
  327. return errUnsupportedType
  328. }
  329. return nil
  330. }
  331. func setValue(kind reflect.Kind, value reflect.Value, str string) error {
  332. if !value.CanSet() {
  333. return errValueNotSettable
  334. }
  335. v, err := convertType(kind, str)
  336. if err != nil {
  337. return err
  338. }
  339. return setMatchedPrimitiveValue(kind, value, v)
  340. }
  341. func structValueRequired(tag string, tp reflect.Type) (bool, error) {
  342. structCacheLock.RLock()
  343. val, ok := structRequiredCache[tp]
  344. structCacheLock.RUnlock()
  345. if ok {
  346. return val.required, val.err
  347. }
  348. required, err := implicitValueRequiredStruct(tag, tp)
  349. structCacheLock.Lock()
  350. structRequiredCache[tp] = requiredCacheValue{
  351. required: required,
  352. err: err,
  353. }
  354. structCacheLock.Unlock()
  355. return required, err
  356. }
  357. func toFloat64(v interface{}) (float64, bool) {
  358. switch val := v.(type) {
  359. case int:
  360. return float64(val), true
  361. case int8:
  362. return float64(val), true
  363. case int16:
  364. return float64(val), true
  365. case int32:
  366. return float64(val), true
  367. case int64:
  368. return float64(val), true
  369. case uint:
  370. return float64(val), true
  371. case uint8:
  372. return float64(val), true
  373. case uint16:
  374. return float64(val), true
  375. case uint32:
  376. return float64(val), true
  377. case uint64:
  378. return float64(val), true
  379. case float32:
  380. return float64(val), true
  381. case float64:
  382. return val, true
  383. default:
  384. return 0, false
  385. }
  386. }
  387. func usingDifferentKeys(key string, field reflect.StructField) bool {
  388. if len(field.Tag) > 0 {
  389. if _, ok := field.Tag.Lookup(key); !ok {
  390. return true
  391. }
  392. }
  393. return false
  394. }
  395. func validateAndSetValue(kind reflect.Kind, value reflect.Value, str string, opts *fieldOptionsWithContext) error {
  396. if !value.CanSet() {
  397. return errValueNotSettable
  398. }
  399. v, err := convertType(kind, str)
  400. if err != nil {
  401. return err
  402. }
  403. if err := validateValueRange(v, opts); err != nil {
  404. return err
  405. }
  406. return setMatchedPrimitiveValue(kind, value, v)
  407. }
  408. func validateJsonNumberRange(v json.Number, opts *fieldOptionsWithContext) error {
  409. if opts == nil || opts.Range == nil {
  410. return nil
  411. }
  412. fv, err := v.Float64()
  413. if err != nil {
  414. return err
  415. }
  416. return validateNumberRange(fv, opts.Range)
  417. }
  418. func validateNumberRange(fv float64, nr *numberRange) error {
  419. if nr == nil {
  420. return nil
  421. }
  422. if (nr.leftInclude && fv < nr.left) || (!nr.leftInclude && fv <= nr.left) {
  423. return errNumberRange
  424. }
  425. if (nr.rightInclude && fv > nr.right) || (!nr.rightInclude && fv >= nr.right) {
  426. return errNumberRange
  427. }
  428. return nil
  429. }
  430. func validateValueInOptions(options []string, value interface{}) error {
  431. if len(options) > 0 {
  432. switch v := value.(type) {
  433. case string:
  434. if !stringx.Contains(options, v) {
  435. return fmt.Errorf(`error: value "%s" is not defined in options "%v"`, v, options)
  436. }
  437. default:
  438. if !stringx.Contains(options, Repr(v)) {
  439. return fmt.Errorf(`error: value "%v" is not defined in options "%v"`, value, options)
  440. }
  441. }
  442. }
  443. return nil
  444. }
  445. func validateValueRange(mapValue interface{}, opts *fieldOptionsWithContext) error {
  446. if opts == nil || opts.Range == nil {
  447. return nil
  448. }
  449. fv, ok := toFloat64(mapValue)
  450. if !ok {
  451. return errNumberRange
  452. }
  453. return validateNumberRange(fv, opts.Range)
  454. }