scan.go 16 KB

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