1 package pgtype
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 )
8
9 type BoundType byte
10
11 const (
12 Inclusive = BoundType('i')
13 Exclusive = BoundType('e')
14 Unbounded = BoundType('U')
15 Empty = BoundType('E')
16 )
17
18 func (bt BoundType) String() string {
19 return string(bt)
20 }
21
22 type UntypedTextRange struct {
23 Lower string
24 Upper string
25 LowerType BoundType
26 UpperType BoundType
27 }
28
29 func ParseUntypedTextRange(src string) (*UntypedTextRange, error) {
30 utr := &UntypedTextRange{}
31 if src == "empty" {
32 utr.LowerType = Empty
33 utr.UpperType = Empty
34 return utr, nil
35 }
36
37 buf := bytes.NewBufferString(src)
38
39 skipWhitespace(buf)
40
41 r, _, err := buf.ReadRune()
42 if err != nil {
43 return nil, fmt.Errorf("invalid lower bound: %v", err)
44 }
45 switch r {
46 case '(':
47 utr.LowerType = Exclusive
48 case '[':
49 utr.LowerType = Inclusive
50 default:
51 return nil, fmt.Errorf("missing lower bound, instead got: %v", string(r))
52 }
53
54 r, _, err = buf.ReadRune()
55 if err != nil {
56 return nil, fmt.Errorf("invalid lower value: %v", err)
57 }
58 buf.UnreadRune()
59
60 if r == ',' {
61 utr.LowerType = Unbounded
62 } else {
63 utr.Lower, err = rangeParseValue(buf)
64 if err != nil {
65 return nil, fmt.Errorf("invalid lower value: %v", err)
66 }
67 }
68
69 r, _, err = buf.ReadRune()
70 if err != nil {
71 return nil, fmt.Errorf("missing range separator: %v", err)
72 }
73 if r != ',' {
74 return nil, fmt.Errorf("missing range separator: %v", r)
75 }
76
77 r, _, err = buf.ReadRune()
78 if err != nil {
79 return nil, fmt.Errorf("invalid upper value: %v", err)
80 }
81
82 if r == ')' || r == ']' {
83 utr.UpperType = Unbounded
84 } else {
85 buf.UnreadRune()
86 utr.Upper, err = rangeParseValue(buf)
87 if err != nil {
88 return nil, fmt.Errorf("invalid upper value: %v", err)
89 }
90
91 r, _, err = buf.ReadRune()
92 if err != nil {
93 return nil, fmt.Errorf("missing upper bound: %v", err)
94 }
95 switch r {
96 case ')':
97 utr.UpperType = Exclusive
98 case ']':
99 utr.UpperType = Inclusive
100 default:
101 return nil, fmt.Errorf("missing upper bound, instead got: %v", string(r))
102 }
103 }
104
105 skipWhitespace(buf)
106
107 if buf.Len() > 0 {
108 return nil, fmt.Errorf("unexpected trailing data: %v", buf.String())
109 }
110
111 return utr, nil
112 }
113
114 func rangeParseValue(buf *bytes.Buffer) (string, error) {
115 r, _, err := buf.ReadRune()
116 if err != nil {
117 return "", err
118 }
119 if r == '"' {
120 return rangeParseQuotedValue(buf)
121 }
122 buf.UnreadRune()
123
124 s := &bytes.Buffer{}
125
126 for {
127 r, _, err := buf.ReadRune()
128 if err != nil {
129 return "", err
130 }
131
132 switch r {
133 case '\\':
134 r, _, err = buf.ReadRune()
135 if err != nil {
136 return "", err
137 }
138 case ',', '[', ']', '(', ')':
139 buf.UnreadRune()
140 return s.String(), nil
141 }
142
143 s.WriteRune(r)
144 }
145 }
146
147 func rangeParseQuotedValue(buf *bytes.Buffer) (string, error) {
148 s := &bytes.Buffer{}
149
150 for {
151 r, _, err := buf.ReadRune()
152 if err != nil {
153 return "", err
154 }
155
156 switch r {
157 case '\\':
158 r, _, err = buf.ReadRune()
159 if err != nil {
160 return "", err
161 }
162 case '"':
163 r, _, err = buf.ReadRune()
164 if err != nil {
165 return "", err
166 }
167 if r != '"' {
168 buf.UnreadRune()
169 return s.String(), nil
170 }
171 }
172 s.WriteRune(r)
173 }
174 }
175
176 type UntypedBinaryRange struct {
177 Lower []byte
178 Upper []byte
179 LowerType BoundType
180 UpperType BoundType
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194 const emptyMask = 1
195 const lowerInclusiveMask = 2
196 const upperInclusiveMask = 4
197 const lowerUnboundedMask = 8
198 const upperUnboundedMask = 16
199
200 func ParseUntypedBinaryRange(src []byte) (*UntypedBinaryRange, error) {
201 ubr := &UntypedBinaryRange{}
202
203 if len(src) == 0 {
204 return nil, fmt.Errorf("range too short: %v", len(src))
205 }
206
207 rangeType := src[0]
208 rp := 1
209
210 if rangeType&emptyMask > 0 {
211 if len(src[rp:]) > 0 {
212 return nil, fmt.Errorf("unexpected trailing bytes parsing empty range: %v", len(src[rp:]))
213 }
214 ubr.LowerType = Empty
215 ubr.UpperType = Empty
216 return ubr, nil
217 }
218
219 if rangeType&lowerInclusiveMask > 0 {
220 ubr.LowerType = Inclusive
221 } else if rangeType&lowerUnboundedMask > 0 {
222 ubr.LowerType = Unbounded
223 } else {
224 ubr.LowerType = Exclusive
225 }
226
227 if rangeType&upperInclusiveMask > 0 {
228 ubr.UpperType = Inclusive
229 } else if rangeType&upperUnboundedMask > 0 {
230 ubr.UpperType = Unbounded
231 } else {
232 ubr.UpperType = Exclusive
233 }
234
235 if ubr.LowerType == Unbounded && ubr.UpperType == Unbounded {
236 if len(src[rp:]) > 0 {
237 return nil, fmt.Errorf("unexpected trailing bytes parsing unbounded range: %v", len(src[rp:]))
238 }
239 return ubr, nil
240 }
241
242 if len(src[rp:]) < 4 {
243 return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
244 }
245 valueLen := int(binary.BigEndian.Uint32(src[rp:]))
246 rp += 4
247
248 val := src[rp : rp+valueLen]
249 rp += valueLen
250
251 if ubr.LowerType != Unbounded {
252 ubr.Lower = val
253 } else {
254 ubr.Upper = val
255 if len(src[rp:]) > 0 {
256 return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
257 }
258 return ubr, nil
259 }
260
261 if ubr.UpperType != Unbounded {
262 if len(src[rp:]) < 4 {
263 return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
264 }
265 valueLen := int(binary.BigEndian.Uint32(src[rp:]))
266 rp += 4
267 ubr.Upper = src[rp : rp+valueLen]
268 rp += valueLen
269 }
270
271 if len(src[rp:]) > 0 {
272 return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
273 }
274
275 return ubr, nil
276
277 }
278
View as plain text