1
2
3
4
5 package text
6
7 import (
8 "bytes"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13
14 "google.golang.org/protobuf/internal/flags"
15 )
16
17
18 type Kind uint8
19
20
21 const (
22 Invalid Kind = iota
23 EOF
24 Name
25 Scalar
26 MessageOpen
27 MessageClose
28 ListOpen
29 ListClose
30
31
32 comma
33 semicolon
34
35
36
37 bof = Invalid
38 )
39
40 func (t Kind) String() string {
41 switch t {
42 case Invalid:
43 return "<invalid>"
44 case EOF:
45 return "eof"
46 case Scalar:
47 return "scalar"
48 case Name:
49 return "name"
50 case MessageOpen:
51 return "{"
52 case MessageClose:
53 return "}"
54 case ListOpen:
55 return "["
56 case ListClose:
57 return "]"
58 case comma:
59 return ","
60 case semicolon:
61 return ";"
62 default:
63 return fmt.Sprintf("<invalid:%v>", uint8(t))
64 }
65 }
66
67
68 type NameKind uint8
69
70
71 const (
72 IdentName NameKind = iota + 1
73 TypeName
74 FieldNumber
75 )
76
77 func (t NameKind) String() string {
78 switch t {
79 case IdentName:
80 return "IdentName"
81 case TypeName:
82 return "TypeName"
83 case FieldNumber:
84 return "FieldNumber"
85 default:
86 return fmt.Sprintf("<invalid:%v>", uint8(t))
87 }
88 }
89
90
91
92
93
94
95 const hasSeparator = 1 << 7
96
97
98 const (
99 numberValue = iota + 1
100 stringValue
101 literalValue
102 )
103
104
105 const isNegative = 1 << 7
106
107
108
109 type Token struct {
110
111 kind Kind
112
113
114
115 attrs uint8
116
117
118
119 numAttrs uint8
120
121 pos int
122
123
124 raw []byte
125
126
127
128
129 str string
130 }
131
132
133 func (t Token) Kind() Kind {
134 return t.kind
135 }
136
137
138 func (t Token) RawString() string {
139 return string(t.raw)
140 }
141
142
143 func (t Token) Pos() int {
144 return t.pos
145 }
146
147
148
149 func (t Token) NameKind() NameKind {
150 if t.kind == Name {
151 return NameKind(t.attrs &^ hasSeparator)
152 }
153 panic(fmt.Sprintf("Token is not a Name type: %s", t.kind))
154 }
155
156
157
158 func (t Token) HasSeparator() bool {
159 if t.kind == Name {
160 return t.attrs&hasSeparator != 0
161 }
162 panic(fmt.Sprintf("Token is not a Name type: %s", t.kind))
163 }
164
165
166 func (t Token) IdentName() string {
167 if t.kind == Name && t.attrs&uint8(IdentName) != 0 {
168 return string(t.raw)
169 }
170 panic(fmt.Sprintf("Token is not an IdentName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator)))
171 }
172
173
174 func (t Token) TypeName() string {
175 if t.kind == Name && t.attrs&uint8(TypeName) != 0 {
176 return t.str
177 }
178 panic(fmt.Sprintf("Token is not a TypeName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator)))
179 }
180
181
182
183
184 func (t Token) FieldNumber() int32 {
185 if t.kind != Name || t.attrs&uint8(FieldNumber) == 0 {
186 panic(fmt.Sprintf("Token is not a FieldNumber: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator)))
187 }
188
189
190 num, _ := strconv.ParseInt(string(t.raw), 10, 32)
191 return int32(num)
192 }
193
194
195 func (t Token) String() (string, bool) {
196 if t.kind != Scalar || t.attrs != stringValue {
197 return "", false
198 }
199 return t.str, true
200 }
201
202
203 func (t Token) Enum() (string, bool) {
204 if t.kind != Scalar || t.attrs != literalValue || (len(t.raw) > 0 && t.raw[0] == '-') {
205 return "", false
206 }
207 return string(t.raw), true
208 }
209
210
211 func (t Token) Bool() (bool, bool) {
212 if t.kind != Scalar {
213 return false, false
214 }
215 switch t.attrs {
216 case literalValue:
217 if b, ok := boolLits[string(t.raw)]; ok {
218 return b, true
219 }
220 case numberValue:
221
222
223 n, err := strconv.ParseUint(t.str, 0, 64)
224 if err == nil {
225 switch n {
226 case 0:
227 return false, true
228 case 1:
229 return true, true
230 }
231 }
232 }
233 return false, false
234 }
235
236
237 var boolLits = map[string]bool{
238 "t": true,
239 "true": true,
240 "True": true,
241 "f": false,
242 "false": false,
243 "False": false,
244 }
245
246
247 func (t Token) Uint64() (uint64, bool) {
248 if t.kind != Scalar || t.attrs != numberValue ||
249 t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 {
250 return 0, false
251 }
252 n, err := strconv.ParseUint(t.str, 0, 64)
253 if err != nil {
254 return 0, false
255 }
256 return n, true
257 }
258
259
260 func (t Token) Uint32() (uint32, bool) {
261 if t.kind != Scalar || t.attrs != numberValue ||
262 t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 {
263 return 0, false
264 }
265 n, err := strconv.ParseUint(t.str, 0, 32)
266 if err != nil {
267 return 0, false
268 }
269 return uint32(n), true
270 }
271
272
273 func (t Token) Int64() (int64, bool) {
274 if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 {
275 return 0, false
276 }
277 if n, err := strconv.ParseInt(t.str, 0, 64); err == nil {
278 return n, true
279 }
280
281
282 if flags.ProtoLegacy && (t.numAttrs == numHex) {
283 if n, err := strconv.ParseUint(t.str, 0, 64); err == nil {
284 return int64(n), true
285 }
286 }
287 return 0, false
288 }
289
290
291 func (t Token) Int32() (int32, bool) {
292 if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 {
293 return 0, false
294 }
295 if n, err := strconv.ParseInt(t.str, 0, 32); err == nil {
296 return int32(n), true
297 }
298
299
300 if flags.ProtoLegacy && (t.numAttrs == numHex) {
301 if n, err := strconv.ParseUint(t.str, 0, 32); err == nil {
302 return int32(n), true
303 }
304 }
305 return 0, false
306 }
307
308
309 func (t Token) Float64() (float64, bool) {
310 if t.kind != Scalar {
311 return 0, false
312 }
313 switch t.attrs {
314 case literalValue:
315 if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok {
316 return f, true
317 }
318 case numberValue:
319 n, err := strconv.ParseFloat(t.str, 64)
320 if err == nil {
321 return n, true
322 }
323 nerr := err.(*strconv.NumError)
324 if nerr.Err == strconv.ErrRange {
325 return n, true
326 }
327 }
328 return 0, false
329 }
330
331
332 func (t Token) Float32() (float32, bool) {
333 if t.kind != Scalar {
334 return 0, false
335 }
336 switch t.attrs {
337 case literalValue:
338 if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok {
339 return float32(f), true
340 }
341 case numberValue:
342 n, err := strconv.ParseFloat(t.str, 64)
343 if err == nil {
344
345 return float32(n), true
346 }
347 nerr := err.(*strconv.NumError)
348 if nerr.Err == strconv.ErrRange {
349 return float32(n), true
350 }
351 }
352 return 0, false
353 }
354
355
356
357 var floatLits = map[string]float64{
358 "nan": math.NaN(),
359 "inf": math.Inf(1),
360 "infinity": math.Inf(1),
361 "-inf": math.Inf(-1),
362 "-infinity": math.Inf(-1),
363 }
364
365
366 func TokenEquals(x, y Token) bool {
367 return x.kind == y.kind &&
368 x.attrs == y.attrs &&
369 x.numAttrs == y.numAttrs &&
370 x.pos == y.pos &&
371 bytes.Equal(x.raw, y.raw) &&
372 x.str == y.str
373 }
374
View as plain text