...

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

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

     1  package proto
     2  
     3  import (
     4  	"encoding"
     5  	"fmt"
     6  	"net"
     7  	"reflect"
     8  	"time"
     9  
    10  	"github.com/redis/go-redis/v9/internal/util"
    11  )
    12  
    13  // Scan parses bytes `b` to `v` with appropriate type.
    14  //
    15  //nolint:gocyclo
    16  func Scan(b []byte, v interface{}) error {
    17  	switch v := v.(type) {
    18  	case nil:
    19  		return fmt.Errorf("redis: Scan(nil)")
    20  	case *string:
    21  		*v = util.BytesToString(b)
    22  		return nil
    23  	case *[]byte:
    24  		*v = b
    25  		return nil
    26  	case *int:
    27  		var err error
    28  		*v, err = util.Atoi(b)
    29  		return err
    30  	case *int8:
    31  		n, err := util.ParseInt(b, 10, 8)
    32  		if err != nil {
    33  			return err
    34  		}
    35  		*v = int8(n)
    36  		return nil
    37  	case *int16:
    38  		n, err := util.ParseInt(b, 10, 16)
    39  		if err != nil {
    40  			return err
    41  		}
    42  		*v = int16(n)
    43  		return nil
    44  	case *int32:
    45  		n, err := util.ParseInt(b, 10, 32)
    46  		if err != nil {
    47  			return err
    48  		}
    49  		*v = int32(n)
    50  		return nil
    51  	case *int64:
    52  		n, err := util.ParseInt(b, 10, 64)
    53  		if err != nil {
    54  			return err
    55  		}
    56  		*v = n
    57  		return nil
    58  	case *uint:
    59  		n, err := util.ParseUint(b, 10, 64)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		*v = uint(n)
    64  		return nil
    65  	case *uint8:
    66  		n, err := util.ParseUint(b, 10, 8)
    67  		if err != nil {
    68  			return err
    69  		}
    70  		*v = uint8(n)
    71  		return nil
    72  	case *uint16:
    73  		n, err := util.ParseUint(b, 10, 16)
    74  		if err != nil {
    75  			return err
    76  		}
    77  		*v = uint16(n)
    78  		return nil
    79  	case *uint32:
    80  		n, err := util.ParseUint(b, 10, 32)
    81  		if err != nil {
    82  			return err
    83  		}
    84  		*v = uint32(n)
    85  		return nil
    86  	case *uint64:
    87  		n, err := util.ParseUint(b, 10, 64)
    88  		if err != nil {
    89  			return err
    90  		}
    91  		*v = n
    92  		return nil
    93  	case *float32:
    94  		n, err := util.ParseFloat(b, 32)
    95  		if err != nil {
    96  			return err
    97  		}
    98  		*v = float32(n)
    99  		return err
   100  	case *float64:
   101  		var err error
   102  		*v, err = util.ParseFloat(b, 64)
   103  		return err
   104  	case *bool:
   105  		*v = len(b) == 1 && b[0] == '1'
   106  		return nil
   107  	case *time.Time:
   108  		var err error
   109  		*v, err = time.Parse(time.RFC3339Nano, util.BytesToString(b))
   110  		return err
   111  	case *time.Duration:
   112  		n, err := util.ParseInt(b, 10, 64)
   113  		if err != nil {
   114  			return err
   115  		}
   116  		*v = time.Duration(n)
   117  		return nil
   118  	case encoding.BinaryUnmarshaler:
   119  		return v.UnmarshalBinary(b)
   120  	case *net.IP:
   121  		*v = b
   122  		return nil
   123  	default:
   124  		return fmt.Errorf(
   125  			"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
   126  	}
   127  }
   128  
   129  func ScanSlice(data []string, slice interface{}) error {
   130  	v := reflect.ValueOf(slice)
   131  	if !v.IsValid() {
   132  		return fmt.Errorf("redis: ScanSlice(nil)")
   133  	}
   134  	if v.Kind() != reflect.Ptr {
   135  		return fmt.Errorf("redis: ScanSlice(non-pointer %T)", slice)
   136  	}
   137  	v = v.Elem()
   138  	if v.Kind() != reflect.Slice {
   139  		return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice)
   140  	}
   141  
   142  	next := makeSliceNextElemFunc(v)
   143  	for i, s := range data {
   144  		elem := next()
   145  		if err := Scan([]byte(s), elem.Addr().Interface()); err != nil {
   146  			err = fmt.Errorf("redis: ScanSlice index=%d value=%q failed: %w", i, s, err)
   147  			return err
   148  		}
   149  	}
   150  
   151  	return nil
   152  }
   153  
   154  func makeSliceNextElemFunc(v reflect.Value) func() reflect.Value {
   155  	elemType := v.Type().Elem()
   156  
   157  	if elemType.Kind() == reflect.Ptr {
   158  		elemType = elemType.Elem()
   159  		return func() reflect.Value {
   160  			if v.Len() < v.Cap() {
   161  				v.Set(v.Slice(0, v.Len()+1))
   162  				elem := v.Index(v.Len() - 1)
   163  				if elem.IsNil() {
   164  					elem.Set(reflect.New(elemType))
   165  				}
   166  				return elem.Elem()
   167  			}
   168  
   169  			elem := reflect.New(elemType)
   170  			v.Set(reflect.Append(v, elem))
   171  			return elem.Elem()
   172  		}
   173  	}
   174  
   175  	zero := reflect.Zero(elemType)
   176  	return func() reflect.Value {
   177  		if v.Len() < v.Cap() {
   178  			v.Set(v.Slice(0, v.Len()+1))
   179  			return v.Index(v.Len() - 1)
   180  		}
   181  
   182  		v.Set(reflect.Append(v, zero))
   183  		return v.Index(v.Len() - 1)
   184  	}
   185  }
   186  

View as plain text