structure.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. package structure
  2. // references: https://github.com/mitchellh/mapstructure
  3. import (
  4. "encoding/base64"
  5. "fmt"
  6. "reflect"
  7. "strconv"
  8. "strings"
  9. )
  10. // Option is the configuration that is used to create a new decoder
  11. type Option struct {
  12. TagName string
  13. WeaklyTypedInput bool
  14. KeyReplacer *strings.Replacer
  15. }
  16. var DefaultKeyReplacer = strings.NewReplacer("_", "-")
  17. // Decoder is the core of structure
  18. type Decoder struct {
  19. option *Option
  20. }
  21. // NewDecoder return a Decoder by Option
  22. func NewDecoder(option Option) *Decoder {
  23. if option.TagName == "" {
  24. option.TagName = "structure"
  25. }
  26. return &Decoder{option: &option}
  27. }
  28. // Decode transform a map[string]any to a struct
  29. func (d *Decoder) Decode(src map[string]any, dst any) error {
  30. if reflect.TypeOf(dst).Kind() != reflect.Ptr {
  31. return fmt.Errorf("decode must recive a ptr struct")
  32. }
  33. t := reflect.TypeOf(dst).Elem()
  34. v := reflect.ValueOf(dst).Elem()
  35. for idx := 0; idx < v.NumField(); idx++ {
  36. field := t.Field(idx)
  37. if field.Anonymous {
  38. if err := d.decodeStruct(field.Name, src, v.Field(idx)); err != nil {
  39. return err
  40. }
  41. continue
  42. }
  43. tag := field.Tag.Get(d.option.TagName)
  44. key, omitKey, found := strings.Cut(tag, ",")
  45. omitempty := found && omitKey == "omitempty"
  46. value, ok := src[key]
  47. if !ok {
  48. if d.option.KeyReplacer != nil {
  49. key = d.option.KeyReplacer.Replace(key)
  50. }
  51. for _strKey := range src {
  52. strKey := _strKey
  53. if d.option.KeyReplacer != nil {
  54. strKey = d.option.KeyReplacer.Replace(strKey)
  55. }
  56. if strings.EqualFold(key, strKey) {
  57. value = src[_strKey]
  58. ok = true
  59. break
  60. }
  61. }
  62. }
  63. if !ok || value == nil {
  64. if omitempty {
  65. continue
  66. }
  67. return fmt.Errorf("key '%s' missing", key)
  68. }
  69. err := d.decode(key, value, v.Field(idx))
  70. if err != nil {
  71. return err
  72. }
  73. }
  74. return nil
  75. }
  76. func (d *Decoder) decode(name string, data any, val reflect.Value) error {
  77. kind := val.Kind()
  78. switch {
  79. case isInt(kind):
  80. return d.decodeInt(name, data, val)
  81. case isUint(kind):
  82. return d.decodeUint(name, data, val)
  83. case isFloat(kind):
  84. return d.decodeFloat(name, data, val)
  85. }
  86. switch kind {
  87. case reflect.Pointer:
  88. if val.IsNil() {
  89. val.Set(reflect.New(val.Type().Elem()))
  90. }
  91. return d.decode(name, data, val.Elem())
  92. case reflect.String:
  93. return d.decodeString(name, data, val)
  94. case reflect.Bool:
  95. return d.decodeBool(name, data, val)
  96. case reflect.Slice:
  97. return d.decodeSlice(name, data, val)
  98. case reflect.Map:
  99. return d.decodeMap(name, data, val)
  100. case reflect.Interface:
  101. return d.setInterface(name, data, val)
  102. case reflect.Struct:
  103. return d.decodeStruct(name, data, val)
  104. default:
  105. return fmt.Errorf("type %s not support", val.Kind().String())
  106. }
  107. }
  108. func isInt(kind reflect.Kind) bool {
  109. switch kind {
  110. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  111. return true
  112. default:
  113. return false
  114. }
  115. }
  116. func isUint(kind reflect.Kind) bool {
  117. switch kind {
  118. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  119. return true
  120. default:
  121. return false
  122. }
  123. }
  124. func isFloat(kind reflect.Kind) bool {
  125. switch kind {
  126. case reflect.Float32, reflect.Float64:
  127. return true
  128. default:
  129. return false
  130. }
  131. }
  132. func (d *Decoder) decodeInt(name string, data any, val reflect.Value) (err error) {
  133. dataVal := reflect.ValueOf(data)
  134. kind := dataVal.Kind()
  135. switch {
  136. case isInt(kind):
  137. val.SetInt(dataVal.Int())
  138. case isUint(kind) && d.option.WeaklyTypedInput:
  139. val.SetInt(int64(dataVal.Uint()))
  140. case isFloat(kind) && d.option.WeaklyTypedInput:
  141. val.SetInt(int64(dataVal.Float()))
  142. case kind == reflect.String && d.option.WeaklyTypedInput:
  143. var i int64
  144. i, err = strconv.ParseInt(dataVal.String(), 0, val.Type().Bits())
  145. if err == nil {
  146. val.SetInt(i)
  147. } else {
  148. err = fmt.Errorf("cannot parse '%s' as int: %s", name, err)
  149. }
  150. default:
  151. err = fmt.Errorf(
  152. "'%s' expected type '%s', got unconvertible type '%s'",
  153. name, val.Type(), dataVal.Type(),
  154. )
  155. }
  156. return err
  157. }
  158. func (d *Decoder) decodeUint(name string, data any, val reflect.Value) (err error) {
  159. dataVal := reflect.ValueOf(data)
  160. kind := dataVal.Kind()
  161. switch {
  162. case isUint(kind):
  163. val.SetUint(dataVal.Uint())
  164. case isInt(kind) && d.option.WeaklyTypedInput:
  165. val.SetUint(uint64(dataVal.Int()))
  166. case isFloat(kind) && d.option.WeaklyTypedInput:
  167. val.SetUint(uint64(dataVal.Float()))
  168. case kind == reflect.String && d.option.WeaklyTypedInput:
  169. var i uint64
  170. i, err = strconv.ParseUint(dataVal.String(), 0, val.Type().Bits())
  171. if err == nil {
  172. val.SetUint(i)
  173. } else {
  174. err = fmt.Errorf("cannot parse '%s' as int: %s", name, err)
  175. }
  176. default:
  177. err = fmt.Errorf(
  178. "'%s' expected type '%s', got unconvertible type '%s'",
  179. name, val.Type(), dataVal.Type(),
  180. )
  181. }
  182. return err
  183. }
  184. func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) (err error) {
  185. dataVal := reflect.ValueOf(data)
  186. kind := dataVal.Kind()
  187. switch {
  188. case isFloat(kind):
  189. val.SetFloat(dataVal.Float())
  190. case isUint(kind):
  191. val.SetFloat(float64(dataVal.Uint()))
  192. case isInt(kind) && d.option.WeaklyTypedInput:
  193. val.SetFloat(float64(dataVal.Int()))
  194. case kind == reflect.String && d.option.WeaklyTypedInput:
  195. var i float64
  196. i, err = strconv.ParseFloat(dataVal.String(), val.Type().Bits())
  197. if err == nil {
  198. val.SetFloat(i)
  199. } else {
  200. err = fmt.Errorf("cannot parse '%s' as int: %s", name, err)
  201. }
  202. default:
  203. err = fmt.Errorf(
  204. "'%s' expected type '%s', got unconvertible type '%s'",
  205. name, val.Type(), dataVal.Type(),
  206. )
  207. }
  208. return err
  209. }
  210. func (d *Decoder) decodeString(name string, data any, val reflect.Value) (err error) {
  211. dataVal := reflect.ValueOf(data)
  212. kind := dataVal.Kind()
  213. switch {
  214. case kind == reflect.String:
  215. val.SetString(dataVal.String())
  216. case isInt(kind) && d.option.WeaklyTypedInput:
  217. val.SetString(strconv.FormatInt(dataVal.Int(), 10))
  218. case isUint(kind) && d.option.WeaklyTypedInput:
  219. val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
  220. case isFloat(kind) && d.option.WeaklyTypedInput:
  221. val.SetString(strconv.FormatFloat(dataVal.Float(), 'E', -1, dataVal.Type().Bits()))
  222. default:
  223. err = fmt.Errorf(
  224. "'%s' expected type '%s', got unconvertible type '%s'",
  225. name, val.Type(), dataVal.Type(),
  226. )
  227. }
  228. return err
  229. }
  230. func (d *Decoder) decodeBool(name string, data any, val reflect.Value) (err error) {
  231. dataVal := reflect.ValueOf(data)
  232. kind := dataVal.Kind()
  233. switch {
  234. case kind == reflect.Bool:
  235. val.SetBool(dataVal.Bool())
  236. case isInt(kind) && d.option.WeaklyTypedInput:
  237. val.SetBool(dataVal.Int() != 0)
  238. case isUint(kind) && d.option.WeaklyTypedInput:
  239. val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
  240. default:
  241. err = fmt.Errorf(
  242. "'%s' expected type '%s', got unconvertible type '%s'",
  243. name, val.Type(), dataVal.Type(),
  244. )
  245. }
  246. return err
  247. }
  248. func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
  249. dataVal := reflect.Indirect(reflect.ValueOf(data))
  250. valType := val.Type()
  251. valElemType := valType.Elem()
  252. if dataVal.Kind() == reflect.String && valElemType.Kind() == reflect.Uint8 { // from encoding/json
  253. s := []byte(dataVal.String())
  254. b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
  255. n, err := base64.StdEncoding.Decode(b, s)
  256. if err != nil {
  257. return fmt.Errorf("try decode '%s' by base64 error: %w", name, err)
  258. }
  259. val.SetBytes(b[:n])
  260. return nil
  261. }
  262. if dataVal.Kind() != reflect.Slice {
  263. return fmt.Errorf("'%s' is not a slice", name)
  264. }
  265. valSlice := val
  266. // make a new slice with cap(val)==cap(dataVal)
  267. // the caller can determine whether the original configuration contains this item by judging whether the value is nil.
  268. valSlice = reflect.MakeSlice(valType, 0, dataVal.Len())
  269. for i := 0; i < dataVal.Len(); i++ {
  270. currentData := dataVal.Index(i).Interface()
  271. for valSlice.Len() <= i {
  272. valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
  273. }
  274. fieldName := fmt.Sprintf("%s[%d]", name, i)
  275. if currentData == nil {
  276. // in weakly type mode, null will convert to zero value
  277. if d.option.WeaklyTypedInput {
  278. continue
  279. }
  280. // in non-weakly type mode, null will convert to nil if element's zero value is nil, otherwise return an error
  281. if elemKind := valElemType.Kind(); elemKind == reflect.Map || elemKind == reflect.Slice {
  282. continue
  283. }
  284. return fmt.Errorf("'%s' can not be null", fieldName)
  285. }
  286. currentField := valSlice.Index(i)
  287. if err := d.decode(fieldName, currentData, currentField); err != nil {
  288. return err
  289. }
  290. }
  291. val.Set(valSlice)
  292. return nil
  293. }
  294. func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
  295. valType := val.Type()
  296. valKeyType := valType.Key()
  297. valElemType := valType.Elem()
  298. valMap := val
  299. if valMap.IsNil() {
  300. mapType := reflect.MapOf(valKeyType, valElemType)
  301. valMap = reflect.MakeMap(mapType)
  302. }
  303. dataVal := reflect.Indirect(reflect.ValueOf(data))
  304. if dataVal.Kind() != reflect.Map {
  305. return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
  306. }
  307. return d.decodeMapFromMap(name, dataVal, val, valMap)
  308. }
  309. func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error {
  310. valType := val.Type()
  311. valKeyType := valType.Key()
  312. valElemType := valType.Elem()
  313. errors := make([]string, 0)
  314. if dataVal.Len() == 0 {
  315. if dataVal.IsNil() {
  316. if !val.IsNil() {
  317. val.Set(dataVal)
  318. }
  319. } else {
  320. val.Set(valMap)
  321. }
  322. return nil
  323. }
  324. for _, k := range dataVal.MapKeys() {
  325. fieldName := fmt.Sprintf("%s[%s]", name, k)
  326. currentKey := reflect.Indirect(reflect.New(valKeyType))
  327. if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
  328. errors = append(errors, err.Error())
  329. continue
  330. }
  331. v := dataVal.MapIndex(k).Interface()
  332. if v == nil {
  333. errors = append(errors, fmt.Sprintf("filed %s invalid", fieldName))
  334. continue
  335. }
  336. currentVal := reflect.Indirect(reflect.New(valElemType))
  337. if err := d.decode(fieldName, v, currentVal); err != nil {
  338. errors = append(errors, err.Error())
  339. continue
  340. }
  341. valMap.SetMapIndex(currentKey, currentVal)
  342. }
  343. val.Set(valMap)
  344. if len(errors) > 0 {
  345. return fmt.Errorf(strings.Join(errors, ","))
  346. }
  347. return nil
  348. }
  349. func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
  350. dataVal := reflect.Indirect(reflect.ValueOf(data))
  351. // If the type of the value to write to and the data match directly,
  352. // then we just set it directly instead of recursing into the structure.
  353. if dataVal.Type() == val.Type() {
  354. val.Set(dataVal)
  355. return nil
  356. }
  357. dataValKind := dataVal.Kind()
  358. switch dataValKind {
  359. case reflect.Map:
  360. return d.decodeStructFromMap(name, dataVal, val)
  361. default:
  362. return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
  363. }
  364. }
  365. func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error {
  366. dataValType := dataVal.Type()
  367. if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
  368. return fmt.Errorf(
  369. "'%s' needs a map with string keys, has '%s' keys",
  370. name, dataValType.Key().Kind())
  371. }
  372. dataValKeys := make(map[reflect.Value]struct{})
  373. dataValKeysUnused := make(map[any]struct{})
  374. for _, dataValKey := range dataVal.MapKeys() {
  375. dataValKeys[dataValKey] = struct{}{}
  376. dataValKeysUnused[dataValKey.Interface()] = struct{}{}
  377. }
  378. errors := make([]string, 0)
  379. // This slice will keep track of all the structs we'll be decoding.
  380. // There can be more than one struct if there are embedded structs
  381. // that are squashed.
  382. structs := make([]reflect.Value, 1, 5)
  383. structs[0] = val
  384. // Compile the list of all the fields that we're going to be decoding
  385. // from all the structs.
  386. type field struct {
  387. field reflect.StructField
  388. val reflect.Value
  389. }
  390. var fields []field
  391. for len(structs) > 0 {
  392. structVal := structs[0]
  393. structs = structs[1:]
  394. structType := structVal.Type()
  395. for i := 0; i < structType.NumField(); i++ {
  396. fieldType := structType.Field(i)
  397. fieldKind := fieldType.Type.Kind()
  398. // If "squash" is specified in the tag, we squash the field down.
  399. squash := false
  400. tagParts := strings.Split(fieldType.Tag.Get(d.option.TagName), ",")
  401. for _, tag := range tagParts[1:] {
  402. if tag == "squash" {
  403. squash = true
  404. break
  405. }
  406. }
  407. if squash {
  408. if fieldKind != reflect.Struct {
  409. errors = append(errors,
  410. fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind).Error())
  411. } else {
  412. structs = append(structs, structVal.FieldByName(fieldType.Name))
  413. }
  414. continue
  415. }
  416. // Normal struct field, store it away
  417. fields = append(fields, field{fieldType, structVal.Field(i)})
  418. }
  419. }
  420. // for fieldType, field := range fields {
  421. for _, f := range fields {
  422. field, fieldValue := f.field, f.val
  423. fieldName := field.Name
  424. tagValue := field.Tag.Get(d.option.TagName)
  425. tagValue = strings.SplitN(tagValue, ",", 2)[0]
  426. if tagValue != "" {
  427. fieldName = tagValue
  428. }
  429. rawMapKey := reflect.ValueOf(fieldName)
  430. rawMapVal := dataVal.MapIndex(rawMapKey)
  431. if !rawMapVal.IsValid() {
  432. // Do a slower search by iterating over each key and
  433. // doing case-insensitive search.
  434. if d.option.KeyReplacer != nil {
  435. fieldName = d.option.KeyReplacer.Replace(fieldName)
  436. }
  437. for dataValKey := range dataValKeys {
  438. mK, ok := dataValKey.Interface().(string)
  439. if !ok {
  440. // Not a string key
  441. continue
  442. }
  443. if d.option.KeyReplacer != nil {
  444. mK = d.option.KeyReplacer.Replace(mK)
  445. }
  446. if strings.EqualFold(mK, fieldName) {
  447. rawMapKey = dataValKey
  448. rawMapVal = dataVal.MapIndex(dataValKey)
  449. break
  450. }
  451. }
  452. if !rawMapVal.IsValid() {
  453. // There was no matching key in the map for the value in
  454. // the struct. Just ignore.
  455. continue
  456. }
  457. }
  458. // Delete the key we're using from the unused map so we stop tracking
  459. delete(dataValKeysUnused, rawMapKey.Interface())
  460. if !fieldValue.IsValid() {
  461. // This should never happen
  462. panic("field is not valid")
  463. }
  464. // If we can't set the field, then it is unexported or something,
  465. // and we just continue onwards.
  466. if !fieldValue.CanSet() {
  467. continue
  468. }
  469. // If the name is empty string, then we're at the root, and we
  470. // don't dot-join the fields.
  471. if name != "" {
  472. fieldName = fmt.Sprintf("%s.%s", name, fieldName)
  473. }
  474. if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil {
  475. errors = append(errors, err.Error())
  476. }
  477. }
  478. if len(errors) > 0 {
  479. return fmt.Errorf(strings.Join(errors, ","))
  480. }
  481. return nil
  482. }
  483. func (d *Decoder) setInterface(name string, data any, val reflect.Value) (err error) {
  484. dataVal := reflect.ValueOf(data)
  485. val.Set(dataVal)
  486. return nil
  487. }