github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/conv/j2p/decode.go (about) 1 package j2p 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 "sync" 8 "unsafe" 9 10 "github.com/bytedance/sonic/ast" 11 "github.com/cloudwego/dynamicgo/conv" 12 "github.com/cloudwego/dynamicgo/internal/rt" 13 "github.com/cloudwego/dynamicgo/meta" 14 "github.com/cloudwego/dynamicgo/proto" 15 "github.com/cloudwego/dynamicgo/proto/binary" 16 ) 17 18 // memory resize factor 19 const ( 20 defaultStkDepth = 256 21 nilStkType uint8 = 0 22 objStkType uint8 = 1 23 arrStkType uint8 = 2 24 mapStkType uint8 = 3 25 ) 26 27 const ( 28 mapkeyFieldNumber = 1 29 mapValueFieldNumber = 2 30 ) 31 32 var ( 33 vuPool = sync.Pool{ 34 New: func() interface{} { 35 return &visitorUserNode{ 36 sp: 0, 37 stk: make([]visitorUserNodeStack, defaultStkDepth), 38 } 39 }, 40 } 41 ) 42 43 func decodeBinary(val string) ([]byte, error) { 44 return decodeBase64(val) 45 } 46 47 // NewvisitorUserNode gets a new visitorUserNode from sync.Pool 48 // and reuse the buffer in pool 49 func newVisitorUserNodeBuffer() *visitorUserNode { 50 vu := vuPool.Get().(*visitorUserNode) 51 for i := 0; i < len(vu.stk); i++ { 52 vu.stk[i].state.lenPos = -1 53 } 54 return vu 55 } 56 57 // FreevisitorUserNode resets the buffer and puts the visitorUserNode back to sync.Pool 58 func freeVisitorUserNodePool(vu *visitorUserNode) { 59 vu.reset() 60 vuPool.Put(vu) 61 } 62 63 // recycle put the visitorUserNode back to sync.Pool 64 func (self *visitorUserNode) recycle() { 65 self.reset() 66 vuPool.Put(self) 67 } 68 69 // reset resets the buffer and read position 70 func (self *visitorUserNode) reset() { 71 self.sp = 0 72 self.p = nil 73 for i := 0; i < len(self.stk); i++ { 74 self.stk[i].reset() 75 } 76 self.globalFieldDesc = nil 77 self.opts = nil 78 } 79 80 // visitorUserNode is used to store some conditional variables about Protobuf when parsing json 81 // Stk: Record MessageDescriptor and PrefixLen when parsing MessageType; Record FieldDescriptor and PairPrefixLen and MapKeyDescriptor when parsing MapType; Record FieldDescriptor and PrefixListLen when parsing List 82 // Sp: using to Record the level of current stack(stk) 83 // P: Output of Protobuf BinaryData 84 // GlobalFieldDesc:After parsing the FieldKey, save the FieldDescriptor 85 type visitorUserNode struct { 86 sp uint8 87 stk []visitorUserNodeStack 88 p *binary.BinaryProtocol 89 globalFieldDesc *proto.FieldDescriptor 90 opts *conv.Options 91 } 92 93 // keep hierarchy when parsing, objStkType represents Message and arrStkType represents List and mapStkType represents Map 94 type visitorUserNodeStack struct { 95 typ uint8 96 state visitorUserNodeState 97 } 98 99 func (stk *visitorUserNodeStack) reset() { 100 stk.typ = nilStkType 101 stk.state.lenPos = -1 102 stk.state.msgDesc = nil 103 stk.state.fieldDesc = nil 104 } 105 106 // push FieldDescriptor、position of prefixLen into stack 107 func (self *visitorUserNode) push(isMap bool, isObj bool, isList bool, desc *proto.FieldDescriptor, pos int) error { 108 err := self.incrSP() 109 t := nilStkType 110 if isMap { 111 t = mapStkType 112 } else if isObj { 113 t = objStkType 114 } else if isList { 115 t = arrStkType 116 } 117 118 self.stk[self.sp] = visitorUserNodeStack{typ: t, state: visitorUserNodeState{ 119 msgDesc: nil, 120 fieldDesc: desc, 121 lenPos: pos, 122 }} 123 return err 124 } 125 126 // After parsing MessageType/MapType/ListType, pop stack 127 func (self *visitorUserNode) pop() { 128 self.stk[self.sp].reset() 129 self.sp-- 130 } 131 132 // combine of Descriptor and position of prefixLength 133 type visitorUserNodeState struct { 134 msgDesc *proto.MessageDescriptor 135 fieldDesc *proto.FieldDescriptor 136 lenPos int 137 } 138 139 func (self *visitorUserNode) decode(bytes []byte, desc *proto.TypeDescriptor) ([]byte, error) { 140 // init initial visitorUserNodeState, may be MessageDescriptor or FieldDescriptor 141 switch desc.Type() { 142 case proto.MESSAGE: 143 convDesc := desc.Message() 144 self.stk[self.sp].state = visitorUserNodeState{msgDesc: convDesc, fieldDesc: nil, lenPos: -1} 145 self.stk[self.sp].typ = objStkType 146 } 147 str := rt.Mem2Str(bytes) 148 if err := ast.Preorder(str, self, nil); err != nil { 149 return nil, err 150 } 151 return self.result() 152 } 153 154 func (self *visitorUserNode) result() ([]byte, error) { 155 if self.sp != 0 { 156 return nil, fmt.Errorf("incorrect sp: %d", self.sp) 157 } 158 return self.p.RawBuf(), nil 159 } 160 161 func (self *visitorUserNode) incrSP() error { 162 self.sp++ 163 if self.sp == 0 { 164 return fmt.Errorf("reached max depth: %d", len(self.stk)) 165 } 166 return nil 167 } 168 169 func (self *visitorUserNode) OnNull() error { 170 // self.stk[self.sp].val = &visitorUserNull{} 171 if err := self.incrSP(); err != nil { 172 return err 173 } 174 return self.onValueEnd() 175 } 176 177 func (self *visitorUserNode) OnBool(v bool) error { 178 var err error 179 if self.globalFieldDesc == nil { 180 return newError(meta.ErrConvert, "self.globalFieldDescriptor is nil, type Onbool", nil) 181 } 182 // TODO 183 if err = self.p.AppendTagByKind(self.globalFieldDesc.Number(), self.globalFieldDesc.Kind()); err != nil { 184 return err 185 } 186 if err = self.p.WriteBool(v); err != nil { 187 return err 188 } 189 return self.onValueEnd() 190 } 191 192 // Parse stringType/bytesType 193 func (self *visitorUserNode) OnString(v string) error { 194 var err error 195 top := self.stk[self.sp].state.fieldDesc 196 fieldDesc := self.globalFieldDesc 197 if fieldDesc == nil && top != nil && top.Type().IsList() { 198 fieldDesc = top 199 } 200 201 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 202 return err 203 } 204 // convert string、bytesType 205 switch fieldDesc.Kind() { 206 case proto.BytesKind: 207 // JSON format string data needs to be decoded via Base64x 208 bytesData, err := decodeBinary(v) 209 if err != nil { 210 return err 211 } 212 if err = self.p.WriteBytes(bytesData); err != nil { 213 return err 214 } 215 case proto.StringKind: 216 if err = self.p.WriteString(v); err != nil { 217 return err 218 } 219 default: 220 return newError(meta.ErrDismatchType, "param isn't stringType", nil) 221 } 222 if self.globalFieldDesc != nil { 223 return self.onValueEnd() 224 } 225 return err 226 } 227 228 func (self *visitorUserNode) OnInt64(v int64, n json.Number) error { 229 var err error 230 top := self.stk[self.sp] 231 fieldDesc := self.globalFieldDesc 232 // case PackedList(List<int32/int64/...), get fieldDescriptor from Stack 233 if self.globalFieldDesc == nil && top.typ == arrStkType { 234 fieldDesc = top.state.fieldDesc 235 } 236 237 // packed list no need to write tag 238 if !fieldDesc.Type().IsList() { 239 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 240 return err 241 } 242 } 243 244 switch fieldDesc.Kind() { 245 case proto.Int32Kind, proto.Sint32Kind, proto.Sfixed32Kind, proto.Fixed32Kind: 246 convertData := *(*int32)(unsafe.Pointer(&v)) 247 248 if err = self.p.WriteInt32(convertData); err != nil { 249 return err 250 } 251 case proto.Uint32Kind: 252 convertData := *(*uint32)(unsafe.Pointer(&v)) 253 if err = self.p.WriteUint32(convertData); err != nil { 254 return err 255 } 256 case proto.Uint64Kind: 257 convertData := *(*uint64)(unsafe.Pointer(&v)) 258 if err = self.p.WriteUint64(convertData); err != nil { 259 return err 260 } 261 case proto.Int64Kind: 262 if err = self.p.WriteInt64(v); err != nil { 263 return err 264 } 265 case proto.FloatKind: 266 if err = self.p.WriteFloat(float32(v)); err != nil { 267 return err 268 } 269 case proto.DoubleKind: 270 if err = self.p.WriteDouble(float64(v)); err != nil { 271 return err 272 } 273 274 default: 275 return newError(meta.ErrDismatchType, "param isn't intType", nil) 276 } 277 // globalFieldDesc must belong to MessageDescriptor 278 if self.globalFieldDesc != nil { 279 err = self.onValueEnd() 280 } 281 return err 282 } 283 284 func (self *visitorUserNode) OnFloat64(v float64, n json.Number) error { 285 var err error 286 top := self.stk[self.sp] 287 fieldDesc := self.globalFieldDesc 288 289 if self.globalFieldDesc == nil && top.typ == arrStkType { 290 fieldDesc = top.state.fieldDesc 291 } 292 switch fieldDesc.Kind() { 293 case proto.FloatKind: 294 convertData := *(*float32)(unsafe.Pointer(&v)) 295 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 296 return err 297 } 298 if err = self.p.WriteFloat(convertData); err != nil { 299 return err 300 } 301 case proto.DoubleKind: 302 convertData := *(*float64)(unsafe.Pointer(&v)) 303 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 304 return err 305 } 306 if err = self.p.WriteDouble(convertData); err != nil { 307 return err 308 } 309 case proto.Int32Kind: 310 convertData := int32(v) 311 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 312 return err 313 } 314 if err = self.p.WriteInt32(convertData); err != nil { 315 return err 316 } 317 case proto.Int64Kind: 318 convertData := int64(v) 319 if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil { 320 return err 321 } 322 if err = self.p.WriteInt64(convertData); err != nil { 323 return err 324 } 325 default: 326 return newError(meta.ErrDismatchType, "param isn't floatType", nil) 327 } 328 if self.globalFieldDesc != nil { 329 err = self.onValueEnd() 330 } 331 return err 332 } 333 334 // Start Parsing JSONObject, which may correspond to Protobuf Map or Protobuf Message 335 // 1. Get fieldDescriptor from globalFieldDesc first, corresponding to Message/Map embedded in a Message 336 // 2. Then get fieldDesc from the top of stack, corresponding to Message embedded in List 337 // 3. When Field is Message type, encode Tag and PrefixLen, and push FieldDescriptor and PrefixLen to the stack. 338 // When Field is Map type, only perform pressing stack operation. 339 func (self *visitorUserNode) OnObjectBegin(capacity int) error { 340 var err error 341 fieldDesc := self.globalFieldDesc 342 top := self.stk[self.sp] 343 curNodeLenPos := -1 344 345 // case List<Message>, get fieldDescriptor 346 if self.globalFieldDesc == nil && top.typ == arrStkType { 347 fieldDesc = top.state.fieldDesc 348 } 349 350 if fieldDesc != nil { 351 if fieldDesc.Type().IsMap() { 352 // case Map, push MapDesc 353 if err = self.push(true, false, false, fieldDesc, curNodeLenPos); err != nil { 354 return err 355 } 356 } else { 357 // case Message, encode Tag、PrefixLen, push MessageDesc、PrefixLen 358 if err = self.p.AppendTag(fieldDesc.Number(), proto.BytesType); err != nil { 359 return meta.NewError(meta.ErrWrite, "append prefix tag failed", nil) 360 } 361 self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf) 362 if err = self.push(false, true, false, fieldDesc, curNodeLenPos); err != nil { 363 return err 364 } 365 } 366 } 367 return err 368 } 369 370 // MapKey maybe int32/sint32/uint32/uint64 etc.... 371 func (self *visitorUserNode) encodeMapKey(key string, t proto.Type) error { 372 switch t { 373 case proto.INT32, proto.SINT32, proto.SFIX32, proto.FIX32: 374 t, _ := strconv.ParseInt(key, 10, 32) 375 if err := self.p.WriteInt32(int32(t)); err != nil { 376 return err 377 } 378 case proto.UINT32: 379 t, _ := strconv.ParseInt(key, 10, 32) 380 if err := self.p.WriteUint32(uint32(t)); err != nil { 381 return err 382 } 383 case proto.UINT64: 384 t, _ := strconv.ParseInt(key, 10, 64) 385 if err := self.p.WriteUint64(uint64(t)); err != nil { 386 return err 387 } 388 case proto.INT64: 389 t, _ := strconv.ParseInt(key, 10, 64) 390 if err := self.p.WriteInt64(int64(t)); err != nil { 391 return err 392 } 393 case proto.BOOL: 394 t, _ := strconv.ParseBool(key) 395 if err := self.p.WriteBool(t); err != nil { 396 return err 397 } 398 case proto.STRING: 399 if err := self.p.WriteString(key); err != nil { 400 return err 401 } 402 default: 403 return newError(meta.ErrDismatchType, "invalid mapKeyDescriptor Type", nil) 404 } 405 406 return nil 407 } 408 409 // Start Parsing JSONField, which may correspond to Protobuf MessageField or Protobuf MapKey 410 // 1. The initial layer obtains the MessageFieldDescriptor, saves it to globalFieldDesc and exits; 411 // 2. The inner layer performs different operations depending on the top-of-stack descriptor type 412 // 2.1 The top of the stack is MessageType, which exits after saving globalFieldDesc; 413 // 2.2 The top of the stack is MapType, write PairTag, PairLen, MapKey, MapKeyLen, and MapKeyData; save MapDesc、PairPrefixLen into stack; save MapValueDescriptor into globalFieldDesc; 414 // 2.3 The top of the stack is ListType, which exits after saving globalFieldDesc; 415 func (self *visitorUserNode) OnObjectKey(key string) error { 416 var err error 417 var top *visitorUserNodeStack 418 var curDesc proto.FieldDescriptor 419 curNodeLenPos := -1 420 421 // get stack top, and recognize currentDescriptor type 422 top = &self.stk[self.sp] 423 if top.state.msgDesc != nil { 424 // first hierarchy 425 rootDesc := top.state.msgDesc 426 fd := rootDesc.ByJSONName(key) 427 if fd == nil { 428 if !self.opts.DisallowUnknownField { 429 return newError(meta.ErrUnknownField, fmt.Sprintf("json key '%s' is unknown", key), err) 430 } else { 431 // todo 432 return nil 433 } 434 } 435 curDesc = *fd 436 } else { 437 fieldDesc := top.state.fieldDesc 438 // case MessageField 439 if top.typ == objStkType { 440 fd := fieldDesc.Message().ByJSONName(key) 441 if fd == nil { 442 if !self.opts.DisallowUnknownField { 443 return newError(meta.ErrUnknownField, fmt.Sprintf("json key '%s' is unknown", key), err) 444 } else { 445 // todo 446 return nil 447 } 448 } 449 curDesc = *fd 450 } else if top.typ == mapStkType { 451 // case MapKey, write PairTag、PairLen、MapKeyTag、MapKeyLen、MapKeyData, push MapDesc into stack 452 453 // encode PairTag、PairLen 454 fd := top.state.fieldDesc; 455 if err := self.p.AppendTag(fd.Number(), proto.BytesType); err != nil { 456 return newError(meta.ErrWrite, fmt.Sprintf("field '%s' encode pair tag faield", fd.Name()), err) 457 } 458 self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf) 459 460 // encode MapKeyTag、MapKeyLen、MapKeyData 461 mapKeyDesc := fieldDesc.MapKey() 462 if err := self.p.AppendTag(mapkeyFieldNumber, mapKeyDesc.WireType()); err != nil { 463 return newError(meta.ErrUnsupportedType, fmt.Sprintf("field '%s' encode map key tag faield", fd.Name()), err) 464 } 465 466 if err := self.encodeMapKey(key, mapKeyDesc.Type()); err != nil { 467 return newError(meta.ErrUnsupportedType, fmt.Sprintf("field '%s' encode map key faield", fd.Name()), err) 468 } 469 470 // push MapDesc into stack 471 if err = self.push(true, false, false, top.state.fieldDesc, curNodeLenPos); err != nil { 472 return err 473 } 474 // save MapValueDesc into globalFieldDesc 475 curDesc = *fieldDesc.Message().ByNumber(mapValueFieldNumber) 476 } else if top.typ == arrStkType { 477 // case List<Message> 478 curDesc = *top.state.fieldDesc 479 } 480 } 481 self.globalFieldDesc = &curDesc 482 return err 483 } 484 485 // After parsing JSONObject, write back prefixLen of Message 486 func (self *visitorUserNode) OnObjectEnd() error { 487 top := &self.stk[self.sp] 488 // root layer no need to write tag and len 489 if top.state.lenPos != -1 { 490 self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos) 491 } 492 return self.onValueEnd() 493 } 494 495 // Start Parsing JSONArray, which may correspond to ProtoBuf PackedList、UnPackedList 496 // 1. If PackedList, Encode ListTag、PrefixLen 497 // 2. push ListDescriptor、PrefixLen(UnPackedList is -1) into stack 498 func (self *visitorUserNode) OnArrayBegin(capacity int) error { 499 var err error 500 curNodeLenPos := -1 501 if self.globalFieldDesc != nil { 502 // PackedList: encode Tag、Len 503 if self.globalFieldDesc.Type().IsPacked() { 504 if err = self.p.AppendTag(self.globalFieldDesc.Number(), proto.BytesType); err != nil { 505 return meta.NewError(meta.ErrWrite, "append prefix tag failed", nil) 506 } 507 self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf) 508 } 509 if err = self.push(false, false, true, self.globalFieldDesc, curNodeLenPos); err != nil { 510 return err 511 } 512 } 513 return err 514 } 515 516 // After Parsing JSONArray, writing back PrefixLen If PackedList 517 func (self *visitorUserNode) OnArrayEnd() error { 518 var top *visitorUserNodeStack 519 top = &self.stk[self.sp] 520 // case PackedList 521 if (top.state.lenPos != -1) && top.state.fieldDesc.Type().IsPacked() { 522 self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos) 523 } 524 return self.onValueEnd() 525 } 526 527 // After parsing one JSON field, maybe basicType(string/int/float/bool/bytes) or complexType(message/map/list) 528 // 1. When type is basicType, note that the format of Map<basicType, basicType>, needs to write back PariPrefixLen of the current pair; 529 // 2. When type is MessageType, current Message may belong to Map<any, Message> or Message{Message}, note that Map<int, Message>, needs to write back PairPrefixLen of current pair; 530 // 3. When type is MapType/ListType, only execute pop operation; 531 func (self *visitorUserNode) onValueEnd() error { 532 if self.sp == 0 && self.globalFieldDesc == nil { 533 return nil 534 } 535 top := self.stk[self.sp] 536 537 // basic Type 538 if self.globalFieldDesc != nil { 539 self.globalFieldDesc = nil 540 // basic Type belong to MapValue 541 // rewrite pairlen in one kv-item of map 542 if top.typ == mapStkType { 543 self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos) 544 self.pop() 545 } 546 return nil 547 } 548 549 // complexType Type 550 if top.typ == objStkType { 551 self.pop() 552 // Message belong to Map<int, Message>、Message{Message} 553 ntop := self.stk[self.sp] 554 if ntop.typ == mapStkType { 555 self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, ntop.state.lenPos) 556 self.pop() 557 } 558 } else if top.typ == arrStkType { 559 self.pop() 560 } else if top.typ == mapStkType { 561 self.pop() 562 } else { 563 return newError(meta.ErrWrite, "disMatched ValueEnd", nil) 564 } 565 return nil 566 }