scan.go 14 KB

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