scan.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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 ensureLen(d reflect.Value, n int) {
  24. if n > d.Cap() {
  25. d.Set(reflect.MakeSlice(d.Type(), n, n))
  26. } else {
  27. d.SetLen(n)
  28. }
  29. }
  30. func cannotConvert(d reflect.Value, s interface{}) error {
  31. var sname string
  32. switch s.(type) {
  33. case string:
  34. sname = "Redis simple string"
  35. case Error:
  36. sname = "Redis error"
  37. case int64:
  38. sname = "Redis integer"
  39. case []byte:
  40. sname = "Redis bulk string"
  41. case []interface{}:
  42. sname = "Redis array"
  43. default:
  44. sname = reflect.TypeOf(s).String()
  45. }
  46. return fmt.Errorf("cannot convert from %s to %s", sname, d.Type())
  47. }
  48. func convertAssignBulkString(d reflect.Value, s []byte) (err error) {
  49. switch d.Type().Kind() {
  50. case reflect.Float32, reflect.Float64:
  51. var x float64
  52. x, err = strconv.ParseFloat(string(s), d.Type().Bits())
  53. d.SetFloat(x)
  54. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  55. var x int64
  56. x, err = strconv.ParseInt(string(s), 10, d.Type().Bits())
  57. d.SetInt(x)
  58. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  59. var x uint64
  60. x, err = strconv.ParseUint(string(s), 10, d.Type().Bits())
  61. d.SetUint(x)
  62. case reflect.Bool:
  63. var x bool
  64. x, err = strconv.ParseBool(string(s))
  65. d.SetBool(x)
  66. case reflect.String:
  67. d.SetString(string(s))
  68. case reflect.Slice:
  69. if d.Type().Elem().Kind() != reflect.Uint8 {
  70. err = cannotConvert(d, s)
  71. } else {
  72. d.SetBytes(s)
  73. }
  74. default:
  75. err = cannotConvert(d, s)
  76. }
  77. return
  78. }
  79. func convertAssignInt(d reflect.Value, s int64) (err error) {
  80. switch d.Type().Kind() {
  81. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  82. d.SetInt(s)
  83. if d.Int() != s {
  84. err = strconv.ErrRange
  85. d.SetInt(0)
  86. }
  87. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  88. if s < 0 {
  89. err = strconv.ErrRange
  90. } else {
  91. x := uint64(s)
  92. d.SetUint(x)
  93. if d.Uint() != x {
  94. err = strconv.ErrRange
  95. d.SetUint(0)
  96. }
  97. }
  98. case reflect.Bool:
  99. d.SetBool(s != 0)
  100. default:
  101. err = cannotConvert(d, s)
  102. }
  103. return
  104. }
  105. func convertAssignValue(d reflect.Value, s interface{}) (err error) {
  106. if d.Kind() != reflect.Ptr {
  107. if d.CanAddr() {
  108. d2 := d.Addr()
  109. if d2.CanInterface() {
  110. if scanner, ok := d2.Interface().(Scanner); ok {
  111. return scanner.RedisScan(s)
  112. }
  113. }
  114. }
  115. } else if d.CanInterface() {
  116. // Already a reflect.Ptr
  117. if d.IsNil() {
  118. d.Set(reflect.New(d.Type().Elem()))
  119. }
  120. if scanner, ok := d.Interface().(Scanner); ok {
  121. return scanner.RedisScan(s)
  122. }
  123. }
  124. switch s := s.(type) {
  125. case []byte:
  126. err = convertAssignBulkString(d, s)
  127. case int64:
  128. err = convertAssignInt(d, s)
  129. default:
  130. err = cannotConvert(d, s)
  131. }
  132. return err
  133. }
  134. func convertAssignArray(d reflect.Value, s []interface{}) error {
  135. if d.Type().Kind() != reflect.Slice {
  136. return cannotConvert(d, s)
  137. }
  138. ensureLen(d, len(s))
  139. for i := 0; i < len(s); i++ {
  140. if err := convertAssignValue(d.Index(i), s[i]); err != nil {
  141. return err
  142. }
  143. }
  144. return nil
  145. }
  146. func convertAssign(d interface{}, s interface{}) (err error) {
  147. if scanner, ok := d.(Scanner); ok {
  148. return scanner.RedisScan(s)
  149. }
  150. // Handle the most common destination types using type switches and
  151. // fall back to reflection for all other types.
  152. switch s := s.(type) {
  153. case nil:
  154. // ignore
  155. case []byte:
  156. switch d := d.(type) {
  157. case *string:
  158. *d = string(s)
  159. case *int:
  160. *d, err = strconv.Atoi(string(s))
  161. case *bool:
  162. *d, err = strconv.ParseBool(string(s))
  163. case *[]byte:
  164. *d = s
  165. case *interface{}:
  166. *d = s
  167. case nil:
  168. // skip value
  169. default:
  170. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  171. err = cannotConvert(d, s)
  172. } else {
  173. err = convertAssignBulkString(d.Elem(), s)
  174. }
  175. }
  176. case int64:
  177. switch d := d.(type) {
  178. case *int:
  179. x := int(s)
  180. if int64(x) != s {
  181. err = strconv.ErrRange
  182. x = 0
  183. }
  184. *d = x
  185. case *bool:
  186. *d = s != 0
  187. case *interface{}:
  188. *d = s
  189. case nil:
  190. // skip value
  191. default:
  192. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  193. err = cannotConvert(d, s)
  194. } else {
  195. err = convertAssignInt(d.Elem(), s)
  196. }
  197. }
  198. case string:
  199. switch d := d.(type) {
  200. case *string:
  201. *d = s
  202. case *interface{}:
  203. *d = s
  204. case nil:
  205. // skip value
  206. default:
  207. err = cannotConvert(reflect.ValueOf(d), s)
  208. }
  209. case []interface{}:
  210. switch d := d.(type) {
  211. case *[]interface{}:
  212. *d = s
  213. case *interface{}:
  214. *d = s
  215. case nil:
  216. // skip value
  217. default:
  218. if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
  219. err = cannotConvert(d, s)
  220. } else {
  221. err = convertAssignArray(d.Elem(), s)
  222. }
  223. }
  224. case Error:
  225. err = s
  226. default:
  227. err = cannotConvert(reflect.ValueOf(d), s)
  228. }
  229. return
  230. }
  231. // Scan copies from src to the values pointed at by dest.
  232. //
  233. // Scan uses RedisScan if available otherwise:
  234. //
  235. // The values pointed at by dest must be an integer, float, boolean, string,
  236. // []byte, interface{} or slices of these types. Scan uses the standard strconv
  237. // package to convert bulk strings to numeric and boolean types.
  238. //
  239. // If a dest value is nil, then the corresponding src value is skipped.
  240. //
  241. // If a src element is nil, then the corresponding dest value is not modified.
  242. //
  243. // To enable easy use of Scan in a loop, Scan returns the slice of src
  244. // following the copied values.
  245. func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
  246. if len(src) < len(dest) {
  247. return nil, errors.New("redigo.Scan: array short")
  248. }
  249. var err error
  250. for i, d := range dest {
  251. err = convertAssign(d, src[i])
  252. if err != nil {
  253. err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
  254. break
  255. }
  256. }
  257. return src[len(dest):], err
  258. }
  259. type fieldSpec struct {
  260. name string
  261. index []int
  262. omitEmpty bool
  263. }
  264. type structSpec struct {
  265. m map[string]*fieldSpec
  266. l []*fieldSpec
  267. }
  268. func (ss *structSpec) fieldSpec(name []byte) *fieldSpec {
  269. return ss.m[string(name)]
  270. }
  271. func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) {
  272. for i := 0; i < t.NumField(); i++ {
  273. f := t.Field(i)
  274. switch {
  275. case f.PkgPath != "" && !f.Anonymous:
  276. // Ignore unexported fields.
  277. case f.Anonymous:
  278. // TODO: Handle pointers. Requires change to decoder and
  279. // protection against infinite recursion.
  280. if f.Type.Kind() == reflect.Struct {
  281. compileStructSpec(f.Type, depth, append(index, i), ss)
  282. }
  283. default:
  284. fs := &fieldSpec{name: f.Name}
  285. tag := f.Tag.Get("redis")
  286. p := strings.Split(tag, ",")
  287. if len(p) > 0 {
  288. if p[0] == "-" {
  289. continue
  290. }
  291. if len(p[0]) > 0 {
  292. fs.name = p[0]
  293. }
  294. for _, s := range p[1:] {
  295. switch s {
  296. case "omitempty":
  297. fs.omitEmpty = true
  298. default:
  299. panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
  300. }
  301. }
  302. }
  303. d, found := depth[fs.name]
  304. if !found {
  305. d = 1 << 30
  306. }
  307. switch {
  308. case len(index) == d:
  309. // At same depth, remove from result.
  310. delete(ss.m, fs.name)
  311. j := 0
  312. for i := 0; i < len(ss.l); i++ {
  313. if fs.name != ss.l[i].name {
  314. ss.l[j] = ss.l[i]
  315. j += 1
  316. }
  317. }
  318. ss.l = ss.l[:j]
  319. case len(index) < d:
  320. fs.index = make([]int, len(index)+1)
  321. copy(fs.index, index)
  322. fs.index[len(index)] = i
  323. depth[fs.name] = len(index)
  324. ss.m[fs.name] = fs
  325. ss.l = append(ss.l, fs)
  326. }
  327. }
  328. }
  329. }
  330. var (
  331. structSpecMutex sync.RWMutex
  332. structSpecCache = make(map[reflect.Type]*structSpec)
  333. defaultFieldSpec = &fieldSpec{}
  334. )
  335. func structSpecForType(t reflect.Type) *structSpec {
  336. structSpecMutex.RLock()
  337. ss, found := structSpecCache[t]
  338. structSpecMutex.RUnlock()
  339. if found {
  340. return ss
  341. }
  342. structSpecMutex.Lock()
  343. defer structSpecMutex.Unlock()
  344. ss, found = structSpecCache[t]
  345. if found {
  346. return ss
  347. }
  348. ss = &structSpec{m: make(map[string]*fieldSpec)}
  349. compileStructSpec(t, make(map[string]int), nil, ss)
  350. structSpecCache[t] = ss
  351. return ss
  352. }
  353. var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil pointer to a struct")
  354. // ScanStruct scans alternating names and values from src to a struct. The
  355. // HGETALL and CONFIG GET commands return replies in this format.
  356. //
  357. // ScanStruct uses exported field names to match values in the response. Use
  358. // 'redis' field tag to override the name:
  359. //
  360. // Field int `redis:"myName"`
  361. //
  362. // Fields with the tag redis:"-" are ignored.
  363. //
  364. // Each field uses RedisScan if available otherwise:
  365. // Integer, float, boolean, string and []byte fields are supported. Scan uses the
  366. // standard strconv package to convert bulk string values to numeric and
  367. // boolean types.
  368. //
  369. // If a src element is nil, then the corresponding field is not modified.
  370. func ScanStruct(src []interface{}, dest interface{}) error {
  371. d := reflect.ValueOf(dest)
  372. if d.Kind() != reflect.Ptr || d.IsNil() {
  373. return errScanStructValue
  374. }
  375. d = d.Elem()
  376. if d.Kind() != reflect.Struct {
  377. return errScanStructValue
  378. }
  379. ss := structSpecForType(d.Type())
  380. if len(src)%2 != 0 {
  381. return errors.New("redigo.ScanStruct: number of values not a multiple of 2")
  382. }
  383. for i := 0; i < len(src); i += 2 {
  384. s := src[i+1]
  385. if s == nil {
  386. continue
  387. }
  388. name, ok := src[i].([]byte)
  389. if !ok {
  390. return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
  391. }
  392. fs := ss.fieldSpec(name)
  393. if fs == nil {
  394. continue
  395. }
  396. if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
  397. return fmt.Errorf("redigo.ScanStruct: cannot assign field %s: %v", fs.name, err)
  398. }
  399. }
  400. return nil
  401. }
  402. var (
  403. errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
  404. )
  405. // ScanSlice scans src to the slice pointed to by dest. The elements the dest
  406. // slice must be integer, float, boolean, string, struct or pointer to struct
  407. // values.
  408. //
  409. // Struct fields must be integer, float, boolean or string values. All struct
  410. // fields are used unless a subset is specified using fieldNames.
  411. func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error {
  412. d := reflect.ValueOf(dest)
  413. if d.Kind() != reflect.Ptr || d.IsNil() {
  414. return errScanSliceValue
  415. }
  416. d = d.Elem()
  417. if d.Kind() != reflect.Slice {
  418. return errScanSliceValue
  419. }
  420. isPtr := false
  421. t := d.Type().Elem()
  422. if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
  423. isPtr = true
  424. t = t.Elem()
  425. }
  426. if t.Kind() != reflect.Struct {
  427. ensureLen(d, len(src))
  428. for i, s := range src {
  429. if s == nil {
  430. continue
  431. }
  432. if err := convertAssignValue(d.Index(i), s); err != nil {
  433. return fmt.Errorf("redigo.ScanSlice: cannot assign element %d: %v", i, err)
  434. }
  435. }
  436. return nil
  437. }
  438. ss := structSpecForType(t)
  439. fss := ss.l
  440. if len(fieldNames) > 0 {
  441. fss = make([]*fieldSpec, len(fieldNames))
  442. for i, name := range fieldNames {
  443. fss[i] = ss.m[name]
  444. if fss[i] == nil {
  445. return fmt.Errorf("redigo.ScanSlice: ScanSlice bad field name %s", name)
  446. }
  447. }
  448. }
  449. if len(fss) == 0 {
  450. return errors.New("redigo.ScanSlice: no struct fields")
  451. }
  452. n := len(src) / len(fss)
  453. if n*len(fss) != len(src) {
  454. return errors.New("redigo.ScanSlice: length not a multiple of struct field count")
  455. }
  456. ensureLen(d, n)
  457. for i := 0; i < n; i++ {
  458. d := d.Index(i)
  459. if isPtr {
  460. if d.IsNil() {
  461. d.Set(reflect.New(t))
  462. }
  463. d = d.Elem()
  464. }
  465. for j, fs := range fss {
  466. s := src[i*len(fss)+j]
  467. if s == nil {
  468. continue
  469. }
  470. if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
  471. return fmt.Errorf("redigo.ScanSlice: cannot assign element %d to field %s: %v", i*len(fss)+j, fs.name, err)
  472. }
  473. }
  474. }
  475. return nil
  476. }
  477. // Args is a helper for constructing command arguments from structured values.
  478. type Args []interface{}
  479. // Add returns the result of appending value to args.
  480. func (args Args) Add(value ...interface{}) Args {
  481. return append(args, value...)
  482. }
  483. // AddFlat returns the result of appending the flattened value of v to args.
  484. //
  485. // Maps are flattened by appending the alternating keys and map values to args.
  486. //
  487. // Slices are flattened by appending the slice elements to args.
  488. //
  489. // Structs are flattened by appending the alternating names and values of
  490. // exported fields to args. If v is a nil struct pointer, then nothing is
  491. // appended. The 'redis' field tag overrides struct field names. See ScanStruct
  492. // for more information on the use of the 'redis' field tag.
  493. //
  494. // Other types are appended to args as is.
  495. func (args Args) AddFlat(v interface{}) Args {
  496. rv := reflect.ValueOf(v)
  497. switch rv.Kind() {
  498. case reflect.Struct:
  499. args = flattenStruct(args, rv)
  500. case reflect.Slice:
  501. for i := 0; i < rv.Len(); i++ {
  502. args = append(args, rv.Index(i).Interface())
  503. }
  504. case reflect.Map:
  505. for _, k := range rv.MapKeys() {
  506. args = append(args, k.Interface(), rv.MapIndex(k).Interface())
  507. }
  508. case reflect.Ptr:
  509. if rv.Type().Elem().Kind() == reflect.Struct {
  510. if !rv.IsNil() {
  511. args = flattenStruct(args, rv.Elem())
  512. }
  513. } else {
  514. args = append(args, v)
  515. }
  516. default:
  517. args = append(args, v)
  518. }
  519. return args
  520. }
  521. func flattenStruct(args Args, v reflect.Value) Args {
  522. ss := structSpecForType(v.Type())
  523. for _, fs := range ss.l {
  524. fv := v.FieldByIndex(fs.index)
  525. if fs.omitEmpty {
  526. var empty = false
  527. switch fv.Kind() {
  528. case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  529. empty = fv.Len() == 0
  530. case reflect.Bool:
  531. empty = !fv.Bool()
  532. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  533. empty = fv.Int() == 0
  534. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  535. empty = fv.Uint() == 0
  536. case reflect.Float32, reflect.Float64:
  537. empty = fv.Float() == 0
  538. case reflect.Interface, reflect.Ptr:
  539. empty = fv.IsNil()
  540. }
  541. if empty {
  542. continue
  543. }
  544. }
  545. args = append(args, fs.name, fv.Interface())
  546. }
  547. return args
  548. }