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