1 package pgtype
2
3 import (
4 "database/sql/driver"
5 "encoding/binary"
6 "fmt"
7 "math"
8 "strconv"
9 "strings"
10
11 "github.com/jackc/pgio"
12 )
13
14 type Box struct {
15 P [2]Vec2
16 Status Status
17 }
18
19 func (dst *Box) Set(src interface{}) error {
20 return fmt.Errorf("cannot convert %v to Box", src)
21 }
22
23 func (dst Box) Get() interface{} {
24 switch dst.Status {
25 case Present:
26 return dst
27 case Null:
28 return nil
29 default:
30 return dst.Status
31 }
32 }
33
34 func (src *Box) AssignTo(dst interface{}) error {
35 return fmt.Errorf("cannot assign %v to %T", src, dst)
36 }
37
38 func (dst *Box) DecodeText(ci *ConnInfo, src []byte) error {
39 if src == nil {
40 *dst = Box{Status: Null}
41 return nil
42 }
43
44 if len(src) < 11 {
45 return fmt.Errorf("invalid length for Box: %v", len(src))
46 }
47
48 str := string(src[1:])
49
50 var end int
51 end = strings.IndexByte(str, ',')
52
53 x1, err := strconv.ParseFloat(str[:end], 64)
54 if err != nil {
55 return err
56 }
57
58 str = str[end+1:]
59 end = strings.IndexByte(str, ')')
60
61 y1, err := strconv.ParseFloat(str[:end], 64)
62 if err != nil {
63 return err
64 }
65
66 str = str[end+3:]
67 end = strings.IndexByte(str, ',')
68
69 x2, err := strconv.ParseFloat(str[:end], 64)
70 if err != nil {
71 return err
72 }
73
74 str = str[end+1 : len(str)-1]
75
76 y2, err := strconv.ParseFloat(str, 64)
77 if err != nil {
78 return err
79 }
80
81 *dst = Box{P: [2]Vec2{{x1, y1}, {x2, y2}}, Status: Present}
82 return nil
83 }
84
85 func (dst *Box) DecodeBinary(ci *ConnInfo, src []byte) error {
86 if src == nil {
87 *dst = Box{Status: Null}
88 return nil
89 }
90
91 if len(src) != 32 {
92 return fmt.Errorf("invalid length for Box: %v", len(src))
93 }
94
95 x1 := binary.BigEndian.Uint64(src)
96 y1 := binary.BigEndian.Uint64(src[8:])
97 x2 := binary.BigEndian.Uint64(src[16:])
98 y2 := binary.BigEndian.Uint64(src[24:])
99
100 *dst = Box{
101 P: [2]Vec2{
102 {math.Float64frombits(x1), math.Float64frombits(y1)},
103 {math.Float64frombits(x2), math.Float64frombits(y2)},
104 },
105 Status: Present,
106 }
107 return nil
108 }
109
110 func (src Box) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
111 switch src.Status {
112 case Null:
113 return nil, nil
114 case Undefined:
115 return nil, errUndefined
116 }
117
118 buf = append(buf, fmt.Sprintf(`(%s,%s),(%s,%s)`,
119 strconv.FormatFloat(src.P[0].X, 'f', -1, 64),
120 strconv.FormatFloat(src.P[0].Y, 'f', -1, 64),
121 strconv.FormatFloat(src.P[1].X, 'f', -1, 64),
122 strconv.FormatFloat(src.P[1].Y, 'f', -1, 64),
123 )...)
124 return buf, nil
125 }
126
127 func (src Box) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
128 switch src.Status {
129 case Null:
130 return nil, nil
131 case Undefined:
132 return nil, errUndefined
133 }
134
135 buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].X))
136 buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].Y))
137 buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].X))
138 buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].Y))
139
140 return buf, nil
141 }
142
143
144 func (dst *Box) Scan(src interface{}) error {
145 if src == nil {
146 *dst = Box{Status: Null}
147 return nil
148 }
149
150 switch src := src.(type) {
151 case string:
152 return dst.DecodeText(nil, []byte(src))
153 case []byte:
154 srcCopy := make([]byte, len(src))
155 copy(srcCopy, src)
156 return dst.DecodeText(nil, srcCopy)
157 }
158
159 return fmt.Errorf("cannot scan %T", src)
160 }
161
162
163 func (src Box) Value() (driver.Value, error) {
164 return EncodeValueText(src)
165 }
166
View as plain text