1
2
3 package pgtype
4
5 import (
6 "database/sql/driver"
7 "encoding/binary"
8 "fmt"
9 "reflect"
10
11 "github.com/jackc/pgio"
12 )
13
14 type Float4Array struct {
15 Elements []Float4
16 Dimensions []ArrayDimension
17 Status Status
18 }
19
20 func (dst *Float4Array) Set(src interface{}) error {
21
22 if src == nil {
23 *dst = Float4Array{Status: Null}
24 return nil
25 }
26
27 if value, ok := src.(interface{ Get() interface{} }); ok {
28 value2 := value.Get()
29 if value2 != value {
30 return dst.Set(value2)
31 }
32 }
33
34
35 switch value := src.(type) {
36
37 case []float32:
38 if value == nil {
39 *dst = Float4Array{Status: Null}
40 } else if len(value) == 0 {
41 *dst = Float4Array{Status: Present}
42 } else {
43 elements := make([]Float4, len(value))
44 for i := range value {
45 if err := elements[i].Set(value[i]); err != nil {
46 return err
47 }
48 }
49 *dst = Float4Array{
50 Elements: elements,
51 Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
52 Status: Present,
53 }
54 }
55
56 case []*float32:
57 if value == nil {
58 *dst = Float4Array{Status: Null}
59 } else if len(value) == 0 {
60 *dst = Float4Array{Status: Present}
61 } else {
62 elements := make([]Float4, len(value))
63 for i := range value {
64 if err := elements[i].Set(value[i]); err != nil {
65 return err
66 }
67 }
68 *dst = Float4Array{
69 Elements: elements,
70 Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
71 Status: Present,
72 }
73 }
74
75 case []Float4:
76 if value == nil {
77 *dst = Float4Array{Status: Null}
78 } else if len(value) == 0 {
79 *dst = Float4Array{Status: Present}
80 } else {
81 *dst = Float4Array{
82 Elements: value,
83 Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
84 Status: Present,
85 }
86 }
87 default:
88
89
90
91 reflectedValue := reflect.ValueOf(src)
92 if !reflectedValue.IsValid() || reflectedValue.IsZero() {
93 *dst = Float4Array{Status: Null}
94 return nil
95 }
96
97 dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
98 if !ok {
99 return fmt.Errorf("cannot find dimensions of %v for Float4Array", src)
100 }
101 if elementsLength == 0 {
102 *dst = Float4Array{Status: Present}
103 return nil
104 }
105 if len(dimensions) == 0 {
106 if originalSrc, ok := underlyingSliceType(src); ok {
107 return dst.Set(originalSrc)
108 }
109 return fmt.Errorf("cannot convert %v to Float4Array", src)
110 }
111
112 *dst = Float4Array{
113 Elements: make([]Float4, elementsLength),
114 Dimensions: dimensions,
115 Status: Present,
116 }
117 elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
118 if err != nil {
119
120 if len(dst.Dimensions) > 1 {
121 dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
122 elementsLength = 0
123 for _, dim := range dst.Dimensions {
124 if elementsLength == 0 {
125 elementsLength = int(dim.Length)
126 } else {
127 elementsLength *= int(dim.Length)
128 }
129 }
130 dst.Elements = make([]Float4, elementsLength)
131 elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
132 if err != nil {
133 return err
134 }
135 } else {
136 return err
137 }
138 }
139 if elementCount != len(dst.Elements) {
140 return fmt.Errorf("cannot convert %v to Float4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
141 }
142 }
143
144 return nil
145 }
146
147 func (dst *Float4Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
148 switch value.Kind() {
149 case reflect.Array:
150 fallthrough
151 case reflect.Slice:
152 if len(dst.Dimensions) == dimension {
153 break
154 }
155
156 valueLen := value.Len()
157 if int32(valueLen) != dst.Dimensions[dimension].Length {
158 return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
159 }
160 for i := 0; i < valueLen; i++ {
161 var err error
162 index, err = dst.setRecursive(value.Index(i), index, dimension+1)
163 if err != nil {
164 return 0, err
165 }
166 }
167
168 return index, nil
169 }
170 if !value.CanInterface() {
171 return 0, fmt.Errorf("cannot convert all values to Float4Array")
172 }
173 if err := dst.Elements[index].Set(value.Interface()); err != nil {
174 return 0, fmt.Errorf("%v in Float4Array", err)
175 }
176 index++
177
178 return index, nil
179 }
180
181 func (dst Float4Array) Get() interface{} {
182 switch dst.Status {
183 case Present:
184 return dst
185 case Null:
186 return nil
187 default:
188 return dst.Status
189 }
190 }
191
192 func (src *Float4Array) AssignTo(dst interface{}) error {
193 switch src.Status {
194 case Present:
195 if len(src.Dimensions) <= 1 {
196
197 switch v := dst.(type) {
198
199 case *[]float32:
200 *v = make([]float32, len(src.Elements))
201 for i := range src.Elements {
202 if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
203 return err
204 }
205 }
206 return nil
207
208 case *[]*float32:
209 *v = make([]*float32, len(src.Elements))
210 for i := range src.Elements {
211 if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
212 return err
213 }
214 }
215 return nil
216
217 }
218 }
219
220
221 if nextDst, retry := GetAssignToDstType(dst); retry {
222 return src.AssignTo(nextDst)
223 }
224
225
226
227
228 value := reflect.ValueOf(dst)
229 if value.Kind() == reflect.Ptr {
230 value = value.Elem()
231 }
232
233 switch value.Kind() {
234 case reflect.Array, reflect.Slice:
235 default:
236 return fmt.Errorf("cannot assign %T to %T", src, dst)
237 }
238
239 if len(src.Elements) == 0 {
240 if value.Kind() == reflect.Slice {
241 value.Set(reflect.MakeSlice(value.Type(), 0, 0))
242 return nil
243 }
244 }
245
246 elementCount, err := src.assignToRecursive(value, 0, 0)
247 if err != nil {
248 return err
249 }
250 if elementCount != len(src.Elements) {
251 return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
252 }
253
254 return nil
255 case Null:
256 return NullAssignTo(dst)
257 }
258
259 return fmt.Errorf("cannot decode %#v into %T", src, dst)
260 }
261
262 func (src *Float4Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
263 switch kind := value.Kind(); kind {
264 case reflect.Array:
265 fallthrough
266 case reflect.Slice:
267 if len(src.Dimensions) == dimension {
268 break
269 }
270
271 length := int(src.Dimensions[dimension].Length)
272 if reflect.Array == kind {
273 typ := value.Type()
274 if typ.Len() != length {
275 return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
276 }
277 value.Set(reflect.New(typ).Elem())
278 } else {
279 value.Set(reflect.MakeSlice(value.Type(), length, length))
280 }
281
282 var err error
283 for i := 0; i < length; i++ {
284 index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
285 if err != nil {
286 return 0, err
287 }
288 }
289
290 return index, nil
291 }
292 if len(src.Dimensions) != dimension {
293 return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
294 }
295 if !value.CanAddr() {
296 return 0, fmt.Errorf("cannot assign all values from Float4Array")
297 }
298 addr := value.Addr()
299 if !addr.CanInterface() {
300 return 0, fmt.Errorf("cannot assign all values from Float4Array")
301 }
302 if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
303 return 0, err
304 }
305 index++
306 return index, nil
307 }
308
309 func (dst *Float4Array) DecodeText(ci *ConnInfo, src []byte) error {
310 if src == nil {
311 *dst = Float4Array{Status: Null}
312 return nil
313 }
314
315 uta, err := ParseUntypedTextArray(string(src))
316 if err != nil {
317 return err
318 }
319
320 var elements []Float4
321
322 if len(uta.Elements) > 0 {
323 elements = make([]Float4, len(uta.Elements))
324
325 for i, s := range uta.Elements {
326 var elem Float4
327 var elemSrc []byte
328 if s != "NULL" || uta.Quoted[i] {
329 elemSrc = []byte(s)
330 }
331 err = elem.DecodeText(ci, elemSrc)
332 if err != nil {
333 return err
334 }
335
336 elements[i] = elem
337 }
338 }
339
340 *dst = Float4Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
341
342 return nil
343 }
344
345 func (dst *Float4Array) DecodeBinary(ci *ConnInfo, src []byte) error {
346 if src == nil {
347 *dst = Float4Array{Status: Null}
348 return nil
349 }
350
351 var arrayHeader ArrayHeader
352 rp, err := arrayHeader.DecodeBinary(ci, src)
353 if err != nil {
354 return err
355 }
356
357 if len(arrayHeader.Dimensions) == 0 {
358 *dst = Float4Array{Dimensions: arrayHeader.Dimensions, Status: Present}
359 return nil
360 }
361
362 elementCount := arrayHeader.Dimensions[0].Length
363 for _, d := range arrayHeader.Dimensions[1:] {
364 elementCount *= d.Length
365 }
366
367 elements := make([]Float4, elementCount)
368
369 for i := range elements {
370 elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
371 rp += 4
372 var elemSrc []byte
373 if elemLen >= 0 {
374 elemSrc = src[rp : rp+elemLen]
375 rp += elemLen
376 }
377 err = elements[i].DecodeBinary(ci, elemSrc)
378 if err != nil {
379 return err
380 }
381 }
382
383 *dst = Float4Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
384 return nil
385 }
386
387 func (src Float4Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
388 switch src.Status {
389 case Null:
390 return nil, nil
391 case Undefined:
392 return nil, errUndefined
393 }
394
395 if len(src.Dimensions) == 0 {
396 return append(buf, '{', '}'), nil
397 }
398
399 buf = EncodeTextArrayDimensions(buf, src.Dimensions)
400
401
402
403
404
405
406 dimElemCounts := make([]int, len(src.Dimensions))
407 dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
408 for i := len(src.Dimensions) - 2; i > -1; i-- {
409 dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
410 }
411
412 inElemBuf := make([]byte, 0, 32)
413 for i, elem := range src.Elements {
414 if i > 0 {
415 buf = append(buf, ',')
416 }
417
418 for _, dec := range dimElemCounts {
419 if i%dec == 0 {
420 buf = append(buf, '{')
421 }
422 }
423
424 elemBuf, err := elem.EncodeText(ci, inElemBuf)
425 if err != nil {
426 return nil, err
427 }
428 if elemBuf == nil {
429 buf = append(buf, `NULL`...)
430 } else {
431 buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
432 }
433
434 for _, dec := range dimElemCounts {
435 if (i+1)%dec == 0 {
436 buf = append(buf, '}')
437 }
438 }
439 }
440
441 return buf, nil
442 }
443
444 func (src Float4Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
445 switch src.Status {
446 case Null:
447 return nil, nil
448 case Undefined:
449 return nil, errUndefined
450 }
451
452 arrayHeader := ArrayHeader{
453 Dimensions: src.Dimensions,
454 }
455
456 if dt, ok := ci.DataTypeForName("float4"); ok {
457 arrayHeader.ElementOID = int32(dt.OID)
458 } else {
459 return nil, fmt.Errorf("unable to find oid for type name %v", "float4")
460 }
461
462 for i := range src.Elements {
463 if src.Elements[i].Status == Null {
464 arrayHeader.ContainsNull = true
465 break
466 }
467 }
468
469 buf = arrayHeader.EncodeBinary(ci, buf)
470
471 for i := range src.Elements {
472 sp := len(buf)
473 buf = pgio.AppendInt32(buf, -1)
474
475 elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
476 if err != nil {
477 return nil, err
478 }
479 if elemBuf != nil {
480 buf = elemBuf
481 pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
482 }
483 }
484
485 return buf, nil
486 }
487
488
489 func (dst *Float4Array) Scan(src interface{}) error {
490 if src == nil {
491 return dst.DecodeText(nil, nil)
492 }
493
494 switch src := src.(type) {
495 case string:
496 return dst.DecodeText(nil, []byte(src))
497 case []byte:
498 srcCopy := make([]byte, len(src))
499 copy(srcCopy, src)
500 return dst.DecodeText(nil, srcCopy)
501 }
502
503 return fmt.Errorf("cannot scan %T", src)
504 }
505
506
507 func (src Float4Array) Value() (driver.Value, error) {
508 buf, err := src.EncodeText(nil, nil)
509 if err != nil {
510 return nil, err
511 }
512 if buf == nil {
513 return nil, nil
514 }
515
516 return string(buf), nil
517 }
518
View as plain text