| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- // Copyright 2012 Gary Burd
- //
- // Licensed under the Apache License, Version 2.0 (the "License"): you may
- // not use this file except in compliance with the License. You may obtain
- // a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- // License for the specific language governing permissions and limitations
- // under the License.
- package redisx
- import (
- "errors"
- "reflect"
- "strconv"
- )
- // ScanStruct is deprecated. Use redis.ScanStruct instead.
- //
- // ScanStruct scans a reply containing alternating names and values to a
- // struct. The HGETALL and CONFIG GET commands return replies in this format.
- //
- // ScanStruct uses the struct field name to match values in the response. Use
- // 'redis' field tag to override the name:
- //
- // Field int `redis:"myName"`
- //
- // Fields with the tag redis:"-" are ignored.
- func ScanStruct(reply interface{}, dst interface{}) error {
- v := reflect.ValueOf(dst)
- if v.Kind() != reflect.Ptr || v.IsNil() {
- return errors.New("redigo: ScanStruct value must be non-nil pointer")
- }
- v = v.Elem()
- ss := structSpecForType(v.Type())
- p, ok := reply.([]interface{})
- if !ok {
- return errors.New("redigo: ScanStruct expectes multibulk reply")
- }
- if len(p)%2 != 0 {
- return errors.New("redigo: ScanStruct expects even number of values in reply")
- }
- for i := 0; i < len(p); i += 2 {
- name, ok := p[i].([]byte)
- if !ok {
- return errors.New("redigo: ScanStruct key not a bulk value")
- }
- value, ok := p[i+1].([]byte)
- if !ok {
- return errors.New("redigo: ScanStruct value not a bulk value")
- }
- fs := ss.fieldSpec(name)
- if fs == nil {
- continue
- }
- fv := v.FieldByIndex(fs.index)
- switch fv.Type().Kind() {
- case reflect.String:
- fv.SetString(string(value))
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- x, err := strconv.ParseInt(string(value), 10, fv.Type().Bits())
- if err != nil {
- return err
- }
- fv.SetInt(x)
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- x, err := strconv.ParseUint(string(value), 10, fv.Type().Bits())
- if err != nil {
- return err
- }
- fv.SetUint(x)
- case reflect.Float32, reflect.Float64:
- x, err := strconv.ParseFloat(string(value), fv.Type().Bits())
- if err != nil {
- return err
- }
- fv.SetFloat(x)
- case reflect.Bool:
- x := len(value) != 0 && (len(value) != 1 || value[0] != '0')
- fv.SetBool(x)
- case reflect.Slice:
- if fv.Type().Elem().Kind() != reflect.Uint8 {
- // TODO: check field types in structSpec
- panic("redigo: unsuported type for field " + string(name))
- }
- fv.SetBytes(value)
- default:
- // TODO: check field types in structSpec
- panic("redigo: unsuported type for field " + string(name))
- }
- }
- return nil
- }
- // AppendStruct is deprecated. Use redis.Args{}.AddFlat() instead.
- func AppendStruct(args []interface{}, src interface{}) []interface{} {
- v := reflect.ValueOf(src)
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- panic("redigo: FormatStruct argument must not be nil")
- }
- v = v.Elem()
- }
- if v.Kind() != reflect.Struct {
- panic("redigo: FormatStruct argument must be a struct or pointer to a struct")
- }
- ss := structSpecForType(v.Type())
- for _, fs := range ss.l {
- fv := v.FieldByIndex(fs.index)
- args = append(args, fs.name, fv.Interface())
- }
- return args
- }
|