gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

array_scan.go (5083B)


      1 package pgdialect
      2 
      3 import (
      4 	"fmt"
      5 	"io"
      6 	"reflect"
      7 	"strconv"
      8 
      9 	"github.com/uptrace/bun/internal"
     10 	"github.com/uptrace/bun/schema"
     11 )
     12 
     13 func arrayScanner(typ reflect.Type) schema.ScannerFunc {
     14 	kind := typ.Kind()
     15 
     16 	switch kind {
     17 	case reflect.Ptr:
     18 		if fn := arrayScanner(typ.Elem()); fn != nil {
     19 			return schema.PtrScanner(fn)
     20 		}
     21 	case reflect.Slice, reflect.Array:
     22 		// ok:
     23 	default:
     24 		return nil
     25 	}
     26 
     27 	elemType := typ.Elem()
     28 
     29 	if kind == reflect.Slice {
     30 		switch elemType {
     31 		case stringType:
     32 			return scanStringSliceValue
     33 		case intType:
     34 			return scanIntSliceValue
     35 		case int64Type:
     36 			return scanInt64SliceValue
     37 		case float64Type:
     38 			return scanFloat64SliceValue
     39 		}
     40 	}
     41 
     42 	scanElem := schema.Scanner(elemType)
     43 	return func(dest reflect.Value, src interface{}) error {
     44 		dest = reflect.Indirect(dest)
     45 		if !dest.CanSet() {
     46 			return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
     47 		}
     48 
     49 		kind := dest.Kind()
     50 
     51 		if src == nil {
     52 			if kind != reflect.Slice || !dest.IsNil() {
     53 				dest.Set(reflect.Zero(dest.Type()))
     54 			}
     55 			return nil
     56 		}
     57 
     58 		if kind == reflect.Slice {
     59 			if dest.IsNil() {
     60 				dest.Set(reflect.MakeSlice(dest.Type(), 0, 0))
     61 			} else if dest.Len() > 0 {
     62 				dest.Set(dest.Slice(0, 0))
     63 			}
     64 		}
     65 
     66 		b, err := toBytes(src)
     67 		if err != nil {
     68 			return err
     69 		}
     70 
     71 		p := newArrayParser(b)
     72 		nextValue := internal.MakeSliceNextElemFunc(dest)
     73 		for {
     74 			elem, err := p.NextElem()
     75 			if err != nil {
     76 				if err == io.EOF {
     77 					break
     78 				}
     79 				return err
     80 			}
     81 
     82 			elemValue := nextValue()
     83 			if err := scanElem(elemValue, elem); err != nil {
     84 				return err
     85 			}
     86 		}
     87 
     88 		return nil
     89 	}
     90 }
     91 
     92 func scanStringSliceValue(dest reflect.Value, src interface{}) error {
     93 	dest = reflect.Indirect(dest)
     94 	if !dest.CanSet() {
     95 		return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
     96 	}
     97 
     98 	slice, err := decodeStringSlice(src)
     99 	if err != nil {
    100 		return err
    101 	}
    102 
    103 	dest.Set(reflect.ValueOf(slice))
    104 	return nil
    105 }
    106 
    107 func decodeStringSlice(src interface{}) ([]string, error) {
    108 	if src == nil {
    109 		return nil, nil
    110 	}
    111 
    112 	b, err := toBytes(src)
    113 	if err != nil {
    114 		return nil, err
    115 	}
    116 
    117 	slice := make([]string, 0)
    118 
    119 	p := newArrayParser(b)
    120 	for {
    121 		elem, err := p.NextElem()
    122 		if err != nil {
    123 			if err == io.EOF {
    124 				break
    125 			}
    126 			return nil, err
    127 		}
    128 		slice = append(slice, string(elem))
    129 	}
    130 
    131 	return slice, nil
    132 }
    133 
    134 func scanIntSliceValue(dest reflect.Value, src interface{}) error {
    135 	dest = reflect.Indirect(dest)
    136 	if !dest.CanSet() {
    137 		return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
    138 	}
    139 
    140 	slice, err := decodeIntSlice(src)
    141 	if err != nil {
    142 		return err
    143 	}
    144 
    145 	dest.Set(reflect.ValueOf(slice))
    146 	return nil
    147 }
    148 
    149 func decodeIntSlice(src interface{}) ([]int, error) {
    150 	if src == nil {
    151 		return nil, nil
    152 	}
    153 
    154 	b, err := toBytes(src)
    155 	if err != nil {
    156 		return nil, err
    157 	}
    158 
    159 	slice := make([]int, 0)
    160 
    161 	p := newArrayParser(b)
    162 	for {
    163 		elem, err := p.NextElem()
    164 		if err != nil {
    165 			if err == io.EOF {
    166 				break
    167 			}
    168 			return nil, err
    169 		}
    170 
    171 		if elem == nil {
    172 			slice = append(slice, 0)
    173 			continue
    174 		}
    175 
    176 		n, err := strconv.Atoi(bytesToString(elem))
    177 		if err != nil {
    178 			return nil, err
    179 		}
    180 
    181 		slice = append(slice, n)
    182 	}
    183 
    184 	return slice, nil
    185 }
    186 
    187 func scanInt64SliceValue(dest reflect.Value, src interface{}) error {
    188 	dest = reflect.Indirect(dest)
    189 	if !dest.CanSet() {
    190 		return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
    191 	}
    192 
    193 	slice, err := decodeInt64Slice(src)
    194 	if err != nil {
    195 		return err
    196 	}
    197 
    198 	dest.Set(reflect.ValueOf(slice))
    199 	return nil
    200 }
    201 
    202 func decodeInt64Slice(src interface{}) ([]int64, error) {
    203 	if src == nil {
    204 		return nil, nil
    205 	}
    206 
    207 	b, err := toBytes(src)
    208 	if err != nil {
    209 		return nil, err
    210 	}
    211 
    212 	slice := make([]int64, 0)
    213 
    214 	p := newArrayParser(b)
    215 	for {
    216 		elem, err := p.NextElem()
    217 		if err != nil {
    218 			if err == io.EOF {
    219 				break
    220 			}
    221 			return nil, err
    222 		}
    223 
    224 		if elem == nil {
    225 			slice = append(slice, 0)
    226 			continue
    227 		}
    228 
    229 		n, err := strconv.ParseInt(bytesToString(elem), 10, 64)
    230 		if err != nil {
    231 			return nil, err
    232 		}
    233 
    234 		slice = append(slice, n)
    235 	}
    236 
    237 	return slice, nil
    238 }
    239 
    240 func scanFloat64SliceValue(dest reflect.Value, src interface{}) error {
    241 	dest = reflect.Indirect(dest)
    242 	if !dest.CanSet() {
    243 		return fmt.Errorf("bun: Scan(non-settable %s)", dest.Type())
    244 	}
    245 
    246 	slice, err := scanFloat64Slice(src)
    247 	if err != nil {
    248 		return err
    249 	}
    250 
    251 	dest.Set(reflect.ValueOf(slice))
    252 	return nil
    253 }
    254 
    255 func scanFloat64Slice(src interface{}) ([]float64, error) {
    256 	if src == -1 {
    257 		return nil, nil
    258 	}
    259 
    260 	b, err := toBytes(src)
    261 	if err != nil {
    262 		return nil, err
    263 	}
    264 
    265 	slice := make([]float64, 0)
    266 
    267 	p := newArrayParser(b)
    268 	for {
    269 		elem, err := p.NextElem()
    270 		if err != nil {
    271 			if err == io.EOF {
    272 				break
    273 			}
    274 			return nil, err
    275 		}
    276 
    277 		if elem == nil {
    278 			slice = append(slice, 0)
    279 			continue
    280 		}
    281 
    282 		n, err := strconv.ParseFloat(bytesToString(elem), 64)
    283 		if err != nil {
    284 			return nil, err
    285 		}
    286 
    287 		slice = append(slice, n)
    288 	}
    289 
    290 	return slice, nil
    291 }
    292 
    293 func toBytes(src interface{}) ([]byte, error) {
    294 	switch src := src.(type) {
    295 	case string:
    296 		return stringToBytes(src), nil
    297 	case []byte:
    298 		return src, nil
    299 	default:
    300 		return nil, fmt.Errorf("bun: got %T, wanted []byte or string", src)
    301 	}
    302 }