xref: /aosp_15_r20/external/golang-protobuf/internal/encoding/json/decode_token.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage json
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"bytes"
9*1c12ee1eSDan Willemsen	"fmt"
10*1c12ee1eSDan Willemsen	"strconv"
11*1c12ee1eSDan Willemsen)
12*1c12ee1eSDan Willemsen
13*1c12ee1eSDan Willemsen// Kind represents a token kind expressible in the JSON format.
14*1c12ee1eSDan Willemsentype Kind uint16
15*1c12ee1eSDan Willemsen
16*1c12ee1eSDan Willemsenconst (
17*1c12ee1eSDan Willemsen	Invalid Kind = (1 << iota) / 2
18*1c12ee1eSDan Willemsen	EOF
19*1c12ee1eSDan Willemsen	Null
20*1c12ee1eSDan Willemsen	Bool
21*1c12ee1eSDan Willemsen	Number
22*1c12ee1eSDan Willemsen	String
23*1c12ee1eSDan Willemsen	Name
24*1c12ee1eSDan Willemsen	ObjectOpen
25*1c12ee1eSDan Willemsen	ObjectClose
26*1c12ee1eSDan Willemsen	ArrayOpen
27*1c12ee1eSDan Willemsen	ArrayClose
28*1c12ee1eSDan Willemsen
29*1c12ee1eSDan Willemsen	// comma is only for parsing in between tokens and
30*1c12ee1eSDan Willemsen	// does not need to be exported.
31*1c12ee1eSDan Willemsen	comma
32*1c12ee1eSDan Willemsen)
33*1c12ee1eSDan Willemsen
34*1c12ee1eSDan Willemsenfunc (k Kind) String() string {
35*1c12ee1eSDan Willemsen	switch k {
36*1c12ee1eSDan Willemsen	case EOF:
37*1c12ee1eSDan Willemsen		return "eof"
38*1c12ee1eSDan Willemsen	case Null:
39*1c12ee1eSDan Willemsen		return "null"
40*1c12ee1eSDan Willemsen	case Bool:
41*1c12ee1eSDan Willemsen		return "bool"
42*1c12ee1eSDan Willemsen	case Number:
43*1c12ee1eSDan Willemsen		return "number"
44*1c12ee1eSDan Willemsen	case String:
45*1c12ee1eSDan Willemsen		return "string"
46*1c12ee1eSDan Willemsen	case ObjectOpen:
47*1c12ee1eSDan Willemsen		return "{"
48*1c12ee1eSDan Willemsen	case ObjectClose:
49*1c12ee1eSDan Willemsen		return "}"
50*1c12ee1eSDan Willemsen	case Name:
51*1c12ee1eSDan Willemsen		return "name"
52*1c12ee1eSDan Willemsen	case ArrayOpen:
53*1c12ee1eSDan Willemsen		return "["
54*1c12ee1eSDan Willemsen	case ArrayClose:
55*1c12ee1eSDan Willemsen		return "]"
56*1c12ee1eSDan Willemsen	case comma:
57*1c12ee1eSDan Willemsen		return ","
58*1c12ee1eSDan Willemsen	}
59*1c12ee1eSDan Willemsen	return "<invalid>"
60*1c12ee1eSDan Willemsen}
61*1c12ee1eSDan Willemsen
62*1c12ee1eSDan Willemsen// Token provides a parsed token kind and value.
63*1c12ee1eSDan Willemsen//
64*1c12ee1eSDan Willemsen// Values are provided by the difference accessor methods. The accessor methods
65*1c12ee1eSDan Willemsen// Name, Bool, and ParsedString will panic if called on the wrong kind. There
66*1c12ee1eSDan Willemsen// are different accessor methods for the Number kind for converting to the
67*1c12ee1eSDan Willemsen// appropriate Go numeric type and those methods have the ok return value.
68*1c12ee1eSDan Willemsentype Token struct {
69*1c12ee1eSDan Willemsen	// Token kind.
70*1c12ee1eSDan Willemsen	kind Kind
71*1c12ee1eSDan Willemsen	// pos provides the position of the token in the original input.
72*1c12ee1eSDan Willemsen	pos int
73*1c12ee1eSDan Willemsen	// raw bytes of the serialized token.
74*1c12ee1eSDan Willemsen	// This is a subslice into the original input.
75*1c12ee1eSDan Willemsen	raw []byte
76*1c12ee1eSDan Willemsen	// boo is parsed boolean value.
77*1c12ee1eSDan Willemsen	boo bool
78*1c12ee1eSDan Willemsen	// str is parsed string value.
79*1c12ee1eSDan Willemsen	str string
80*1c12ee1eSDan Willemsen}
81*1c12ee1eSDan Willemsen
82*1c12ee1eSDan Willemsen// Kind returns the token kind.
83*1c12ee1eSDan Willemsenfunc (t Token) Kind() Kind {
84*1c12ee1eSDan Willemsen	return t.kind
85*1c12ee1eSDan Willemsen}
86*1c12ee1eSDan Willemsen
87*1c12ee1eSDan Willemsen// RawString returns the read value in string.
88*1c12ee1eSDan Willemsenfunc (t Token) RawString() string {
89*1c12ee1eSDan Willemsen	return string(t.raw)
90*1c12ee1eSDan Willemsen}
91*1c12ee1eSDan Willemsen
92*1c12ee1eSDan Willemsen// Pos returns the token position from the input.
93*1c12ee1eSDan Willemsenfunc (t Token) Pos() int {
94*1c12ee1eSDan Willemsen	return t.pos
95*1c12ee1eSDan Willemsen}
96*1c12ee1eSDan Willemsen
97*1c12ee1eSDan Willemsen// Name returns the object name if token is Name, else it panics.
98*1c12ee1eSDan Willemsenfunc (t Token) Name() string {
99*1c12ee1eSDan Willemsen	if t.kind == Name {
100*1c12ee1eSDan Willemsen		return t.str
101*1c12ee1eSDan Willemsen	}
102*1c12ee1eSDan Willemsen	panic(fmt.Sprintf("Token is not a Name: %v", t.RawString()))
103*1c12ee1eSDan Willemsen}
104*1c12ee1eSDan Willemsen
105*1c12ee1eSDan Willemsen// Bool returns the bool value if token kind is Bool, else it panics.
106*1c12ee1eSDan Willemsenfunc (t Token) Bool() bool {
107*1c12ee1eSDan Willemsen	if t.kind == Bool {
108*1c12ee1eSDan Willemsen		return t.boo
109*1c12ee1eSDan Willemsen	}
110*1c12ee1eSDan Willemsen	panic(fmt.Sprintf("Token is not a Bool: %v", t.RawString()))
111*1c12ee1eSDan Willemsen}
112*1c12ee1eSDan Willemsen
113*1c12ee1eSDan Willemsen// ParsedString returns the string value for a JSON string token or the read
114*1c12ee1eSDan Willemsen// value in string if token is not a string.
115*1c12ee1eSDan Willemsenfunc (t Token) ParsedString() string {
116*1c12ee1eSDan Willemsen	if t.kind == String {
117*1c12ee1eSDan Willemsen		return t.str
118*1c12ee1eSDan Willemsen	}
119*1c12ee1eSDan Willemsen	panic(fmt.Sprintf("Token is not a String: %v", t.RawString()))
120*1c12ee1eSDan Willemsen}
121*1c12ee1eSDan Willemsen
122*1c12ee1eSDan Willemsen// Float returns the floating-point number if token kind is Number.
123*1c12ee1eSDan Willemsen//
124*1c12ee1eSDan Willemsen// The floating-point precision is specified by the bitSize parameter: 32 for
125*1c12ee1eSDan Willemsen// float32 or 64 for float64. If bitSize=32, the result still has type float64,
126*1c12ee1eSDan Willemsen// but it will be convertible to float32 without changing its value. It will
127*1c12ee1eSDan Willemsen// return false if the number exceeds the floating point limits for given
128*1c12ee1eSDan Willemsen// bitSize.
129*1c12ee1eSDan Willemsenfunc (t Token) Float(bitSize int) (float64, bool) {
130*1c12ee1eSDan Willemsen	if t.kind != Number {
131*1c12ee1eSDan Willemsen		return 0, false
132*1c12ee1eSDan Willemsen	}
133*1c12ee1eSDan Willemsen	f, err := strconv.ParseFloat(t.RawString(), bitSize)
134*1c12ee1eSDan Willemsen	if err != nil {
135*1c12ee1eSDan Willemsen		return 0, false
136*1c12ee1eSDan Willemsen	}
137*1c12ee1eSDan Willemsen	return f, true
138*1c12ee1eSDan Willemsen}
139*1c12ee1eSDan Willemsen
140*1c12ee1eSDan Willemsen// Int returns the signed integer number if token is Number.
141*1c12ee1eSDan Willemsen//
142*1c12ee1eSDan Willemsen// The given bitSize specifies the integer type that the result must fit into.
143*1c12ee1eSDan Willemsen// It returns false if the number is not an integer value or if the result
144*1c12ee1eSDan Willemsen// exceeds the limits for given bitSize.
145*1c12ee1eSDan Willemsenfunc (t Token) Int(bitSize int) (int64, bool) {
146*1c12ee1eSDan Willemsen	s, ok := t.getIntStr()
147*1c12ee1eSDan Willemsen	if !ok {
148*1c12ee1eSDan Willemsen		return 0, false
149*1c12ee1eSDan Willemsen	}
150*1c12ee1eSDan Willemsen	n, err := strconv.ParseInt(s, 10, bitSize)
151*1c12ee1eSDan Willemsen	if err != nil {
152*1c12ee1eSDan Willemsen		return 0, false
153*1c12ee1eSDan Willemsen	}
154*1c12ee1eSDan Willemsen	return n, true
155*1c12ee1eSDan Willemsen}
156*1c12ee1eSDan Willemsen
157*1c12ee1eSDan Willemsen// Uint returns the signed integer number if token is Number.
158*1c12ee1eSDan Willemsen//
159*1c12ee1eSDan Willemsen// The given bitSize specifies the unsigned integer type that the result must
160*1c12ee1eSDan Willemsen// fit into. It returns false if the number is not an unsigned integer value
161*1c12ee1eSDan Willemsen// or if the result exceeds the limits for given bitSize.
162*1c12ee1eSDan Willemsenfunc (t Token) Uint(bitSize int) (uint64, bool) {
163*1c12ee1eSDan Willemsen	s, ok := t.getIntStr()
164*1c12ee1eSDan Willemsen	if !ok {
165*1c12ee1eSDan Willemsen		return 0, false
166*1c12ee1eSDan Willemsen	}
167*1c12ee1eSDan Willemsen	n, err := strconv.ParseUint(s, 10, bitSize)
168*1c12ee1eSDan Willemsen	if err != nil {
169*1c12ee1eSDan Willemsen		return 0, false
170*1c12ee1eSDan Willemsen	}
171*1c12ee1eSDan Willemsen	return n, true
172*1c12ee1eSDan Willemsen}
173*1c12ee1eSDan Willemsen
174*1c12ee1eSDan Willemsenfunc (t Token) getIntStr() (string, bool) {
175*1c12ee1eSDan Willemsen	if t.kind != Number {
176*1c12ee1eSDan Willemsen		return "", false
177*1c12ee1eSDan Willemsen	}
178*1c12ee1eSDan Willemsen	parts, ok := parseNumberParts(t.raw)
179*1c12ee1eSDan Willemsen	if !ok {
180*1c12ee1eSDan Willemsen		return "", false
181*1c12ee1eSDan Willemsen	}
182*1c12ee1eSDan Willemsen	return normalizeToIntString(parts)
183*1c12ee1eSDan Willemsen}
184*1c12ee1eSDan Willemsen
185*1c12ee1eSDan Willemsen// TokenEquals returns true if given Tokens are equal, else false.
186*1c12ee1eSDan Willemsenfunc TokenEquals(x, y Token) bool {
187*1c12ee1eSDan Willemsen	return x.kind == y.kind &&
188*1c12ee1eSDan Willemsen		x.pos == y.pos &&
189*1c12ee1eSDan Willemsen		bytes.Equal(x.raw, y.raw) &&
190*1c12ee1eSDan Willemsen		x.boo == y.boo &&
191*1c12ee1eSDan Willemsen		x.str == y.str
192*1c12ee1eSDan Willemsen}
193