scan.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. // Copyright 2012 Gary Burd
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package redis
  15. import (
  16. "errors"
  17. "fmt"
  18. "reflect"
  19. "strconv"
  20. "strings"
  21. "sync"
  22. )
  23. func cannotConvert(d reflect.Value, s interface{}) error {
  24. return fmt.Errorf("redigo: Scan cannot convert from %s to %s",
  25. reflect.TypeOf(s), d.Type())
  26. }
  27. func convertAssignBytes(d reflect.Value, s []byte) (err error) {
  28. switch d.Type().Kind() {
  29. case reflect.Float32, reflect.Float64:
  30. var x float64
  31. x, err = strconv.ParseFloat(string(s), d.Type().Bits())
  32. d.SetFloat(x)
  33. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  34. var x int64
  35. x, err = strconv.ParseInt(string(s), 10, d.Type().Bits())
  36. d.SetInt(x)
  37. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  38. var x uint64
  39. x, err = strconv.ParseUint(string(s), 10, d.Type().Bits())
  40. d.SetUint(x)
  41. case reflect.Bool:
  42. var x bool
  43. x, err = strconv.ParseBool(string(s))
  44. d.SetBool(x)
  45. case reflect.String:
  46. d.SetString(string(s))
  47. case reflect.Slice:
  48. if d.Type().Elem().Kind() != reflect.Uint8 {
  49. err = cannotConvert(d, s)
  50. } else {
  51. d.SetBytes(s)
  52. }
  53. default:
  54. err = cannotConvert(d, s)
  55. }
  56. return
  57. }
  58. func convertAssignInt(d reflect.Value, s int64) (err error) {
  59. switch d.Type().Kind() {
  60. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  61. d.SetInt(s)
  62. if d.Int() != s {
  63. err = strconv.ErrRange
  64. d.SetInt(0)
  65. }
  66. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  67. if s < 0 {
  68. err = strconv.ErrRange
  69. } else {
  70. x := uint64(s)
  71. d.SetUint(x)
  72. if d.Uint() != x {
  73. err = strconv.ErrRange
  74. d.SetUint(0)
  75. }
  76. }
  77. case reflect.Bool:
  78. d.SetBool(s != 0)
  79. default:
  80. err = cannotConvert(d, s)
  81. }
  82. return
  83. }
  84. func convertAssignValues(d reflect.Value, s []interface{}) (err error) {
  85. if d.Type().Kind() != reflect.Slice {
  86. return cannotConvert(d, s)
  87. }
  88. if len(s) > d.Cap() {
  89. d.Set(reflect.MakeSlice(d.Type(), len(s), len(s)))
  90. } else {
  91. d.SetLen(len(s))
  92. }
  93. for i := 0; i < len(s); i++ {
  94. switch s := s[i].(type) {
  95. case []byte:
  96. err = convertAssignBytes(d.Index(i), s)
  97. case int64:
  98. err = convertAssignInt(d.Index(i), s)
  99. default:
  100. err = cannotConvert(d, s)
  101. }
  102. if err != nil {
  103. break
  104. }
  105. }
  106. return
  107. }
  108. func convertAssign(d interface{}, s interface{}) (err error) {
  109. // Handle the most common destination types using type switches and
  110. // fall back to reflection for all other types.
  111. switch s := s.(type) {
  112. case nil:
  113. // ingore
  114. case []byte:
  115. switch d := d.(type) {
  116. case *string:
  117. *d = string(s)
  118. case *int:
  119. *d, err = strconv.Atoi(string(s))
  120. case *bool:
  121. *d, err = strconv.ParseBool(string(s))
  122. case *[]byte:
  123. *d = s
  124. case *interface{}:
  125. *d = s
  126. case nil:
  127. // skip value
  128. default:
  129. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  130. err = cannotConvert(d, s)
  131. } else {
  132. err = convertAssignBytes(d.Elem(), s)
  133. }
  134. }
  135. case int64:
  136. switch d := d.(type) {
  137. case *int:
  138. x := int(s)
  139. if int64(x) != s {
  140. err = strconv.ErrRange
  141. x = 0
  142. }
  143. *d = x
  144. case *bool:
  145. *d = s != 0
  146. case *interface{}:
  147. *d = s
  148. case nil:
  149. // skip value
  150. default:
  151. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  152. err = cannotConvert(d, s)
  153. } else {
  154. err = convertAssignInt(d.Elem(), s)
  155. }
  156. }
  157. case []interface{}:
  158. switch d := d.(type) {
  159. case *[]interface{}:
  160. *d = s
  161. case *interface{}:
  162. *d = s
  163. case nil:
  164. // skip value
  165. default:
  166. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  167. err = cannotConvert(d, s)
  168. } else {
  169. err = convertAssignValues(d.Elem(), s)
  170. }
  171. }
  172. case Error:
  173. err = s
  174. default:
  175. err = cannotConvert(reflect.ValueOf(d), s)
  176. }
  177. return
  178. }
  179. // Scan copies from the multi-bulk src to the values pointed at by dest.
  180. //
  181. // The values pointed at by dest must be a numeric type, boolean, string,
  182. // []byte, interface{} or a slice of these types. Scan uses the standard
  183. // strconv package to convert bulk values to numeric and boolean types.
  184. //
  185. // If a dest value is nil, then the corresponding src value is skipped.
  186. //
  187. // If the multi-bulk value is nil, then the corresponding dest value is not
  188. // modified.
  189. //
  190. // To enable easy use of Scan in a loop, Scan returns the slice of src
  191. // following the copied values.
  192. func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
  193. if len(src) < len(dest) {
  194. return nil, errors.New("redigo: Scan multibulk short")
  195. }
  196. var err error
  197. for i, d := range dest {
  198. err = convertAssign(d, src[i])
  199. if err != nil {
  200. break
  201. }
  202. }
  203. return src[len(dest):], err
  204. }
  205. type fieldSpec struct {
  206. name string
  207. index []int
  208. //omitEmpty bool
  209. }
  210. type structSpec struct {
  211. m map[string]*fieldSpec
  212. l []*fieldSpec
  213. }
  214. func (ss *structSpec) fieldSpec(name []byte) *fieldSpec {
  215. return ss.m[string(name)]
  216. }
  217. func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) {
  218. for i := 0; i < t.NumField(); i++ {
  219. f := t.Field(i)
  220. switch {
  221. case f.PkgPath != "":
  222. // Ignore unexported fields.
  223. case f.Anonymous:
  224. // TODO: Handle pointers. Requires change to decoder and
  225. // protection against infinite recursion.
  226. if f.Type.Kind() == reflect.Struct {
  227. compileStructSpec(f.Type, depth, append(index, i), ss)
  228. }
  229. default:
  230. fs := &fieldSpec{name: f.Name}
  231. tag := f.Tag.Get("redis")
  232. p := strings.Split(tag, ",")
  233. if len(p) > 0 {
  234. if p[0] == "-" {
  235. continue
  236. }
  237. if len(p[0]) > 0 {
  238. fs.name = p[0]
  239. }
  240. for _, s := range p[1:] {
  241. switch s {
  242. //case "omitempty":
  243. // fs.omitempty = true
  244. default:
  245. panic(errors.New("redigo: unknown field flag " + s + " for type " + t.Name()))
  246. }
  247. }
  248. }
  249. d, found := depth[fs.name]
  250. if !found {
  251. d = 1 << 30
  252. }
  253. switch {
  254. case len(index) == d:
  255. // At same depth, remove from result.
  256. delete(ss.m, fs.name)
  257. j := 0
  258. for i := 0; i < len(ss.l); i++ {
  259. if fs.name != ss.l[i].name {
  260. ss.l[j] = ss.l[i]
  261. j += 1
  262. }
  263. }
  264. ss.l = ss.l[:j]
  265. case len(index) < d:
  266. fs.index = make([]int, len(index)+1)
  267. copy(fs.index, index)
  268. fs.index[len(index)] = i
  269. depth[fs.name] = len(index)
  270. ss.m[fs.name] = fs
  271. ss.l = append(ss.l, fs)
  272. }
  273. }
  274. }
  275. }
  276. var (
  277. structSpecMutex sync.RWMutex
  278. structSpecCache = make(map[reflect.Type]*structSpec)
  279. defaultFieldSpec = &fieldSpec{}
  280. )
  281. func structSpecForType(t reflect.Type) *structSpec {
  282. structSpecMutex.RLock()
  283. ss, found := structSpecCache[t]
  284. structSpecMutex.RUnlock()
  285. if found {
  286. return ss
  287. }
  288. structSpecMutex.Lock()
  289. defer structSpecMutex.Unlock()
  290. ss, found = structSpecCache[t]
  291. if found {
  292. return ss
  293. }
  294. ss = &structSpec{m: make(map[string]*fieldSpec)}
  295. compileStructSpec(t, make(map[string]int), nil, ss)
  296. structSpecCache[t] = ss
  297. return ss
  298. }
  299. // ScanStruct scans a multi-bulk src containing alternating names and values to
  300. // a struct. The HGETALL and CONFIG GET commands return replies in this format.
  301. //
  302. // ScanStruct uses the struct field name to match values in the response. Use
  303. // 'redis' field tag to override the name:
  304. //
  305. // Field int `redis:"myName"`
  306. //
  307. // Fields with the tag redis:"-" are ignored.
  308. func ScanStruct(src []interface{}, dest interface{}) error {
  309. d := reflect.ValueOf(dest)
  310. if d.Kind() != reflect.Ptr || d.IsNil() {
  311. return errors.New("redigo: ScanStruct value must be non-nil pointer")
  312. }
  313. d = d.Elem()
  314. ss := structSpecForType(d.Type())
  315. if len(src)%2 != 0 {
  316. return errors.New("redigo: ScanStruct expects even number of values in values")
  317. }
  318. for i := 0; i < len(src); i += 2 {
  319. name, ok := src[i].([]byte)
  320. if !ok {
  321. return errors.New("redigo: ScanStruct key not a bulk value")
  322. }
  323. fs := ss.fieldSpec(name)
  324. if fs == nil {
  325. continue
  326. }
  327. f := d.FieldByIndex(fs.index)
  328. var err error
  329. switch s := src[i+1].(type) {
  330. case nil:
  331. // ignore
  332. case []byte:
  333. err = convertAssignBytes(f, s)
  334. case int64:
  335. err = convertAssignInt(f, s)
  336. default:
  337. err = cannotConvert(f, s)
  338. }
  339. if err != nil {
  340. return err
  341. }
  342. }
  343. return nil
  344. }