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