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.
 
 
 

556 lines
14 KiB

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