...

Source file src/github.com/redis/go-redis/v9/internal/hscan/hscan.go

Documentation: github.com/redis/go-redis/v9/internal/hscan

     1  package hscan
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  )
     9  
    10  // decoderFunc represents decoding functions for default built-in types.
    11  type decoderFunc func(reflect.Value, string) error
    12  
    13  // Scanner is the interface implemented by themselves,
    14  // which will override the decoding behavior of decoderFunc.
    15  type Scanner interface {
    16  	ScanRedis(s string) error
    17  }
    18  
    19  var (
    20  	// List of built-in decoders indexed by their numeric constant values (eg: reflect.Bool = 1).
    21  	decoders = []decoderFunc{
    22  		reflect.Bool:          decodeBool,
    23  		reflect.Int:           decodeInt,
    24  		reflect.Int8:          decodeInt8,
    25  		reflect.Int16:         decodeInt16,
    26  		reflect.Int32:         decodeInt32,
    27  		reflect.Int64:         decodeInt64,
    28  		reflect.Uint:          decodeUint,
    29  		reflect.Uint8:         decodeUint8,
    30  		reflect.Uint16:        decodeUint16,
    31  		reflect.Uint32:        decodeUint32,
    32  		reflect.Uint64:        decodeUint64,
    33  		reflect.Float32:       decodeFloat32,
    34  		reflect.Float64:       decodeFloat64,
    35  		reflect.Complex64:     decodeUnsupported,
    36  		reflect.Complex128:    decodeUnsupported,
    37  		reflect.Array:         decodeUnsupported,
    38  		reflect.Chan:          decodeUnsupported,
    39  		reflect.Func:          decodeUnsupported,
    40  		reflect.Interface:     decodeUnsupported,
    41  		reflect.Map:           decodeUnsupported,
    42  		reflect.Ptr:           decodeUnsupported,
    43  		reflect.Slice:         decodeSlice,
    44  		reflect.String:        decodeString,
    45  		reflect.Struct:        decodeUnsupported,
    46  		reflect.UnsafePointer: decodeUnsupported,
    47  	}
    48  
    49  	// Global map of struct field specs that is populated once for every new
    50  	// struct type that is scanned. This caches the field types and the corresponding
    51  	// decoder functions to avoid iterating through struct fields on subsequent scans.
    52  	globalStructMap = newStructMap()
    53  )
    54  
    55  func Struct(dst interface{}) (StructValue, error) {
    56  	v := reflect.ValueOf(dst)
    57  
    58  	// The destination to scan into should be a struct pointer.
    59  	if v.Kind() != reflect.Ptr || v.IsNil() {
    60  		return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst)
    61  	}
    62  
    63  	v = v.Elem()
    64  	if v.Kind() != reflect.Struct {
    65  		return StructValue{}, fmt.Errorf("redis.Scan(non-struct %T)", dst)
    66  	}
    67  
    68  	return StructValue{
    69  		spec:  globalStructMap.get(v.Type()),
    70  		value: v,
    71  	}, nil
    72  }
    73  
    74  // Scan scans the results from a key-value Redis map result set to a destination struct.
    75  // The Redis keys are matched to the struct's field with the `redis` tag.
    76  func Scan(dst interface{}, keys []interface{}, vals []interface{}) error {
    77  	if len(keys) != len(vals) {
    78  		return errors.New("args should have the same number of keys and vals")
    79  	}
    80  
    81  	strct, err := Struct(dst)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	// Iterate through the (key, value) sequence.
    87  	for i := 0; i < len(vals); i++ {
    88  		key, ok := keys[i].(string)
    89  		if !ok {
    90  			continue
    91  		}
    92  
    93  		val, ok := vals[i].(string)
    94  		if !ok {
    95  			continue
    96  		}
    97  
    98  		if err := strct.Scan(key, val); err != nil {
    99  			return err
   100  		}
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  func decodeBool(f reflect.Value, s string) error {
   107  	b, err := strconv.ParseBool(s)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	f.SetBool(b)
   112  	return nil
   113  }
   114  
   115  func decodeInt8(f reflect.Value, s string) error {
   116  	return decodeNumber(f, s, 8)
   117  }
   118  
   119  func decodeInt16(f reflect.Value, s string) error {
   120  	return decodeNumber(f, s, 16)
   121  }
   122  
   123  func decodeInt32(f reflect.Value, s string) error {
   124  	return decodeNumber(f, s, 32)
   125  }
   126  
   127  func decodeInt64(f reflect.Value, s string) error {
   128  	return decodeNumber(f, s, 64)
   129  }
   130  
   131  func decodeInt(f reflect.Value, s string) error {
   132  	return decodeNumber(f, s, 0)
   133  }
   134  
   135  func decodeNumber(f reflect.Value, s string, bitSize int) error {
   136  	v, err := strconv.ParseInt(s, 10, bitSize)
   137  	if err != nil {
   138  		return err
   139  	}
   140  	f.SetInt(v)
   141  	return nil
   142  }
   143  
   144  func decodeUint8(f reflect.Value, s string) error {
   145  	return decodeUnsignedNumber(f, s, 8)
   146  }
   147  
   148  func decodeUint16(f reflect.Value, s string) error {
   149  	return decodeUnsignedNumber(f, s, 16)
   150  }
   151  
   152  func decodeUint32(f reflect.Value, s string) error {
   153  	return decodeUnsignedNumber(f, s, 32)
   154  }
   155  
   156  func decodeUint64(f reflect.Value, s string) error {
   157  	return decodeUnsignedNumber(f, s, 64)
   158  }
   159  
   160  func decodeUint(f reflect.Value, s string) error {
   161  	return decodeUnsignedNumber(f, s, 0)
   162  }
   163  
   164  func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error {
   165  	v, err := strconv.ParseUint(s, 10, bitSize)
   166  	if err != nil {
   167  		return err
   168  	}
   169  	f.SetUint(v)
   170  	return nil
   171  }
   172  
   173  func decodeFloat32(f reflect.Value, s string) error {
   174  	v, err := strconv.ParseFloat(s, 32)
   175  	if err != nil {
   176  		return err
   177  	}
   178  	f.SetFloat(v)
   179  	return nil
   180  }
   181  
   182  // although the default is float64, but we better define it.
   183  func decodeFloat64(f reflect.Value, s string) error {
   184  	v, err := strconv.ParseFloat(s, 64)
   185  	if err != nil {
   186  		return err
   187  	}
   188  	f.SetFloat(v)
   189  	return nil
   190  }
   191  
   192  func decodeString(f reflect.Value, s string) error {
   193  	f.SetString(s)
   194  	return nil
   195  }
   196  
   197  func decodeSlice(f reflect.Value, s string) error {
   198  	// []byte slice ([]uint8).
   199  	if f.Type().Elem().Kind() == reflect.Uint8 {
   200  		f.SetBytes([]byte(s))
   201  	}
   202  	return nil
   203  }
   204  
   205  func decodeUnsupported(v reflect.Value, s string) error {
   206  	return fmt.Errorf("redis.Scan(unsupported %s)", v.Type())
   207  }
   208  

View as plain text