github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/proto/generic/path.go (about) 1 package generic 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 "unsafe" 8 9 "github.com/cloudwego/dynamicgo/internal/native/types" 10 "github.com/cloudwego/dynamicgo/meta" 11 "github.com/cloudwego/dynamicgo/proto" 12 "github.com/cloudwego/dynamicgo/proto/binary" 13 "github.com/cloudwego/dynamicgo/proto/protowire" 14 ) 15 16 var ( 17 _SkipMaxDepth = types.TB_SKIP_STACK_SIZE - 1 18 ) 19 20 // PathType is the type of path 21 type PathType uint8 22 23 const ( 24 // PathFieldId represents a field id of MESSAGE type 25 PathFieldId PathType = 1 + iota 26 27 // PathFieldName represents a field name of MESSAGE type 28 // NOTICE: it is only supported by Value 29 PathFieldName 30 31 // PathIndex represents a index of LIST type 32 PathIndex 33 34 // Path represents a string key of MAP type 35 PathStrKey 36 37 // Path represents a int key of MAP type 38 PathIntKey 39 40 // Path represents a raw-bytes key of MAP type 41 // It is usually used for neither-string-nor-integer type key 42 PathBinKey // not supported in protobuf MapKeyDescriptor 43 ) 44 45 // Path represents the relative position of a sub node in a complex parent node 46 type Path struct { 47 t PathType // path type 48 v unsafe.Pointer 49 l int 50 } 51 52 // Str returns the string value of a PathFieldName\PathStrKey path 53 func (self Path) Str() string { 54 switch self.t { 55 case PathFieldName, PathStrKey: 56 return self.str() 57 default: 58 return "" 59 } 60 } 61 62 func (self Path) str() string { 63 return *(*string)(unsafe.Pointer(&self.v)) 64 } 65 66 // Int returns the int value of a PathIndex\PathIntKey path 67 func (self Path) Int() int { 68 switch self.t { 69 case PathIndex, PathIntKey: 70 return self.int() 71 default: 72 return -1 73 } 74 } 75 76 func (self Path) int() int { 77 return self.l 78 } 79 80 // Id returns the field id of a PathFieldId path 81 func (self Path) Id() proto.FieldNumber { 82 switch self.t { 83 case PathFieldId: 84 return self.id() 85 default: 86 return proto.FieldNumber(0) 87 } 88 } 89 90 func (self Path) id() proto.FieldNumber { 91 return proto.FieldNumber(self.l) 92 } 93 94 // Type returns the type of a Path 95 func (self Path) Type() PathType { 96 return self.t 97 } 98 99 // Value returns the equivalent go interface of a Path 100 func (self Path) Value() interface{} { 101 switch self.t { 102 case PathFieldId: 103 return self.id() 104 case PathFieldName, PathStrKey: 105 return self.str() 106 case PathIndex, PathIntKey: 107 return self.int() 108 default: 109 return nil 110 } 111 } 112 113 // ToRaw converts underlying value to protobuf-encoded bytes 114 func (self Path) ToRaw(t proto.Type) []byte { 115 switch self.t { 116 case PathFieldId: 117 // tag 118 ret := make([]byte, 0, DefaultTagSliceCap) 119 if t != proto.LIST && t != proto.MAP { 120 kind := t.TypeToKind() 121 tag := uint64(self.l)<<3 | uint64(proto.Kind2Wire[kind]) 122 ret = protowire.BinaryEncoder{}.EncodeUint64(ret, tag) 123 } 124 return ret 125 case PathStrKey: 126 // tag + string key 127 ret := make([]byte, 0, DefaultTagSliceCap) 128 tag := uint64(1)<<3 | uint64(proto.STRING) 129 ret = protowire.BinaryEncoder{}.EncodeUint64(ret, tag) 130 ret = protowire.BinaryEncoder{}.EncodeString(ret, self.str()) 131 return ret 132 case PathIntKey: 133 // tag + int key 134 kind := t.TypeToKind() 135 ret := make([]byte, 0, DefaultTagSliceCap) 136 tag := uint64(1)<<3 | uint64(proto.Kind2Wire[kind]) 137 ret = protowire.BinaryEncoder{}.EncodeUint64(ret, tag) 138 switch t { 139 case proto.INT32: 140 ret = protowire.BinaryEncoder{}.EncodeInt32(ret, int32(self.l)) 141 case proto.SINT32: 142 ret = protowire.BinaryEncoder{}.EncodeSint32(ret, int32(self.l)) 143 case proto.SFIX32: 144 ret = protowire.BinaryEncoder{}.EncodeSfixed32(ret, int32(self.l)) 145 case proto.INT64: 146 ret = protowire.BinaryEncoder{}.EncodeInt64(ret, int64(self.l)) 147 case proto.SINT64: 148 ret = protowire.BinaryEncoder{}.EncodeSint64(ret, int64(self.l)) 149 case proto.SFIX64: 150 ret = protowire.BinaryEncoder{}.EncodeSfixed64(ret, int64(self.l)) 151 } 152 return ret 153 case PathBinKey: 154 return nil 155 default: 156 return nil 157 } 158 } 159 160 // NewPathFieldId creates a PathFieldId path 161 func NewPathFieldId(id proto.FieldNumber) Path { 162 return Path{ 163 t: PathFieldId, 164 l: int(id), 165 } 166 } 167 168 // NewPathFieldName creates a PathFieldName path 169 func NewPathFieldName(name string) Path { 170 return Path{ 171 t: PathFieldName, 172 v: *(*unsafe.Pointer)(unsafe.Pointer(&name)), 173 l: len(name), 174 } 175 } 176 177 // NewPathIndex creates a PathIndex path 178 func NewPathIndex(index int) Path { 179 return Path{ 180 t: PathIndex, 181 l: index, 182 } 183 } 184 185 // NewPathStrKey creates a PathStrKey path 186 func NewPathStrKey(key string) Path { 187 return Path{ 188 t: PathStrKey, 189 v: *(*unsafe.Pointer)(unsafe.Pointer(&key)), 190 l: len(key), 191 } 192 } 193 194 // NewPathIntKey creates a PathIntKey path 195 func NewPathIntKey(key int) Path { 196 return Path{ 197 t: PathIntKey, 198 l: key, 199 } 200 } 201 202 // PathNode is a three node of DOM tree 203 type PathNode struct { 204 Path 205 Node 206 Next []PathNode 207 } 208 209 var pathNodePool = sync.Pool{ 210 New: func() interface{} { 211 return &PathNode{} 212 }, 213 } 214 215 // NewPathNode get a new PathNode from memory pool 216 func NewPathNode() *PathNode { 217 return pathNodePool.Get().(*PathNode) 218 } 219 220 // CopyTo deeply copy self and its children to a PathNode 221 func (self PathNode) CopyTo(to *PathNode) { 222 to.Path = self.Path 223 to.Node = self.Node 224 if cap(to.Next) < len(self.Next) { 225 to.Next = make([]PathNode, len(self.Next)) 226 } 227 to.Next = to.Next[:len(self.Next)] 228 for i, c := range self.Next { 229 c.CopyTo(&to.Next[i]) 230 } 231 } 232 233 // ResetValue resets self's node and its children's node 234 func (self *PathNode) ResetValue() { 235 self.Node = Node{} 236 for i := range self.Next { 237 self.Next[i].ResetValue() 238 } 239 } 240 241 // ResetAll resets self and its children, including path and node both 242 func (self *PathNode) ResetAll() { 243 for i := range self.Next { 244 self.Next[i].ResetAll() 245 } 246 self.Node = Node{} 247 self.Path = Path{} 248 self.Next = self.Next[:0] 249 } 250 251 // FreePathNode put a PathNode back to memory pool 252 func FreePathNode(p *PathNode) { 253 p.Path = Path{} 254 p.Node = Node{} 255 p.Next = p.Next[:0] 256 pathNodePool.Put(p) 257 } 258 259 // extend cap of a PathNode slice 260 func guardPathNodeSlice(con *[]PathNode, l int) { 261 c := cap(*con) // Get the current capacity of the slice 262 if l >= c { 263 tmp := make([]PathNode, len(*con), l+DefaultNodeSliceCap) // Create a new slice 'tmp' 264 copy(tmp, *con) // Copy elements from the original slice to the new slice 'tmp' 265 *con = tmp // Update the reference of the original slice to point to the new slice 'tmp' 266 } 267 } 268 269 // scanChildren scans all children of self and store them in self.Next 270 // messageLen is only used when self.Node.t == proto.MESSAGE 271 func (self *PathNode) scanChildren(p *binary.BinaryProtocol, recurse bool, opts *Options, desc *proto.TypeDescriptor, messageLen int) (err error) { 272 next := self.Next[:0] // []PathNode len=0 273 l := len(next) 274 c := cap(next) 275 276 var v *PathNode 277 switch self.Node.t { 278 case proto.MESSAGE: 279 messageDesc := desc.Message() 280 start := p.Read 281 // range all fields formats: [FieldTag(L)V][FieldTag(L)V][FieldTag(L)V]... 282 for p.Read < start+messageLen { 283 fieldNumber, wireType, tagLen, tagErr := p.ConsumeTag() 284 if tagErr != nil { 285 return wrapError(meta.ErrRead, "PathNode.scanChildren: invalid field tag.", tagErr) 286 } 287 288 field := messageDesc.ByNumber(fieldNumber) 289 if field != nil { 290 v, err = self.handleChild(&next, &l, &c, p, recurse, field.Type(), tagLen, opts) 291 } else { 292 // store unknown field without recurse subnodes, containing the whole [TLV] of unknown field 293 v, err = self.handleUnknownChild(&next, &l, &c, p, recurse, opts, fieldNumber, wireType, tagLen) 294 } 295 296 if err != nil { 297 return err 298 } 299 v.Path = NewPathFieldId(fieldNumber) 300 } 301 case proto.LIST: 302 // range all elements 303 // FieldDesc := (*desc).(proto.FieldDescriptor) 304 fieldNumber := desc.BaseId() 305 start := p.Read 306 // must set list element type first, so that handleChild will can handle the element correctly 307 self.et = desc.Elem().Type() 308 listIndex := 0 309 // packed formats: [ListFieldTag][ListByteLen][VVVVV]... 310 if desc.IsPacked() { 311 if _, _, _, tagErr := p.ConsumeTag(); tagErr != nil { 312 return wrapError(meta.ErrRead, "PathNode.scanChildren: invalid list tag", tagErr) 313 } 314 315 listLen, lengthErr := p.ReadLength() 316 if lengthErr != nil { 317 return wrapError(meta.ErrRead, "PathNode.scanChildren: invalid list len", lengthErr) 318 } 319 320 start = p.Read 321 for p.Read < start+listLen { 322 // listLen is not used when node is LIST 323 v, err = self.handleChild(&next, &l, &c, p, recurse, desc.Elem(), listLen, opts) 324 if err != nil { 325 return err 326 } 327 v.Path = NewPathIndex(listIndex) 328 listIndex++ 329 } 330 } else { 331 // unpacked formats: [FieldTag(L)V][FieldTag(L)V]... 332 for p.Read < len(p.Buf) { 333 itemNumber, _, tagLen, tagErr := p.ConsumeTagWithoutMove() 334 if tagErr != nil { 335 return wrapError(meta.ErrRead, "PathNode.scanChildren: invalid element tag", tagErr) 336 } 337 338 if itemNumber != fieldNumber { 339 break 340 } 341 p.Read += tagLen 342 // tagLen is not used when node is MAP 343 v, err = self.handleChild(&next, &l, &c, p, recurse, desc.Elem(), tagLen, opts) 344 if err != nil { 345 return err 346 } 347 v.Path = NewPathIndex(listIndex) 348 listIndex++ 349 } 350 } 351 self.size = listIndex 352 case proto.MAP: 353 // range all map entries: [PairTag][PairLen][MapKeyT(L)V][MapValueT(L)V], [PairTag][PairLen][MapKeyT(L)V][MapValueT(L)V]... 354 keyDesc := desc.Key() 355 valueDesc := desc.Elem() 356 // set map key type and value type 357 self.kt = keyDesc.Type() // map key type only support int/string 358 self.et = valueDesc.Type() 359 mapNumber := desc.BaseId() 360 for p.Read < len(p.Buf) { 361 pairNumber, _, pairTagLen, pairTagErr := p.ConsumeTagWithoutMove() 362 if pairTagErr != nil { 363 return wrapError(meta.ErrRead, "PathNode.scanChildren: Consume pair tag failed", nil) 364 } 365 if pairNumber != mapNumber { 366 break 367 } 368 p.Read += pairTagLen 369 370 pairLen, pairLenErr := p.ReadLength() 371 if pairLen <= 0 || pairLenErr != nil { 372 return wrapError(meta.ErrRead, "PathNode.scanChildren:invalid pair len", pairLenErr) 373 } 374 375 if _, _, _, keyTagErr := p.ConsumeTag(); keyTagErr != nil { 376 return wrapError(meta.ErrRead, "PathNode.scanChildren: Consume map key tag failed", nil) 377 } 378 379 var keyString string 380 var keyInt int 381 var keyErr error 382 383 if self.kt == proto.STRING { 384 keyString, keyErr = p.ReadString(false) 385 } else if self.kt.IsInt() { 386 keyInt, keyErr = p.ReadInt(self.kt) 387 } else { 388 return wrapError(meta.ErrUnsupportedType, "PathNode.scanChildren: Unsupported map key type", nil) 389 } 390 391 if keyErr != nil { 392 return wrapError(meta.ErrRead, "PathNode.scanChildren: can not read map key.", keyErr) 393 } 394 395 _, _, valueLen, valueTagErr := p.ConsumeTag() // consume value tag 396 397 if valueTagErr != nil { 398 return wrapError(meta.ErrRead, "PathNode.scanChildren: Consume map value tag failed", nil) 399 } 400 401 v, err = self.handleChild(&next, &l, &c, p, recurse, valueDesc, valueLen, opts) 402 if err != nil { 403 return err 404 } 405 406 if self.kt == proto.STRING { 407 v.Path = NewPathStrKey(keyString) 408 } else if self.kt.IsInt() { 409 v.Path = NewPathIntKey(keyInt) 410 } else { 411 return wrapError(meta.ErrUnsupportedType, "PathNode.scanChildren: Unsupported map key type", nil) 412 } 413 self.size++ // map enrty size ++ 414 } 415 default: 416 return wrapError(meta.ErrUnsupportedType, "PathNode.scanChildren: Unsupported children type", nil) 417 } 418 419 self.Next = next 420 return nil 421 } 422 423 func (self *PathNode) handleChild(in *[]PathNode, lp *int, cp *int, p *binary.BinaryProtocol, recurse bool, desc *proto.TypeDescriptor, tagL int, opts *Options) (*PathNode, error) { 424 var con = *in 425 var l = *lp 426 guardPathNodeSlice(&con, l) // extend cap of con 427 if l >= len(con) { 428 con = con[:l+1] 429 } 430 v := &con[l] 431 l += 1 432 433 start := p.Read 434 buf := p.Buf 435 436 var skipType proto.WireType 437 tt := desc.Type() 438 IsPacked := desc.IsPacked() 439 440 if tt != proto.LIST { 441 skipType = desc.WireType() 442 } 443 444 // if parent node is LIST, the children type of parent node is the element type of LIST 445 if self.Node.t == proto.LIST { 446 tt = self.et 447 } 448 449 if tt == proto.LIST || tt == proto.MAP { 450 // when list/map the parent node will contain the tag, so the start need to move back tagL 451 start = start - tagL 452 if start < 0 { 453 return nil, wrapError(meta.ErrRead, "invalid start", nil) 454 } 455 skipType = proto.BytesType 456 } 457 458 // notice: when parent node is packed LIST, the size is not calculated in order to fast read all elements 459 if e := p.Skip(skipType, opts.UseNativeSkip); e != nil { 460 return nil, wrapError(meta.ErrRead, "skip field failed", e) 461 } 462 463 // unpacked LIST or MAP 464 if (tt == proto.LIST && IsPacked == false) || tt == proto.MAP { 465 fieldNumber := desc.BaseId() 466 // skip remain elements with the same field number 467 for p.Read < len(p.Buf) { 468 number, wt, tagLen, err := p.ConsumeTagWithoutMove() 469 if err != nil { 470 return nil, err 471 } 472 if number != fieldNumber { 473 break 474 } 475 p.Read += tagLen 476 if e := p.Skip(wt, opts.UseNativeSkip); e != nil { 477 return nil, wrapError(meta.ErrRead, "skip field failed", e) 478 } 479 } 480 } 481 v.Node = self.slice(start, p.Read, tt) 482 483 if tt.IsComplex() { 484 if recurse { 485 p.Buf = p.Buf[start:] 486 p.Read = 0 487 parentDesc := desc 488 messageLen := 0 489 if tt == proto.MESSAGE { 490 // parentDesc = desc.Message() 491 var err error 492 messageLen, err = p.ReadLength() // the sub message has message byteLen need to read before next recurse for scanChildren 493 if messageLen <= 0 || err != nil { 494 return nil, wrapError(meta.ErrRead, "read message length failed", err) 495 } 496 } 497 498 if err := v.scanChildren(p, recurse, opts, parentDesc, messageLen); err != nil { 499 return nil, err 500 } 501 p.Buf = buf 502 p.Read = start + p.Read 503 } else { 504 // set complex Node type when lazy load 505 if tt == proto.LIST { 506 v.et = desc.Elem().Type() 507 } else if tt == proto.MAP { 508 v.kt = desc.Key().Type() 509 v.et = desc.Elem().Type() 510 } 511 } 512 513 } 514 515 *in = con 516 *lp = l 517 *cp = cap(con) 518 return v, nil 519 } 520 521 // handleUnknownChild handles unknown field and store the [TLV] of unknown field to the proto.UNKNOWN Node 522 func (self *PathNode) handleUnknownChild(in *[]PathNode, lp *int, cp *int, p *binary.BinaryProtocol, recurse bool, opts *Options, fieldNumber proto.FieldNumber, wireType proto.WireType, tagL int) (*PathNode, error) { 523 var con = *in 524 var l = *lp 525 guardPathNodeSlice(&con, l) // extend cap of con 526 if l >= len(con) { 527 con = con[:l+1] 528 } 529 v := &con[l] 530 l += 1 531 532 start := p.Read - tagL 533 534 if e := p.Skip(wireType, opts.UseNativeSkip); e != nil { 535 return nil, wrapError(meta.ErrRead, "skip unknown field failed", e) 536 } 537 538 // maybe there are more unknown fields with the same field number such as unknown packed list or map 539 for p.Read < len(p.Buf) { 540 number, wt, tagLen, err := p.ConsumeTagWithoutMove() 541 if err != nil { 542 return nil, err 543 } 544 if number != fieldNumber { 545 break 546 } 547 p.Read += tagLen 548 if e := p.Skip(wt, opts.UseNativeSkip); e != nil { 549 return nil, wrapError(meta.ErrRead, "skip unknown field failed", e) 550 } 551 } 552 v.Node = self.slice(start, p.Read, proto.UNKNOWN) 553 554 *in = con 555 *lp = l 556 *cp = cap(con) 557 return v, nil 558 } 559 560 // Load loads self's all children ( and children's children if recurse is true) into self.Next, 561 // no matter whether self.Next is empty or set before (will be reset). 562 // NOTICE: if opts.NotScanParentNode is true, the parent nodes (PathNode.Node) of complex (map/list/struct) type won't be assgined data 563 func (self *PathNode) Load(recurse bool, opts *Options, desc *proto.TypeDescriptor) error { 564 if self == nil { 565 panic("nil PathNode") 566 } 567 if self.Error() != "" { 568 return self 569 } 570 self.Next = self.Next[:0] 571 p := binary.BinaryProtocol{ 572 Buf: self.Node.raw(), 573 } 574 // fd, ok := (*desc).(proto.Descriptor) 575 // if !ok { 576 // return wrapError(meta.ErrInvalidParam, "invalid descriptor", nil) 577 // } 578 return self.scanChildren(&p, recurse, opts, desc, len(p.Buf)) 579 } 580 581 func getDescByPath(root *proto.TypeDescriptor, pathes ...Path) (*proto.TypeDescriptor, error) { 582 desc := root 583 for i, p := range pathes { 584 if i == 0 { 585 switch p.Type() { 586 case PathFieldId: 587 f := desc.Message().ByNumber(p.id()) 588 if f == nil { 589 return nil, wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", p.id()), nil) 590 } 591 desc = f.Type() 592 case PathFieldName: 593 f := desc.Message().ByName(p.str()) 594 if f == nil { 595 return nil, wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %s", p.str()), nil) 596 } 597 desc = f.Type() 598 default: 599 return nil, wrapError(meta.ErrUnsupportedType, "unsupported path type", nil) 600 } 601 } else { 602 t := desc.Type() 603 switch t { 604 case proto.MESSAGE: 605 switch p.Type() { 606 case PathFieldId: 607 f := desc.Message().ByNumber(p.id()) 608 if f == nil { 609 return nil, wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", p.id()), nil) 610 } 611 desc = f.Type() 612 case PathFieldName: 613 f := desc.Message().ByName(p.str()) 614 if f == nil { 615 return nil, wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %s", p.str()), nil) 616 } 617 desc = f.Type() 618 default: 619 return nil, wrapError(meta.ErrUnsupportedType, "unsupported path type", nil) 620 } 621 case proto.MAP: 622 valueDesc := desc.Elem() 623 desc = valueDesc 624 case proto.LIST: 625 desc = desc.Elem() 626 default: 627 return nil, wrapError(meta.ErrInvalidParam, "unsupported path type", nil) 628 } 629 } 630 631 if desc == nil { 632 return nil, wrapError(meta.ErrNotFound, "descriptor is not found.", nil) 633 } 634 } 635 636 return desc, nil 637 } 638 639 func (self PathNode) Marshal(opt *Options) (out []byte, err error) { 640 p := binary.NewBinaryProtocolBuffer() 641 rootLayer := true // TODO: make rootLayer to be a parameter will be better 642 err = self.marshal(p, rootLayer, opt) 643 if err == nil { 644 out = make([]byte, len(p.Buf)) 645 copy(out, p.Buf) 646 } 647 binary.FreeBinaryProtocol(p) 648 return 649 } 650 651 func (self PathNode) marshal(p *binary.BinaryProtocol, rootLayer bool, opts *Options) error { 652 if self.IsError() { 653 return self.Node 654 } 655 656 // if node is basic type, Next[] is empty, directly append to buf 657 if len(self.Next) == 0 { 658 p.Buf = append(p.Buf, self.Node.raw()...) 659 return nil 660 } 661 662 var err error 663 664 switch self.Node.t { 665 case proto.MESSAGE: 666 pos := -1 667 // only root layer no need append message tag and write prefix length 668 if !rootLayer { 669 p.Buf, pos = binary.AppendSpeculativeLength(p.Buf) 670 if pos < 0 { 671 return wrapError(meta.ErrWrite, "PathNode.marshal: append speculative length failed", nil) 672 } 673 } 674 675 for _, v := range self.Next { 676 // when node type is not LIST/MAP write tag 677 if v.Node.t != proto.LIST && v.Node.t != proto.MAP && v.Node.t != proto.UNKNOWN { 678 err = p.AppendTag(v.Path.Id(), proto.Kind2Wire[v.Node.t.TypeToKind()]) 679 } 680 if err != nil { 681 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 682 } 683 684 if err = v.marshal(p, false, opts); err != nil { 685 return unwrapError(fmt.Sprintf("field %d marshal failed", v.Path.id()), err) 686 } 687 } 688 if !rootLayer { 689 p.Buf = binary.FinishSpeculativeLength(p.Buf, pos) 690 } 691 case proto.LIST: 692 et := self.et 693 filedNumber := self.Path.Id() 694 IsPacked := et.IsPacked() 695 pos := -1 696 // packed need first list tag and write prefix length 697 if IsPacked { 698 if err = p.AppendTag(filedNumber, proto.BytesType); err != nil { 699 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 700 } 701 p.Buf, pos = binary.AppendSpeculativeLength(p.Buf) 702 if pos < 0 { 703 return wrapError(meta.ErrWrite, "PathNode.marshal: append speculative length failed", nil) 704 } 705 } 706 707 for _, v := range self.Next { 708 // unpacked need append tag first 709 if !IsPacked { 710 if err = p.AppendTag(filedNumber, proto.Kind2Wire[v.Node.t.TypeToKind()]); err != nil { 711 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 712 } 713 } 714 715 if err = v.marshal(p, false, opts); err != nil { 716 return unwrapError(fmt.Sprintf("field %d marshal failed", v.Path.id()), err) 717 } 718 } 719 720 // packed mode need update prefix list length 721 if IsPacked { 722 p.Buf = binary.FinishSpeculativeLength(p.Buf, pos) 723 } 724 725 case proto.MAP: 726 kt := self.kt 727 et := self.et 728 filedNumber := self.Path.Id() 729 pos := -1 730 731 for _, v := range self.Next { 732 // append pair tag and write prefix length 733 if err = p.AppendTag(filedNumber, proto.BytesType); err != nil { 734 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 735 } 736 p.Buf, pos = binary.AppendSpeculativeLength(p.Buf) 737 if pos < 0 { 738 return wrapError(meta.ErrWrite, "PathNode.marshal: append speculative length failed", nil) 739 } 740 741 // write key tag + value 742 if kt == proto.STRING { 743 // Mapkey field number is 1 744 if err = p.AppendTag(1, proto.BytesType); err != nil { 745 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 746 } 747 748 if err = p.WriteString(v.Path.Str()); err != nil { 749 return wrapError(meta.ErrWrite, "PathNode.marshal: append string failed", err) 750 } 751 } else if kt.IsInt() { 752 wt := proto.Kind2Wire[kt.TypeToKind()] 753 // Mapkey field number is 1 754 if err = p.AppendTag(1, wt); err != nil { 755 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 756 } 757 758 if wt == proto.VarintType { 759 err = p.WriteInt64(int64(v.Path.int())) 760 } else if wt == proto.Fixed32Type { 761 err = p.WriteSfixed32(int32(v.Path.int())) 762 } else if wt == proto.Fixed64Type { 763 err = p.WriteSfixed64(int64(v.Path.int())) 764 } 765 if err != nil { 766 return wrapError(meta.ErrWrite, "PathNode.marshal: append int failed", err) 767 } 768 } else { 769 return wrapError(meta.ErrUnsupportedType, "PathNode.marshal: unsupported map key type", nil) 770 } 771 772 // if value is basic type, need append tag first 773 if v.Node.t != proto.LIST && v.Node.t != proto.MAP { 774 // MapValue field number is 2 775 if err = p.AppendTag(2, proto.Kind2Wire[et.TypeToKind()]); err != nil { 776 return wrapError(meta.ErrWrite, "PathNode.marshal: append tag failed", err) 777 } 778 } 779 780 if err = v.marshal(p, false, opts); err != nil { 781 return unwrapError(fmt.Sprintf("field %d marshal failed", v.Path.id()), err) 782 } 783 p.Buf = binary.FinishSpeculativeLength(p.Buf, pos) 784 } 785 case proto.BOOL, proto.INT32, proto.SINT32, proto.UINT32, proto.FIX32, proto.SFIX32, proto.INT64, proto.SINT64, proto.UINT64, proto.FIX64, proto.SFIX64, proto.FLOAT, proto.DOUBLE, proto.STRING, proto.BYTE: 786 p.Buf = append(p.Buf, self.Node.raw()...) 787 case proto.UNKNOWN: 788 // unknown bytes can also be marshaled, but we don't know its real type, so we can't read it, just skip it. 789 p.Buf = append(p.Buf, self.Node.raw()...) 790 default: 791 return wrapError(meta.ErrUnsupportedType, "PathNode.marshal: unsupported type", nil) 792 } 793 794 return err 795 } 796 797 798 // pathNode Slice Pool 799 type pnSlice struct { 800 a []PathNode 801 b []PathNode 802 } 803 804 func (self pnSlice) Len() int { 805 return len(self.a) 806 } 807 808 func (self *pnSlice) Swap(i, j int) { 809 self.a[i], self.a[j] = self.a[j], self.a[i] 810 self.b[i], self.b[j] = self.b[j], self.b[i] 811 } 812 813 func (self pnSlice) Less(i, j int) bool { 814 return int(uintptr(self.a[i].Node.v)) < int(uintptr(self.a[j].Node.v)) 815 } 816 817 func (self *pnSlice) Sort() { 818 sort.Sort(self) 819 }