You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
4.8 KiB

  1. package hscan
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. )
  8. // decoderFunc represents decoding functions for default built-in types.
  9. type decoderFunc func(reflect.Value, string) error
  10. var (
  11. // List of built-in decoders indexed by their numeric constant values (eg: reflect.Bool = 1).
  12. decoders = []decoderFunc{
  13. reflect.Bool: decodeBool,
  14. reflect.Int: decodeInt,
  15. reflect.Int8: decodeInt8,
  16. reflect.Int16: decodeInt16,
  17. reflect.Int32: decodeInt32,
  18. reflect.Int64: decodeInt64,
  19. reflect.Uint: decodeUint,
  20. reflect.Uint8: decodeUint8,
  21. reflect.Uint16: decodeUint16,
  22. reflect.Uint32: decodeUint32,
  23. reflect.Uint64: decodeUint64,
  24. reflect.Float32: decodeFloat32,
  25. reflect.Float64: decodeFloat64,
  26. reflect.Complex64: decodeUnsupported,
  27. reflect.Complex128: decodeUnsupported,
  28. reflect.Array: decodeUnsupported,
  29. reflect.Chan: decodeUnsupported,
  30. reflect.Func: decodeUnsupported,
  31. reflect.Interface: decodeUnsupported,
  32. reflect.Map: decodeUnsupported,
  33. reflect.Ptr: decodeUnsupported,
  34. reflect.Slice: decodeSlice,
  35. reflect.String: decodeString,
  36. reflect.Struct: decodeUnsupported,
  37. reflect.UnsafePointer: decodeUnsupported,
  38. }
  39. // Global map of struct field specs that is populated once for every new
  40. // struct type that is scanned. This caches the field types and the corresponding
  41. // decoder functions to avoid iterating through struct fields on subsequent scans.
  42. globalStructMap = newStructMap()
  43. )
  44. func Struct(dst interface{}) (StructValue, error) {
  45. v := reflect.ValueOf(dst)
  46. // The destination to scan into should be a struct pointer.
  47. if v.Kind() != reflect.Ptr || v.IsNil() {
  48. return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst)
  49. }
  50. v = v.Elem()
  51. if v.Kind() != reflect.Struct {
  52. return StructValue{}, fmt.Errorf("redis.Scan(non-struct %T)", dst)
  53. }
  54. return StructValue{
  55. spec: globalStructMap.get(v.Type()),
  56. value: v,
  57. }, nil
  58. }
  59. // Scan scans the results from a key-value Redis map result set to a destination struct.
  60. // The Redis keys are matched to the struct's field with the `redis` tag.
  61. func Scan(dst interface{}, keys []interface{}, vals []interface{}) error {
  62. if len(keys) != len(vals) {
  63. return errors.New("args should have the same number of keys and vals")
  64. }
  65. strct, err := Struct(dst)
  66. if err != nil {
  67. return err
  68. }
  69. // Iterate through the (key, value) sequence.
  70. for i := 0; i < len(vals); i++ {
  71. key, ok := keys[i].(string)
  72. if !ok {
  73. continue
  74. }
  75. val, ok := vals[i].(string)
  76. if !ok {
  77. continue
  78. }
  79. if err := strct.Scan(key, val); err != nil {
  80. return err
  81. }
  82. }
  83. return nil
  84. }
  85. func decodeBool(f reflect.Value, s string) error {
  86. b, err := strconv.ParseBool(s)
  87. if err != nil {
  88. return err
  89. }
  90. f.SetBool(b)
  91. return nil
  92. }
  93. func decodeInt8(f reflect.Value, s string) error {
  94. return decodeNumber(f, s, 8)
  95. }
  96. func decodeInt16(f reflect.Value, s string) error {
  97. return decodeNumber(f, s, 16)
  98. }
  99. func decodeInt32(f reflect.Value, s string) error {
  100. return decodeNumber(f, s, 32)
  101. }
  102. func decodeInt64(f reflect.Value, s string) error {
  103. return decodeNumber(f, s, 64)
  104. }
  105. func decodeInt(f reflect.Value, s string) error {
  106. return decodeNumber(f, s, 0)
  107. }
  108. func decodeNumber(f reflect.Value, s string, bitSize int) error {
  109. v, err := strconv.ParseInt(s, 10, bitSize)
  110. if err != nil {
  111. return err
  112. }
  113. f.SetInt(v)
  114. return nil
  115. }
  116. func decodeUint8(f reflect.Value, s string) error {
  117. return decodeUnsignedNumber(f, s, 8)
  118. }
  119. func decodeUint16(f reflect.Value, s string) error {
  120. return decodeUnsignedNumber(f, s, 16)
  121. }
  122. func decodeUint32(f reflect.Value, s string) error {
  123. return decodeUnsignedNumber(f, s, 32)
  124. }
  125. func decodeUint64(f reflect.Value, s string) error {
  126. return decodeUnsignedNumber(f, s, 64)
  127. }
  128. func decodeUint(f reflect.Value, s string) error {
  129. return decodeUnsignedNumber(f, s, 0)
  130. }
  131. func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error {
  132. v, err := strconv.ParseUint(s, 10, bitSize)
  133. if err != nil {
  134. return err
  135. }
  136. f.SetUint(v)
  137. return nil
  138. }
  139. func decodeFloat32(f reflect.Value, s string) error {
  140. v, err := strconv.ParseFloat(s, 32)
  141. if err != nil {
  142. return err
  143. }
  144. f.SetFloat(v)
  145. return nil
  146. }
  147. // although the default is float64, but we better define it.
  148. func decodeFloat64(f reflect.Value, s string) error {
  149. v, err := strconv.ParseFloat(s, 64)
  150. if err != nil {
  151. return err
  152. }
  153. f.SetFloat(v)
  154. return nil
  155. }
  156. func decodeString(f reflect.Value, s string) error {
  157. f.SetString(s)
  158. return nil
  159. }
  160. func decodeSlice(f reflect.Value, s string) error {
  161. // []byte slice ([]uint8).
  162. if f.Type().Elem().Kind() == reflect.Uint8 {
  163. f.SetBytes([]byte(s))
  164. }
  165. return nil
  166. }
  167. func decodeUnsupported(v reflect.Value, s string) error {
  168. return fmt.Errorf("redis.Scan(unsupported %s)", v.Type())
  169. }