utils.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  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/zeromicro/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. escapeChar = '\\'
  22. leftBracket = '('
  23. rightBracket = ')'
  24. leftSquareBracket = '['
  25. rightSquareBracket = ']'
  26. segmentSeparator = ','
  27. )
  28. var (
  29. errUnsupportedType = errors.New("unsupported type on setting field value")
  30. errNumberRange = errors.New("wrong number range setting")
  31. optionsCache = make(map[string]optionsCacheValue)
  32. cacheLock sync.RWMutex
  33. structRequiredCache = make(map[reflect.Type]requiredCacheValue)
  34. structCacheLock sync.RWMutex
  35. )
  36. type (
  37. optionsCacheValue struct {
  38. key string
  39. options *fieldOptions
  40. err error
  41. }
  42. requiredCacheValue struct {
  43. required bool
  44. err error
  45. }
  46. )
  47. // Deref dereferences a type, if pointer type, returns its element type.
  48. func Deref(t reflect.Type) reflect.Type {
  49. if t.Kind() == reflect.Ptr {
  50. t = t.Elem()
  51. }
  52. return t
  53. }
  54. // DerefVal dereferences a value, if pointer value nil set new a value, returns is not a ptr element value.
  55. func DerefVal(v reflect.Value) reflect.Value {
  56. for {
  57. if v.Kind() != reflect.Ptr {
  58. break
  59. }
  60. if v.IsNil() {
  61. v.Set(reflect.New(v.Type().Elem()))
  62. }
  63. v = v.Elem()
  64. }
  65. return v
  66. }
  67. // Repr returns the string representation of v.
  68. func Repr(v interface{}) string {
  69. if v == nil {
  70. return ""
  71. }
  72. // if func (v *Type) String() string, we can't use Elem()
  73. switch vt := v.(type) {
  74. case fmt.Stringer:
  75. return vt.String()
  76. }
  77. val := reflect.ValueOf(v)
  78. if val.Kind() == reflect.Ptr && !val.IsNil() {
  79. val = val.Elem()
  80. }
  81. return reprOfValue(val)
  82. }
  83. // ValidatePtr validates v if it's a valid pointer.
  84. func ValidatePtr(v *reflect.Value) error {
  85. // sequence is very important, IsNil must be called after checking Kind() with reflect.Ptr,
  86. // panic otherwise
  87. if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
  88. return fmt.Errorf("not a valid pointer: %v", v)
  89. }
  90. return nil
  91. }
  92. func convertType(kind reflect.Kind, str string) (interface{}, error) {
  93. switch kind {
  94. case reflect.Bool:
  95. return str == "1" || strings.ToLower(str) == "true", nil
  96. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  97. intValue, err := strconv.ParseInt(str, 10, 64)
  98. if err != nil {
  99. return 0, fmt.Errorf("the value %q cannot parsed as int", str)
  100. }
  101. return intValue, nil
  102. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  103. uintValue, err := strconv.ParseUint(str, 10, 64)
  104. if err != nil {
  105. return 0, fmt.Errorf("the value %q cannot parsed as uint", str)
  106. }
  107. return uintValue, nil
  108. case reflect.Float32, reflect.Float64:
  109. floatValue, err := strconv.ParseFloat(str, 64)
  110. if err != nil {
  111. return 0, fmt.Errorf("the value %q cannot parsed as float", str)
  112. }
  113. return floatValue, nil
  114. case reflect.String:
  115. return str, nil
  116. default:
  117. return nil, errUnsupportedType
  118. }
  119. }
  120. func doParseKeyAndOptions(field reflect.StructField, value string) (string, *fieldOptions, error) {
  121. segments := parseSegments(value)
  122. key := strings.TrimSpace(segments[0])
  123. options := segments[1:]
  124. if len(options) == 0 {
  125. return key, nil, nil
  126. }
  127. var fieldOpts fieldOptions
  128. for _, segment := range options {
  129. option := strings.TrimSpace(segment)
  130. if err := parseOption(&fieldOpts, field.Name, option); err != nil {
  131. return "", nil, err
  132. }
  133. }
  134. return key, &fieldOpts, nil
  135. }
  136. func implicitValueRequiredStruct(tag string, tp reflect.Type) (bool, error) {
  137. numFields := tp.NumField()
  138. for i := 0; i < numFields; i++ {
  139. childField := tp.Field(i)
  140. if usingDifferentKeys(tag, childField) {
  141. return true, nil
  142. }
  143. _, opts, err := parseKeyAndOptions(tag, childField)
  144. if err != nil {
  145. return false, err
  146. }
  147. if opts == nil {
  148. if childField.Type.Kind() != reflect.Struct {
  149. return true, nil
  150. }
  151. if required, err := implicitValueRequiredStruct(tag, childField.Type); err != nil {
  152. return false, err
  153. } else if required {
  154. return true, nil
  155. }
  156. } else if !opts.Optional && len(opts.Default) == 0 {
  157. return true, nil
  158. } else if len(opts.OptionalDep) > 0 && opts.OptionalDep[0] == notSymbol {
  159. return true, nil
  160. }
  161. }
  162. return false, nil
  163. }
  164. func isLeftInclude(b byte) (bool, error) {
  165. switch b {
  166. case '[':
  167. return true, nil
  168. case '(':
  169. return false, nil
  170. default:
  171. return false, errNumberRange
  172. }
  173. }
  174. func isRightInclude(b byte) (bool, error) {
  175. switch b {
  176. case ']':
  177. return true, nil
  178. case ')':
  179. return false, nil
  180. default:
  181. return false, errNumberRange
  182. }
  183. }
  184. func maybeNewValue(field reflect.StructField, value reflect.Value) {
  185. if field.Type.Kind() == reflect.Ptr && value.IsNil() {
  186. value.Set(reflect.New(value.Type().Elem()))
  187. }
  188. }
  189. func parseGroupedSegments(val string) []string {
  190. val = strings.TrimLeftFunc(val, func(r rune) bool {
  191. return r == leftBracket || r == leftSquareBracket
  192. })
  193. val = strings.TrimRightFunc(val, func(r rune) bool {
  194. return r == rightBracket || r == rightSquareBracket
  195. })
  196. return parseSegments(val)
  197. }
  198. // don't modify returned fieldOptions, it's cached and shared among different calls.
  199. func parseKeyAndOptions(tagName string, field reflect.StructField) (string, *fieldOptions, error) {
  200. value := field.Tag.Get(tagName)
  201. if len(value) == 0 {
  202. return field.Name, nil, nil
  203. }
  204. cacheLock.RLock()
  205. cache, ok := optionsCache[value]
  206. cacheLock.RUnlock()
  207. if ok {
  208. return stringx.TakeOne(cache.key, field.Name), cache.options, cache.err
  209. }
  210. key, options, err := doParseKeyAndOptions(field, value)
  211. cacheLock.Lock()
  212. optionsCache[value] = optionsCacheValue{
  213. key: key,
  214. options: options,
  215. err: err,
  216. }
  217. cacheLock.Unlock()
  218. return stringx.TakeOne(key, field.Name), options, err
  219. }
  220. // support below notations:
  221. // [:5] (:5] [:5) (:5)
  222. // [1:] [1:) (1:] (1:)
  223. // [1:5] [1:5) (1:5] (1:5)
  224. func parseNumberRange(str string) (*numberRange, error) {
  225. if len(str) == 0 {
  226. return nil, errNumberRange
  227. }
  228. leftInclude, err := isLeftInclude(str[0])
  229. if err != nil {
  230. return nil, err
  231. }
  232. str = str[1:]
  233. if len(str) == 0 {
  234. return nil, errNumberRange
  235. }
  236. rightInclude, err := isRightInclude(str[len(str)-1])
  237. if err != nil {
  238. return nil, err
  239. }
  240. str = str[:len(str)-1]
  241. fields := strings.Split(str, ":")
  242. if len(fields) != 2 {
  243. return nil, errNumberRange
  244. }
  245. if len(fields[0]) == 0 && len(fields[1]) == 0 {
  246. return nil, errNumberRange
  247. }
  248. var left float64
  249. if len(fields[0]) > 0 {
  250. var err error
  251. if left, err = strconv.ParseFloat(fields[0], 64); err != nil {
  252. return nil, err
  253. }
  254. } else {
  255. left = -math.MaxFloat64
  256. }
  257. var right float64
  258. if len(fields[1]) > 0 {
  259. var err error
  260. if right, err = strconv.ParseFloat(fields[1], 64); err != nil {
  261. return nil, err
  262. }
  263. } else {
  264. right = math.MaxFloat64
  265. }
  266. return &numberRange{
  267. left: left,
  268. leftInclude: leftInclude,
  269. right: right,
  270. rightInclude: rightInclude,
  271. }, nil
  272. }
  273. func parseOption(fieldOpts *fieldOptions, fieldName, option string) error {
  274. switch {
  275. case option == stringOption:
  276. fieldOpts.FromString = true
  277. case strings.HasPrefix(option, optionalOption):
  278. segs := strings.Split(option, equalToken)
  279. switch len(segs) {
  280. case 1:
  281. fieldOpts.Optional = true
  282. case 2:
  283. fieldOpts.Optional = true
  284. fieldOpts.OptionalDep = segs[1]
  285. default:
  286. return fmt.Errorf("field %s has wrong optional", fieldName)
  287. }
  288. case option == optionalOption:
  289. fieldOpts.Optional = true
  290. case strings.HasPrefix(option, optionsOption):
  291. segs := strings.Split(option, equalToken)
  292. if len(segs) != 2 {
  293. return fmt.Errorf("field %s has wrong options", fieldName)
  294. }
  295. fieldOpts.Options = parseOptions(segs[1])
  296. case strings.HasPrefix(option, defaultOption):
  297. segs := strings.Split(option, equalToken)
  298. if len(segs) != 2 {
  299. return fmt.Errorf("field %s has wrong default option", fieldName)
  300. }
  301. fieldOpts.Default = strings.TrimSpace(segs[1])
  302. case strings.HasPrefix(option, rangeOption):
  303. segs := strings.Split(option, equalToken)
  304. if len(segs) != 2 {
  305. return fmt.Errorf("field %s has wrong range", fieldName)
  306. }
  307. nr, err := parseNumberRange(segs[1])
  308. if err != nil {
  309. return err
  310. }
  311. fieldOpts.Range = nr
  312. }
  313. return nil
  314. }
  315. // parseOptions parses the given options in tag.
  316. // for example: `json:"name,options=foo|bar"` or `json:"name,options=[foo,bar]"`
  317. func parseOptions(val string) []string {
  318. if len(val) == 0 {
  319. return nil
  320. }
  321. if val[0] == leftSquareBracket {
  322. return parseGroupedSegments(val)
  323. }
  324. return strings.Split(val, optionSeparator)
  325. }
  326. func parseSegments(val string) []string {
  327. var segments []string
  328. var escaped, grouped bool
  329. var buf strings.Builder
  330. for _, ch := range val {
  331. if escaped {
  332. buf.WriteRune(ch)
  333. escaped = false
  334. continue
  335. }
  336. switch ch {
  337. case segmentSeparator:
  338. if grouped {
  339. buf.WriteRune(ch)
  340. } else {
  341. // need to trim spaces, but we cannot ignore empty string,
  342. // because the first segment stands for the key might be empty.
  343. // if ignored, the later tag will be used as the key.
  344. segments = append(segments, strings.TrimSpace(buf.String()))
  345. buf.Reset()
  346. }
  347. case escapeChar:
  348. if grouped {
  349. buf.WriteRune(ch)
  350. } else {
  351. escaped = true
  352. }
  353. case leftBracket, leftSquareBracket:
  354. buf.WriteRune(ch)
  355. grouped = true
  356. case rightBracket, rightSquareBracket:
  357. buf.WriteRune(ch)
  358. grouped = false
  359. default:
  360. buf.WriteRune(ch)
  361. }
  362. }
  363. last := strings.TrimSpace(buf.String())
  364. // ignore last empty string
  365. if len(last) > 0 {
  366. segments = append(segments, last)
  367. }
  368. return segments
  369. }
  370. func reprOfValue(val reflect.Value) string {
  371. switch vt := val.Interface().(type) {
  372. case bool:
  373. return strconv.FormatBool(vt)
  374. case error:
  375. return vt.Error()
  376. case float32:
  377. return strconv.FormatFloat(float64(vt), 'f', -1, 32)
  378. case float64:
  379. return strconv.FormatFloat(vt, 'f', -1, 64)
  380. case fmt.Stringer:
  381. return vt.String()
  382. case int:
  383. return strconv.Itoa(vt)
  384. case int8:
  385. return strconv.Itoa(int(vt))
  386. case int16:
  387. return strconv.Itoa(int(vt))
  388. case int32:
  389. return strconv.Itoa(int(vt))
  390. case int64:
  391. return strconv.FormatInt(vt, 10)
  392. case string:
  393. return vt
  394. case uint:
  395. return strconv.FormatUint(uint64(vt), 10)
  396. case uint8:
  397. return strconv.FormatUint(uint64(vt), 10)
  398. case uint16:
  399. return strconv.FormatUint(uint64(vt), 10)
  400. case uint32:
  401. return strconv.FormatUint(uint64(vt), 10)
  402. case uint64:
  403. return strconv.FormatUint(vt, 10)
  404. case []byte:
  405. return string(vt)
  406. default:
  407. return fmt.Sprint(val.Interface())
  408. }
  409. }
  410. func setMatchedPrimitiveValue(kind reflect.Kind, value reflect.Value, v interface{}) error {
  411. switch kind {
  412. case reflect.Bool:
  413. value.SetBool(v.(bool))
  414. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  415. value.SetInt(v.(int64))
  416. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  417. value.SetUint(v.(uint64))
  418. case reflect.Float32, reflect.Float64:
  419. value.SetFloat(v.(float64))
  420. case reflect.String:
  421. value.SetString(v.(string))
  422. default:
  423. return errUnsupportedType
  424. }
  425. return nil
  426. }
  427. func setValue(kind reflect.Kind, value reflect.Value, str string) error {
  428. if !value.CanSet() {
  429. return errValueNotSettable
  430. }
  431. value = DerefVal(value)
  432. v, err := convertType(kind, str)
  433. if err != nil {
  434. return err
  435. }
  436. return setMatchedPrimitiveValue(kind, value, v)
  437. }
  438. func structValueRequired(tag string, tp reflect.Type) (bool, error) {
  439. structCacheLock.RLock()
  440. val, ok := structRequiredCache[tp]
  441. structCacheLock.RUnlock()
  442. if ok {
  443. return val.required, val.err
  444. }
  445. required, err := implicitValueRequiredStruct(tag, tp)
  446. structCacheLock.Lock()
  447. structRequiredCache[tp] = requiredCacheValue{
  448. required: required,
  449. err: err,
  450. }
  451. structCacheLock.Unlock()
  452. return required, err
  453. }
  454. func toFloat64(v interface{}) (float64, bool) {
  455. switch val := v.(type) {
  456. case int:
  457. return float64(val), true
  458. case int8:
  459. return float64(val), true
  460. case int16:
  461. return float64(val), true
  462. case int32:
  463. return float64(val), true
  464. case int64:
  465. return float64(val), true
  466. case uint:
  467. return float64(val), true
  468. case uint8:
  469. return float64(val), true
  470. case uint16:
  471. return float64(val), true
  472. case uint32:
  473. return float64(val), true
  474. case uint64:
  475. return float64(val), true
  476. case float32:
  477. return float64(val), true
  478. case float64:
  479. return val, true
  480. default:
  481. return 0, false
  482. }
  483. }
  484. func usingDifferentKeys(key string, field reflect.StructField) bool {
  485. if len(field.Tag) > 0 {
  486. if _, ok := field.Tag.Lookup(key); !ok {
  487. return true
  488. }
  489. }
  490. return false
  491. }
  492. func validateAndSetValue(kind reflect.Kind, value reflect.Value, str string, opts *fieldOptionsWithContext) error {
  493. if !value.CanSet() {
  494. return errValueNotSettable
  495. }
  496. v, err := convertType(kind, str)
  497. if err != nil {
  498. return err
  499. }
  500. if err := validateValueRange(v, opts); err != nil {
  501. return err
  502. }
  503. return setMatchedPrimitiveValue(kind, value, v)
  504. }
  505. func validateJsonNumberRange(v json.Number, opts *fieldOptionsWithContext) error {
  506. if opts == nil || opts.Range == nil {
  507. return nil
  508. }
  509. fv, err := v.Float64()
  510. if err != nil {
  511. return err
  512. }
  513. return validateNumberRange(fv, opts.Range)
  514. }
  515. func validateNumberRange(fv float64, nr *numberRange) error {
  516. if nr == nil {
  517. return nil
  518. }
  519. if (nr.leftInclude && fv < nr.left) || (!nr.leftInclude && fv <= nr.left) {
  520. return errNumberRange
  521. }
  522. if (nr.rightInclude && fv > nr.right) || (!nr.rightInclude && fv >= nr.right) {
  523. return errNumberRange
  524. }
  525. return nil
  526. }
  527. func validateValueInOptions(val interface{}, options []string) error {
  528. if len(options) > 0 {
  529. switch v := val.(type) {
  530. case string:
  531. if !stringx.Contains(options, v) {
  532. return fmt.Errorf(`error: value "%s" is not defined in options "%v"`, v, options)
  533. }
  534. default:
  535. if !stringx.Contains(options, Repr(v)) {
  536. return fmt.Errorf(`error: value "%v" is not defined in options "%v"`, val, options)
  537. }
  538. }
  539. }
  540. return nil
  541. }
  542. func validateValueRange(mapValue interface{}, opts *fieldOptionsWithContext) error {
  543. if opts == nil || opts.Range == nil {
  544. return nil
  545. }
  546. fv, ok := toFloat64(mapValue)
  547. if !ok {
  548. return errNumberRange
  549. }
  550. return validateNumberRange(fv, opts.Range)
  551. }