github.com/cloudwego/frugal@v0.1.15/internal/binary/defs/types.go (about) 1 /* 2 * Copyright 2022 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package defs 18 19 import ( 20 `fmt` 21 `reflect` 22 `strings` 23 `sync` 24 `unicode` 25 26 `github.com/cloudwego/frugal/internal/utils` 27 ) 28 29 type Tag uint8 30 31 const ( 32 T_bool Tag = 2 33 T_i8 Tag = 3 34 T_double Tag = 4 35 T_i16 Tag = 6 36 T_i32 Tag = 8 37 T_i64 Tag = 10 38 T_string Tag = 11 39 T_struct Tag = 12 40 T_map Tag = 13 41 T_set Tag = 14 42 T_list Tag = 15 43 T_enum Tag = 0x80 44 T_binary Tag = 0x81 45 T_pointer Tag = 0x82 46 ) 47 48 var wireTags = [256]bool { 49 T_bool : true, 50 T_i8 : true, 51 T_double : true, 52 T_i16 : true, 53 T_i32 : true, 54 T_i64 : true, 55 T_string : true, 56 T_struct : true, 57 T_map : true, 58 T_set : true, 59 T_list : true, 60 } 61 62 var keywordTab = [256]string { 63 T_bool : "bool", 64 T_i8 : "i8 byte", 65 T_double : "double", 66 T_i16 : "i16", 67 T_i32 : "i32", 68 T_i64 : "i64", 69 T_string : "string", 70 T_binary : "binary", 71 T_struct : "struct", 72 T_map : "map", 73 } 74 75 var ( 76 i64type = reflect.TypeOf(int64(0)) 77 ) 78 79 func T_int() Tag { 80 switch IntSize { 81 case 4 : return T_i32 82 case 8 : return T_i64 83 default : panic("invalid int size") 84 } 85 } 86 87 func (self Tag) IsWireTag() bool { 88 return wireTags[self] 89 } 90 91 type Type struct { 92 T Tag 93 K *Type 94 V *Type 95 S reflect.Type 96 } 97 98 var ( 99 typePool sync.Pool 100 ) 101 102 func newType() *Type { 103 if v := typePool.Get(); v == nil { 104 return new(Type) 105 } else { 106 return resetType(v.(*Type)) 107 } 108 } 109 110 func resetType(p *Type) *Type { 111 *p = Type{} 112 return p 113 } 114 115 func (self *Type) Tag() Tag { 116 switch self.T { 117 case T_enum : return T_i32 118 case T_binary : return T_string 119 case T_pointer : return self.V.Tag() 120 default : return self.T 121 } 122 } 123 124 func (self *Type) Free() { 125 typePool.Put(self) 126 } 127 128 func (self *Type) String() string { 129 switch self.T { 130 case T_bool : return "bool" 131 case T_i8 : return "i8" 132 case T_double : return "double" 133 case T_i16 : return "i16" 134 case T_i32 : return "i32" 135 case T_i64 : return "i64" 136 case T_string : return "string" 137 case T_struct : return self.S.Name() 138 case T_map : return fmt.Sprintf("map<%s:%s>", self.K.String(), self.V.String()) 139 case T_set : return fmt.Sprintf("set<%s>", self.V.String()) 140 case T_list : return fmt.Sprintf("list<%s>", self.V.String()) 141 case T_enum : return "enum" 142 case T_binary : return "binary" 143 case T_pointer : return "*" + self.V.String() 144 default : return fmt.Sprintf("Type(Tag(%d))", self.T) 145 } 146 } 147 148 func (self *Type) IsKeyType() bool { 149 switch self.T { 150 case T_bool : return true 151 case T_i8 : return true 152 case T_double : return true 153 case T_i16 : return true 154 case T_i32 : return true 155 case T_i64 : return true 156 case T_string : return true 157 case T_enum : return true 158 case T_pointer : return self.V.T == T_struct 159 default : return false 160 } 161 } 162 163 func (self *Type) IsValueType() bool { 164 return self.T != T_pointer || self.V.T == T_struct 165 } 166 167 func (self *Type) IsSimpleType() bool { 168 switch self.T { 169 case T_bool : return true 170 case T_i8 : return true 171 case T_double : return true 172 case T_i16 : return true 173 case T_i32 : return true 174 case T_i64 : return true 175 case T_string : return true 176 case T_enum : return true 177 default : return false 178 } 179 } 180 181 func ParseType(vt reflect.Type, def string) (*Type, error) { 182 var i int 183 return doParseType(vt, def, &i, true) 184 } 185 186 func isident(c byte) bool { 187 return isident0(c) || c >= '0' && c <= '9' 188 } 189 190 func isident0(c byte) bool { 191 return c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' 192 } 193 194 func readToken(src string, i *int, eofok bool) (string, error) { 195 p := *i 196 n := len(src) 197 198 /* skip the spaces */ 199 for p < n && unicode.IsSpace(rune(src[p])) { 200 p++ 201 } 202 203 /* check for EOF */ 204 if p == n { 205 if eofok { 206 return "", nil 207 } else { 208 return "", utils.ESyntax(p, src, "unexpected EOF") 209 } 210 } 211 212 /* skip the character */ 213 q := p 214 p++ 215 216 /* check for identifiers */ 217 if isident0(src[q]) { 218 for p < n && isident(src[p]) { 219 p++ 220 } 221 } 222 223 /* slice the source */ 224 *i = p 225 return src[q:p], nil 226 } 227 228 func mkMistyped(pos int, src string, tv string, tag Tag, vt reflect.Type) utils.SyntaxError { 229 if tag != T_struct { 230 return utils.ESyntax(pos, src, fmt.Sprintf("type mismatch, %s expected, got %s", keywordTab[tag], tv)) 231 } else { 232 return utils.ESyntax(pos, src, fmt.Sprintf("struct name mismatch, %s expected, got %s", vt.Name(), tv)) 233 } 234 } 235 236 func doParseType(vt reflect.Type, def string, i *int, allowPtrs bool) (*Type, error) { 237 var tag Tag 238 var err error 239 var ret *Type 240 241 /* dereference the pointer if possible */ 242 if ret = newType(); vt.Kind() == reflect.Ptr { 243 ret.S = vt 244 ret.T = T_pointer 245 246 /* prohibit nested pointers */ 247 if !allowPtrs { 248 return nil, utils.EType(ret.V.S, "nested pointer is not allowed") 249 } 250 251 /* parse the pointer element recursively */ 252 if ret.V, err = doParseType(vt.Elem(), def, i, false); err != nil { 253 return nil, err 254 } else { 255 return ret, nil 256 } 257 } 258 259 /* check for value kind */ 260 switch vt.Kind() { 261 case reflect.Bool : tag = T_bool 262 case reflect.Int : tag = T_int() 263 case reflect.Int8 : tag = T_i8 264 case reflect.Int16 : tag = T_i16 265 case reflect.Int32 : tag = T_i32 266 case reflect.Int64 : tag = T_i64 267 case reflect.Uint : return nil, utils.EUseOther(vt, "int") 268 case reflect.Uint8 : return nil, utils.EUseOther(vt, "int8") 269 case reflect.Uint16 : return nil, utils.EUseOther(vt, "int16") 270 case reflect.Uint32 : return nil, utils.EUseOther(vt, "int32") 271 case reflect.Uint64 : return nil, utils.EUseOther(vt, "int64") 272 case reflect.Float32 : return nil, utils.EUseOther(vt, "float64") 273 case reflect.Float64 : tag = T_double 274 case reflect.Array : return nil, utils.EUseOther(vt, "[]" + vt.Elem().String()) 275 case reflect.Map : tag = T_map 276 case reflect.Slice : break 277 case reflect.String : tag = T_string 278 case reflect.Struct : tag = T_struct 279 default : return nil, utils.EType(vt, "unsupported type") 280 } 281 282 /* it's a slice, check for byte slice */ 283 if tag == 0 { 284 if et := vt.Elem(); utils.IsByteType(et) { 285 tag = T_binary 286 } else if def == "" { 287 return nil, utils.ESetList(*i, def, et) 288 } else { 289 return doParseSlice(vt, et, def, i, ret) 290 } 291 } 292 293 /* match the type if any */ 294 if def != "" { 295 if tv, et := readToken(def, i, false); et != nil { 296 return nil, et 297 } else if !strings.Contains(keywordTab[tag], tv) { 298 if !isident0(tv[0]) { 299 return nil, mkMistyped(*i - len(tv), def, tv, tag, vt) 300 } else if ok, ex := doMatchStruct(vt, def, i, &tv); ex != nil { 301 return nil, ex 302 } else if !ok { 303 return nil, mkMistyped(*i - len(tv), def, tv, tag, vt) 304 } else if tag == T_i64 && vt != i64type { 305 tag = T_enum 306 } 307 } 308 } 309 310 /* simple types */ 311 if tag != T_map { 312 ret.S = vt 313 ret.T = tag 314 return ret, nil 315 } 316 317 /* map begin */ 318 if def != "" { 319 if tk, et := readToken(def, i, false); et != nil { 320 return nil, et 321 } else if tk != "<" { 322 return nil, utils.ESyntax(*i - len(tk), def, "'<' expected") 323 } 324 } 325 326 /* parse the key type */ 327 if ret.K, err = doParseType(vt.Key(), def, i, true); err != nil { 328 return nil, err 329 } 330 331 /* validate map key */ 332 if !ret.K.IsKeyType() { 333 return nil, utils.EType(ret.K.S, "not a valid map key type") 334 } 335 336 /* key-value delimiter */ 337 if def != "" { 338 if tk, et := readToken(def, i, false); et != nil { 339 return nil, et 340 } else if tk != ":" { 341 return nil, utils.ESyntax(*i - len(tk), def, "':' expected") 342 } 343 } 344 345 /* parse the value type */ 346 if ret.V, err = doParseType(vt.Elem(), def, i, true); err != nil { 347 return nil, err 348 } 349 350 /* map end */ 351 if def != "" { 352 if tk, et := readToken(def, i, false); et != nil { 353 return nil, et 354 } else if tk != ">" { 355 return nil, utils.ESyntax(*i - len(tk), def, "'>' expected") 356 } 357 } 358 359 /* check for list elements */ 360 if !ret.V.IsValueType() { 361 return nil, utils.EType(ret.V.S, "non-struct pointers are not valid map value types") 362 } 363 364 /* set the type tag */ 365 ret.S = vt 366 ret.T = T_map 367 return ret, nil 368 } 369 370 func doParseSlice(vt reflect.Type, et reflect.Type, def string, i *int, rt *Type) (*Type, error) { 371 var err error 372 var tok string 373 374 /* read the next token */ 375 if tok, err = readToken(def, i, false); err != nil { 376 return nil, err 377 } 378 379 /* identify "set" or "list" */ 380 if tok == "set" { 381 rt.T = T_set 382 } else if tok == "list" { 383 rt.T = T_list 384 } else { 385 return nil, utils.ESyntax(*i - len(tok), def, `"set" or "list" expected`) 386 } 387 388 /* list or set begin */ 389 if tok, err = readToken(def, i, false); err != nil { 390 return nil, err 391 } else if tok != "<" { 392 return nil, utils.ESyntax(*i - len(tok), def, "'<' expected") 393 } 394 395 /* set or list element */ 396 if rt.V, err = doParseType(et, def, i, true); err != nil { 397 return nil, err 398 } 399 400 /* list or set end */ 401 if tok, err = readToken(def, i, false); err != nil { 402 return nil, err 403 } else if tok != ">" { 404 return nil, utils.ESyntax(*i - len(tok), def, "'>' expected") 405 } 406 407 /* check for list elements */ 408 if !rt.V.IsValueType() { 409 return nil, utils.EType(rt.V.S, "non-struct pointers are not valid list/set elements") 410 } 411 412 /* set the type */ 413 rt.S = vt 414 return rt, nil 415 } 416 417 func doMatchStruct(vt reflect.Type, def string, i *int, tv *string) (bool, error) { 418 var err error 419 var tok string 420 421 /* mark the starting position */ 422 sp := *i 423 tn := vt.Name() 424 425 /* read the next token */ 426 if tok, err = readToken(def, &sp, true); err != nil { 427 return false, err 428 } 429 430 /* anonymous struct */ 431 if tn == "" && vt.Kind() == reflect.Struct { 432 return true, nil 433 } 434 435 /* just a simple type with no qualifiers */ 436 if tok == "" || tok == ":" || tok == ">" { 437 return tn == *tv, nil 438 } 439 440 /* otherwise, it must be a "." */ 441 if tok != "." { 442 return false, utils.ESyntax(sp, def, "'.' or '>' expected") 443 } 444 445 /* must be an identifier */ 446 if *tv, err = readToken(def, &sp, false); err != nil { 447 return false, err 448 } else if !isident0((*tv)[0]) { 449 return false, utils.ESyntax(sp, def, "struct name expected") 450 } 451 452 /* update parsing position */ 453 *i = sp 454 return tn == *tv, nil 455 }