github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/path.go (about) 1 /** 2 * Copyright 2023 CloudWeGo Authors. 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 generic 18 19 import ( 20 "fmt" 21 "sort" 22 "strconv" 23 "sync" 24 "unsafe" 25 26 "github.com/cloudwego/dynamicgo/internal/caching" 27 "github.com/cloudwego/dynamicgo/internal/rt" 28 "github.com/cloudwego/dynamicgo/meta" 29 "github.com/cloudwego/dynamicgo/thrift" 30 ) 31 32 // PathType is the type of path 33 type PathType uint8 34 35 const ( 36 // PathFieldId represents a field id of STRUCT type 37 PathFieldId PathType = 1 + iota 38 39 // PathFieldName represents a field name of STRUCT type 40 // NOTICE: it is only supported by Value 41 PathFieldName 42 43 // PathIndex represents a index of LIST\SET type 44 PathIndex 45 46 // Path represents a string key of MAP type 47 PathStrKey 48 49 // Path represents a int key of MAP type 50 PathIntKey 51 52 // Path represents a raw-bytes key of MAP type 53 // It is usually used for neither-string-nor-integer type key 54 PathBinKey 55 ) 56 57 // Path represents the relative position of a sub node in a complex parent node 58 type Path struct { 59 t PathType 60 v unsafe.Pointer 61 l int 62 } 63 64 // Str returns the string value of a PathFieldName\PathStrKey path 65 func (self Path) Str() string { 66 switch self.t { 67 case PathFieldName, PathStrKey: 68 return self.str() 69 default: 70 return "" 71 } 72 } 73 74 func (self Path) str() string { 75 return *(*string)(unsafe.Pointer(&self.v)) 76 } 77 78 // Int returns the int value of a PathIndex\PathIntKey path 79 func (self Path) Int() int { 80 switch self.t { 81 case PathIndex, PathIntKey: 82 return self.int() 83 default: 84 return -1 85 } 86 } 87 88 func (self Path) int() int { 89 return self.l 90 } 91 92 // Id returns the field id of a PathFieldId path 93 func (self Path) Id() thrift.FieldID { 94 switch self.t { 95 case PathFieldId: 96 return self.id() 97 default: 98 return thrift.FieldID(0) 99 } 100 } 101 102 func (self Path) id() thrift.FieldID { 103 return thrift.FieldID(self.l) 104 } 105 106 // Bin returns the raw bytes value of a PathBinKey path 107 func (self Path) Bin() []byte { 108 switch self.t { 109 case PathBinKey: 110 return self.bin() 111 default: 112 return nil 113 } 114 } 115 116 func (self Path) bin() []byte { 117 return rt.BytesFrom(self.v, self.l, self.l) 118 } 119 120 // ToRaw converts underlying value to thrift-encoded bytes 121 func (self Path) ToRaw(t thrift.Type) []byte { 122 switch self.t { 123 case PathFieldId: 124 ret := make([]byte, 3, 3) 125 thrift.BinaryEncoding{}.EncodeByte(ret, byte(t)) 126 thrift.BinaryEncoding{}.EncodeInt16(ret[1:], int16(self.l)) 127 return ret 128 case PathStrKey: 129 ret := make([]byte, 4+self.l, 4+self.l) 130 thrift.BinaryEncoding{}.EncodeString(ret, self.str()) 131 return ret 132 case PathIntKey: 133 switch t { 134 case thrift.I08: 135 ret := make([]byte, 1, 1) 136 thrift.BinaryEncoding{}.EncodeByte(ret, byte(self.l)) 137 return ret 138 case thrift.I16: 139 ret := make([]byte, 2, 2) 140 thrift.BinaryEncoding{}.EncodeInt16(ret, int16(self.l)) 141 return ret 142 case thrift.I32: 143 ret := make([]byte, 4, 4) 144 thrift.BinaryEncoding{}.EncodeInt32(ret, int32(self.l)) 145 return ret 146 case thrift.I64: 147 ret := make([]byte, 8, 8) 148 thrift.BinaryEncoding{}.EncodeInt64(ret, int64(self.l)) 149 return ret 150 default: 151 return nil 152 } 153 case PathBinKey: 154 return rt.BytesFrom(self.v, self.l, self.l) 155 default: 156 return nil 157 } 158 } 159 160 // String returns the string representation of a Path 161 func (self Path) String() string { 162 switch self.t { 163 case PathFieldId: 164 return "FieldId(" + strconv.Itoa(int(self.id())) + ")" 165 case PathFieldName: 166 return "FieldName(\"" + self.str() + "\")" 167 case PathIndex: 168 return "Index(" + strconv.Itoa(self.int()) + ")" 169 case PathStrKey: 170 return "Key(\"" + self.str() + "\")" 171 case PathIntKey: 172 return "Key(" + strconv.Itoa(self.int()) + ")" 173 case PathBinKey: 174 return "Key(" + fmt.Sprintf("%x", self.bin()) + ")" 175 default: 176 return fmt.Sprintf("unsupported path %#v", self) 177 } 178 } 179 180 // Type returns the type of a Path 181 func (self Path) Type() PathType { 182 return self.t 183 } 184 185 // Value returns the equivalent go interface of a Path 186 func (self Path) Value() interface{} { 187 switch self.t { 188 case PathFieldId: 189 return self.id() 190 case PathFieldName, PathStrKey: 191 return self.str() 192 case PathIndex, PathIntKey: 193 return self.int() 194 case PathBinKey: 195 return self.bin() 196 default: 197 return nil 198 } 199 } 200 201 // NewPathFieldId creates a PathFieldId path 202 func NewPathFieldId(id thrift.FieldID) Path { 203 return Path{ 204 t: PathFieldId, 205 l: int(id), 206 } 207 } 208 209 // NewPathFieldName creates a PathFieldName path 210 func NewPathFieldName(name string) Path { 211 return Path{ 212 t: PathFieldName, 213 v: *(*unsafe.Pointer)(unsafe.Pointer(&name)), 214 l: len(name), 215 } 216 } 217 218 // NewPathIndex creates a PathIndex path 219 func NewPathIndex(index int) Path { 220 return Path{ 221 t: PathIndex, 222 l: index, 223 } 224 } 225 226 // NewPathStrKey creates a PathStrKey path 227 func NewPathStrKey(key string) Path { 228 return Path{ 229 t: PathStrKey, 230 v: *(*unsafe.Pointer)(unsafe.Pointer(&key)), 231 l: len(key), 232 } 233 } 234 235 // NewPathIntKey creates a PathIntKey path 236 func NewPathIntKey(key int) Path { 237 return Path{ 238 t: PathIntKey, 239 l: key, 240 } 241 } 242 243 // NewPathBinKey creates a PathBinKey path 244 func NewPathBinKey(key []byte) Path { 245 return Path{ 246 t: PathBinKey, 247 v: *(*unsafe.Pointer)(unsafe.Pointer(&key)), 248 l: len(key), 249 } 250 } 251 252 // GetDescByPath searches longitudinally and returns the sub descriptor of the desc specified by path 253 func GetDescByPath(desc *thrift.TypeDescriptor, path ...Path) (ret *thrift.TypeDescriptor, err error) { 254 ret = desc 255 for _, p := range path { 256 switch desc.Type() { 257 case thrift.STRUCT: 258 switch p.Type() { 259 case PathFieldId: 260 f := desc.Struct().FieldById(thrift.FieldID(p.l)) 261 if f == nil { 262 return nil, errNode(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", p.l), nil) 263 } 264 ret = f.Type() 265 case PathFieldName: 266 f := desc.Struct().FieldByKey(p.str()) 267 if f == nil { 268 return nil, errNode(meta.ErrUnknownField, fmt.Sprintf("unknown field %s", p.str()), nil) 269 } 270 ret = f.Type() 271 default: 272 return nil, errNode(meta.ErrInvalidParam, "", nil) 273 } 274 case thrift.LIST, thrift.SET, thrift.MAP: 275 ret = desc.Elem() 276 default: 277 return nil, errNode(meta.ErrUnsupportedType, "", err) 278 } 279 if ret == nil { 280 return nil, errNode(meta.ErrNotFound, "", err) 281 } 282 } 283 return 284 } 285 286 // PathNode is a three node of DOM tree 287 type PathNode struct { 288 Path 289 Node 290 Next []PathNode 291 } 292 293 var pathNodePool = sync.Pool{ 294 New: func() interface{} { 295 return &PathNode{} 296 }, 297 } 298 299 // NewPathNode get a new PathNode from memory pool 300 func NewPathNode() *PathNode { 301 return pathNodePool.Get().(*PathNode) 302 } 303 304 // FreePathNode put a PathNode back to memory pool 305 func FreePathNode(p *PathNode) { 306 p.Path = Path{} 307 p.Node = Node{} 308 p.Next = p.Next[:0] 309 pathNodePool.Put(p) 310 } 311 312 // DescriptorToPathNode converts a thrift type descriptor to a DOM, assgining path to root 313 // NOTICE: it only recursively converts STRUCT type 314 func DescriptorToPathNode(desc *thrift.TypeDescriptor, root *PathNode, opts *Options) error { 315 return descriptorToPathNode(0, desc, root, opts) 316 } 317 318 func descriptorToPathNode(recurse int, desc *thrift.TypeDescriptor, root *PathNode, opts *Options) error { 319 if opts.DescriptorToPathNodeMaxDepth > 0 && recurse > opts.DescriptorToPathNodeMaxDepth { 320 return nil 321 } 322 if desc == nil || root == nil { 323 panic("nil pointer") 324 } 325 t := desc.Type() 326 root.Node.t = t 327 if t == thrift.STRUCT { 328 fs := desc.Struct().Fields() 329 ns := root.Next 330 if cap(ns) == 0 { 331 ns = make([]PathNode, 0, len(fs)) 332 } else { 333 ns = ns[:0] 334 } 335 for _, f := range fs { 336 if f.Required() == thrift.OptionalRequireness && !opts.DescriptorToPathNodeWriteOptional { 337 continue 338 } 339 if f.Required() == thrift.DefaultRequireness && !opts.DescriptorToPathNodeWriteDefualt { 340 continue 341 } 342 var p PathNode 343 // if opts.FieldByName { 344 // p.Path = NewPathFieldName(f.Name()) 345 // } else { 346 p.Path = NewPathFieldId(f.ID()) 347 // println("field: ", f.ID()) 348 // } 349 if err := descriptorToPathNode(recurse+1, f.Type(), &p, opts); err != nil { 350 return err 351 } 352 ns = append(ns, p) 353 } 354 root.Next = ns 355 } else if t == thrift.LIST || t == thrift.SET { 356 if opts.DescriptorToPathNodeArraySize > 0 { 357 next := make([]PathNode, opts.DescriptorToPathNodeArraySize) 358 for i := range next { 359 next[i].Path = NewPathIndex(i) 360 if err := descriptorToPathNode(recurse+1, desc.Elem(), &next[i], opts); err != nil { 361 return err 362 } 363 } 364 root.Next = next 365 root.Node.et = desc.Elem().Type() 366 } 367 } else if t == thrift.MAP { 368 if opts.DescriptorToPathNodeMapSize > 0 { 369 next := make([]PathNode, opts.DescriptorToPathNodeMapSize) 370 for i := range next { 371 if ty := desc.Key().Type(); ty.IsInt() { 372 next[i].Path = NewPathIntKey(i) // NOTICE: use index as int key here 373 } else if ty == thrift.STRING { 374 next[i].Path = NewPathStrKey(strconv.Itoa(i)) // NOTICE: use index as string key here 375 } else { 376 buf := thrift.NewBinaryProtocol([]byte{}) 377 _ = buf.WriteEmpty(desc.Key()) // NOTICE: use emtpy value as binary key here 378 next[i].Path = NewPathBinKey(buf.Buf) 379 } 380 if err := descriptorToPathNode(recurse+1, desc.Elem(), &next[i], opts); err != nil { 381 return err 382 } 383 } 384 root.Next = next 385 root.Node.kt = desc.Key().Type() 386 root.Node.et = desc.Elem().Type() 387 } 388 } else { 389 // println("type: ", desc.Type().String()) 390 buf := thrift.NewBinaryProtocol([]byte{}) 391 _ = buf.WriteEmpty(desc) 392 root.Node = NewNode(desc.Type(), buf.Buf) 393 } 394 return nil 395 } 396 397 // PathNodeToInterface convert a pathnode to a interface 398 func PathNodeToInterface(tree PathNode, opts *Options, useParent bool) interface{} { 399 switch tree.Node.Type() { 400 case thrift.STRUCT: 401 if len(tree.Next) == 0 && useParent { 402 vv, err := tree.Node.Interface(opts) 403 if err != nil { 404 panic(err) 405 } 406 return vv 407 } 408 ret := make(map[int]interface{}, len(tree.Next)) 409 for _, v := range tree.Next { 410 vv := PathNodeToInterface(v, opts, useParent) 411 if vv == nil { 412 continue 413 } 414 ret[int(v.Path.Id())] = vv 415 } 416 return ret 417 case thrift.LIST, thrift.SET: 418 if len(tree.Next) == 0 && useParent { 419 vv, err := tree.Node.Interface(opts) 420 if err != nil { 421 panic(err) 422 } 423 return vv 424 } 425 ret := make([]interface{}, len(tree.Next)) 426 for _, v := range tree.Next { 427 vv := PathNodeToInterface(v, opts, useParent) 428 if vv == nil { 429 continue 430 } 431 ret[v.Path.Int()] = vv 432 } 433 return ret 434 case thrift.MAP: 435 if len(tree.Next) == 0 && useParent { 436 vv, err := tree.Node.Interface(opts) 437 if err != nil { 438 panic(err) 439 } 440 return vv 441 } 442 if kt := tree.Node.kt; kt == thrift.STRING { 443 ret := make(map[string]interface{}, len(tree.Next)) 444 for _, v := range tree.Next { 445 vv := PathNodeToInterface(v, opts, useParent) 446 if vv == nil { 447 continue 448 } 449 ret[v.Path.Str()] = vv 450 } 451 return ret 452 } else if kt.IsInt() { 453 ret := make(map[int]interface{}, len(tree.Next)) 454 for _, v := range tree.Next { 455 vv := PathNodeToInterface(v, opts, useParent) 456 if vv == nil { 457 continue 458 } 459 ret[v.Path.Int()] = vv 460 } 461 return ret 462 } else { 463 ret := make(map[interface{}]interface{}, len(tree.Next)) 464 for _, v := range tree.Next { 465 kp := PathNode{ 466 Node: NewNode(kt, v.Path.Bin()), 467 } 468 kv := PathNodeToInterface(kp, opts, true) 469 if kv == nil { 470 continue 471 } 472 vv := PathNodeToInterface(v, opts, useParent) 473 if vv == nil { 474 continue 475 } 476 switch x := kv.(type) { 477 case map[string]interface{}: 478 ret[&x] = vv 479 case map[int]interface{}: 480 ret[&x] = vv 481 case map[interface{}]interface{}: 482 ret[&x] = vv 483 case []interface{}: 484 ret[&x] = vv 485 default: 486 ret[kv] = vv 487 } 488 } 489 return ret 490 } 491 case thrift.STOP: 492 return nil 493 default: 494 ret, err := tree.Node.Interface(opts) 495 if err != nil { 496 panic(err) 497 } 498 return ret 499 } 500 } 501 502 // Assgin assigns self's raw Value according to its Next Path, 503 // which must be set before calling this method. 504 func (self *PathNode) Assgin(recurse bool, opts *Options) error { 505 if self.Node.IsError() { 506 return self.Node 507 } 508 if len(self.Next) == 0 { 509 return nil 510 } 511 if err := self.Node.GetMany(self.Next, opts); err != nil { 512 return err 513 } 514 if !recurse { 515 return nil 516 } 517 for _, n := range self.Next { 518 if n.Node.IsEmpty() { 519 continue 520 } 521 if err := n.assgin(_SkipMaxDepth, opts); err != nil { 522 return err 523 } 524 } 525 return nil 526 } 527 528 func (self *PathNode) assgin(depth int, opts *Options) error { 529 if self.Node.IsError() { 530 return self.Node 531 } 532 if len(self.Next) == 0 || depth == 0 { 533 return nil 534 } 535 if err := self.Node.GetMany(self.Next, opts); err != nil { 536 return err 537 } 538 for _, n := range self.Next { 539 if n.Node.IsEmpty() { 540 continue 541 } 542 if err := n.assgin(depth-1, opts); err != nil { 543 break 544 } 545 } 546 return nil 547 } 548 549 // Load loads self's all children ( and children's children if recurse is true) into self.Next, 550 // no matter whether self.Next is empty or set before (will be reset). 551 // NOTICE: if opts.NotScanParentNode is true, the parent nodes (PathNode.Node) of complex (map/list/struct) type won't be assgined data 552 func (self *PathNode) Load(recurse bool, opts *Options) error { 553 if self == nil { 554 panic("nil PathNode") 555 } 556 if self.Error() != "" { 557 return self 558 } 559 self.Next = self.Next[:0] 560 p := thrift.BinaryProtocol{ 561 Buf: self.Node.raw(), 562 } 563 return self.scanChildren(&p, recurse, opts) 564 } 565 566 // Fork deeply copy self and its children to a new PathNode 567 func (self PathNode) Fork() PathNode { 568 n := PathNode{ 569 Path: self.Path, 570 Node: self.Node, 571 } 572 for _, c := range self.Next { 573 n.Next = append(n.Next, c.Fork()) 574 } 575 return n 576 } 577 578 // CopyTo deeply copy self and its children to a PathNode 579 func (self PathNode) CopyTo(to *PathNode) { 580 to.Path = self.Path 581 to.Node = self.Node 582 if cap(to.Next) < len(self.Next) { 583 to.Next = make([]PathNode, len(self.Next)) 584 } 585 to.Next = to.Next[:len(self.Next)] 586 for i, c := range self.Next { 587 c.CopyTo(&to.Next[i]) 588 } 589 } 590 591 // ResetValue resets self's node and its children's node 592 func (self *PathNode) ResetValue() { 593 self.Node = Node{} 594 for i := range self.Next { 595 self.Next[i].ResetValue() 596 } 597 } 598 599 // ResetAll resets self and its children, including path and node both 600 func (self *PathNode) ResetAll() { 601 for i := range self.Next { 602 self.Next[i].ResetAll() 603 } 604 self.Node = Node{} 605 self.Path = Path{} 606 self.Next = self.Next[:0] 607 } 608 609 // Marshal marshals self to thrift bytes 610 func (self PathNode) Marshal(opt *Options) (out []byte, err error) { 611 p := thrift.NewBinaryProtocolBuffer() 612 err = self.marshal(p, opt) 613 if err == nil { 614 out = make([]byte, len(p.Buf)) 615 copy(out, p.Buf) 616 } 617 thrift.FreeBinaryProtocolBuffer(p) 618 return 619 } 620 621 // MarshalIntoBuffer marshals self to thrift bytes into a buffer 622 func (self PathNode) MarshalIntoBuffer(out *[]byte, opt *Options) error { 623 p := thrift.BinaryProtocol{ 624 Buf: *out, 625 } 626 if err := self.marshal(&p, opt); err != nil { 627 return err 628 } 629 *out = p.Buf 630 return nil 631 } 632 633 func (self PathNode) marshal(p *thrift.BinaryProtocol, opts *Options) error { 634 if self.IsError() { 635 return self.Node 636 } 637 if len(self.Next) == 0 { 638 p.Buf = append(p.Buf, self.raw()...) 639 return nil 640 } 641 642 var err error 643 // desc := self.Node.d 644 switch self.Node.t { 645 case thrift.STRUCT: 646 // err = p.WriteStructBegin("") 647 // if err != nil { 648 // return wrapError(meta.ErrWrite, "", err) 649 // } 650 for _, v := range self.Next { 651 // NOTICE: we skip if the value is empty. 652 if v.IsEmpty() { 653 continue 654 } 655 err = p.WriteFieldBegin("", v.Node.t, (v.Path.id())) 656 if err != nil { 657 return wrapError(meta.ErrWrite, "", err) 658 } 659 if err = v.marshal(p, opts); err != nil { 660 return unwrapError(fmt.Sprintf("field %d marshal failed", v.Path.id()), err) 661 } 662 err = p.WriteFieldEnd() 663 } 664 // NOTICE: we don't check if required fields unset. 665 err = p.WriteStructEnd() 666 if err != nil { 667 return wrapError(meta.ErrWrite, "", err) 668 } 669 case thrift.LIST, thrift.SET: 670 size := len(self.Next) 671 rewrite, err := p.WriteListBeginWithSizePos(self.et, size) 672 // if found emtpy value, we must rewite size 673 if err != nil { 674 return wrapError(meta.ErrWrite, "", err) 675 } 676 for _, v := range self.Next { 677 // NOTICE: we rewite list size if the value is empty. 678 if v.IsEmpty() { 679 size -= 1 680 p.ModifyI32(rewrite, int32(size)) 681 continue 682 } 683 if err = v.marshal(p, opts); err != nil { 684 return unwrapError(fmt.Sprintf("element %v of list marshal failed", v.Path.v), err) 685 } 686 } 687 // err = p.WriteSetEnd() 688 // if err != nil { 689 // return wrapError(meta.ErrWrite, "", err) 690 // } 691 case thrift.MAP: 692 size := len(self.Next) 693 rewrite, err := p.WriteMapBeginWithSizePos(self.kt, self.et, len(self.Next)) 694 if err != nil { 695 return wrapError(meta.ErrWrite, "", err) 696 } 697 if kt := self.kt; kt == thrift.STRING { 698 for _, v := range self.Next { 699 // NOTICE: we skip if the value is empty. 700 if v.IsEmpty() { 701 size -= 1 702 p.ModifyI32(rewrite, int32(size)) 703 continue 704 } 705 if v.Path.Type() != PathStrKey { 706 return errNode(meta.ErrDismatchType, "path key must be string", nil) 707 } 708 if err = p.WriteString(v.Path.str()); err != nil { 709 return wrapError(meta.ErrWrite, fmt.Sprintf("key %v of map marshal failed", v.Path.str()), err) 710 } 711 if err = v.marshal(p, opts); err != nil { 712 return unwrapError(fmt.Sprintf("element %v marshal failed", v.Path.str()), err) 713 } 714 } 715 716 } else if kt.IsInt() { 717 for _, v := range self.Next { 718 // NOTICE: we skip if the value is empty. 719 if v.IsEmpty() { 720 size -= 1 721 p.ModifyI32(rewrite, int32(size)) 722 continue 723 } 724 if v.Path.Type() != PathIntKey { 725 return errNode(meta.ErrDismatchType, "path key must be int", nil) 726 } 727 if err = p.WriteInt(kt, v.Path.int()); err != nil { 728 return wrapError(meta.ErrWrite, fmt.Sprintf("key %v of map marshal failed", v.Path.int()), err) 729 } 730 if err = v.marshal(p, opts); err != nil { 731 return unwrapError(fmt.Sprintf("element %v marshal failed", v.Path.int()), err) 732 } 733 } 734 } else { 735 for _, v := range self.Next { 736 // NOTICE: we skip if the value is empty. 737 if v.IsEmpty() { 738 size -= 1 739 p.ModifyI32(rewrite, int32(size)) 740 continue 741 } 742 if v.Path.Type() != PathBinKey { 743 return errNode(meta.ErrDismatchType, "path key must be binary", nil) 744 } 745 p.Buf = append(p.Buf, v.Path.bin()...) 746 if err = v.marshal(p, opts); err != nil { 747 return unwrapError(fmt.Sprintf("element %v marshal failed", v.Path.bin()), err) 748 } 749 } 750 } 751 // err = p.WriteMapEnd() 752 // if err != nil { 753 // return wrapError(meta.ErrWrite, "", err) 754 // } 755 756 case thrift.BOOL, thrift.I08, thrift.I16, thrift.I32, thrift.I64, thrift.DOUBLE, thrift.STRING: 757 p.Buf = append(p.Buf, self.raw()...) 758 default: 759 return meta.NewError(meta.ErrUnsupportedType, "", nil) 760 } 761 762 return err 763 } 764 765 func guardPathNodeSlice(con *[]PathNode, l int) { 766 c := cap(*con) 767 if l >= c { 768 tmp := make([]PathNode, len(*con), l+DefaultNodeSliceCap) 769 copy(tmp, *con) 770 *con = tmp 771 } 772 } 773 774 type pnSlice struct { 775 a []PathNode 776 b []PathNode 777 } 778 779 func (self pnSlice) Len() int { 780 return len(self.a) 781 } 782 783 func (self *pnSlice) Swap(i, j int) { 784 self.a[i], self.a[j] = self.a[j], self.a[i] 785 self.b[i], self.b[j] = self.b[j], self.b[i] 786 } 787 788 func (self pnSlice) Less(i, j int) bool { 789 return int(uintptr(self.a[i].Node.v)) < int(uintptr(self.a[j].Node.v)) 790 } 791 792 func (self *pnSlice) Sort() { 793 sort.Sort(self) 794 } 795 func (self *PathNode) handleChild(in *[]PathNode, lp *int, cp *int, p *thrift.BinaryProtocol, recurse bool, opts *Options, et thrift.Type) (*PathNode, error) { 796 var con = *in 797 var l = *lp 798 guardPathNodeSlice(&con, l) 799 if l >= len(con) { 800 con = con[:l+1] 801 } 802 v := &con[l] 803 l += 1 804 805 ss := p.Read 806 buf := p.Buf 807 808 if recurse && (et.IsComplex() && opts.NotScanParentNode) { 809 v.Node = Node{ 810 t: et, 811 l: 0, 812 v: unsafe.Pointer(uintptr(self.Node.v) + uintptr(ss)), 813 } 814 } else { 815 if e := p.Skip(et, opts.UseNativeSkip); e != nil { 816 return nil, errNode(meta.ErrRead, "", e) 817 } 818 v.Node = self.slice(ss, p.Read, et) 819 } 820 821 if recurse && et.IsComplex() { 822 p.Buf = p.Buf[ss:] 823 p.Read = 0 824 if err := v.scanChildren(p, recurse, opts); err != nil { 825 return nil, err 826 } 827 p.Buf = buf 828 p.Read = ss + p.Read 829 } 830 831 *in = con 832 *lp = l 833 *cp = cap(con) 834 return v, nil 835 } 836 837 // Error returns non-empty string if the PathNode has error 838 func (self PathNode) Error() string { 839 return self.Node.Error() 840 } 841 842 // Check returns non-nil error if the PathNode has error 843 func (self *PathNode) Check() error { 844 if self == nil { 845 return errNotFound 846 } 847 if self.Node.t == thrift.ERROR { 848 return self 849 } 850 return nil 851 } 852 853 func (self *PathNode) should(op string, t thrift.Type) *PathNode { 854 if self == nil { 855 return errPathNode(meta.ErrNotFound, op, nil) 856 } 857 if self.Node.t != t { 858 return errPathNode(meta.ErrDismatchType, op, nil) 859 } 860 return nil 861 } 862 863 func (self *PathNode) should2(op string, t thrift.Type, t2 thrift.Type) *PathNode { 864 if self == nil { 865 return errPathNode(meta.ErrNotFound, op, nil) 866 } 867 if self.Node.t != t && self.Node.t != t2 { 868 return errPathNode(meta.ErrDismatchType, op, nil) 869 } 870 return nil 871 } 872 873 func getStrHash(next *[]PathNode, key string, N int) *PathNode { 874 h := int(caching.StrHash(key) % uint64(N)) 875 s := (*PathNode)(rt.IndexPtr(*(*unsafe.Pointer)(unsafe.Pointer(next)), sizePathNode, h)) 876 for s.Path.t == PathStrKey { 877 if s.Path.str() == key { 878 return s 879 } 880 h = (h + 1) % N 881 s = (*PathNode)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + sizePathNode)) 882 } 883 return nil 884 } 885 886 func seekIntHash(next unsafe.Pointer, key uint64, N int) int { 887 h := int(key % uint64(N)) 888 s := (*PathNode)(rt.IndexPtr(next, sizePathNode, h)) 889 for s.Path.t != 0 { 890 h = (h + 1) % N 891 s = (*PathNode)(rt.AddPtr(unsafe.Pointer(s), sizePathNode)) 892 } 893 return h 894 } 895 896 func getIntHash(next *[]PathNode, key uint64, N int) *PathNode { 897 h := int(key % uint64(N)) 898 s := (*PathNode)(rt.IndexPtr(*(*unsafe.Pointer)(unsafe.Pointer(next)), sizePathNode, h)) 899 for s.Path.t == PathIntKey { 900 if uint64(s.Path.int()) == key { 901 return s 902 } 903 h = (h + 1) % N 904 s = (*PathNode)(rt.AddPtr(unsafe.Pointer(s), sizePathNode)) 905 } 906 return nil 907 } 908 909 // GetByInt get the child node by string. Only support MAP with string-type key. 910 // 911 // If opts.StoreChildrenByHash is true, it will try to use hash (O(1)) to search the key. 912 // However, if the map size has changed, it may fallback to O(n) search. 913 func (self *PathNode) GetByStr(key string, opts *Options) *PathNode { 914 if err := self.should("GetStrKey() only support MAP", thrift.MAP); err != nil { 915 return err 916 } 917 if self.Node.kt != thrift.STRING { 918 return errPathNode(meta.ErrDismatchType, "GetStrKey() only support MAP with string key", nil) 919 } 920 // fast path: use hash to find the key. 921 if opts.StoreChildrenByHash { 922 n, _ := self.Node.len() 923 N := n * 2 924 // TODO: cap may change after Set. Use better way to store hash size 925 if cap(self.Next) >= N { 926 if s := getStrHash(&self.Next, key, N); s != nil { 927 return s 928 } 929 } 930 // not find, maybe hash size has changed, try to search from the beginning. 931 } 932 for i := range self.Next { 933 v := &self.Next[i] 934 if v.Path.t == PathStrKey && v.Path.str() == key { 935 return v 936 } 937 } 938 return nil 939 } 940 941 // SetByStr set the child node by string. Only support MAP with string-type key. 942 // If the key already exists, it will be overwritten and return true. 943 // 944 // If opts.StoreChildrenByHash is true, it will try to use hash (O(1)) to search the key. 945 // However, if the map hash size has changed, it may fallback to O(n) search. 946 func (self *PathNode) SetByStr(key string, val Node, opts *Options) (bool, error) { 947 if err := self.should("SetStrKey() only support MAP", thrift.MAP); err != nil { 948 return false, err 949 } 950 if self.Node.kt != thrift.STRING { 951 return false, errPathNode(meta.ErrDismatchType, "GetStrKey() only support MAP with string key", nil) 952 } 953 // fast path: use hash to find the key. 954 if opts.StoreChildrenByHash { 955 n, _ := self.Node.len() 956 N := n * 2 957 // TODO: cap may change after Set. Use better way to store hash size 958 if cap(self.Next) >= N { 959 if s := getStrHash(&self.Next, key, N); s != nil { 960 s.Node = val 961 return true, nil 962 } 963 } 964 // not find, maybe hash size has changed, try to search from the beginning. 965 } 966 for i := range self.Next { 967 v := &self.Next[i] 968 if v.Path.t == PathStrKey && v.Path.str() == key { 969 v.Node = val 970 return true, nil 971 } 972 } 973 self.Next = append(self.Next, PathNode{ 974 Path: NewPathStrKey(key), 975 Node: val, 976 }) 977 return false, nil 978 } 979 980 // GetByInt get the child node by integer. Only support MAP with integer-type key. 981 // 982 // If opts.StoreChildrenByHash is true, it will try to use hash (O(1)) to search the key. 983 // However, if the map size has changed, it may fallback to O(n) search. 984 func (self *PathNode) GetByInt(key int, opts *Options) *PathNode { 985 if err := self.should("GetByInt() only support MAP", thrift.MAP); err != nil { 986 return err 987 } 988 if !self.Node.kt.IsInt() { 989 return errPathNode(meta.ErrDismatchType, "GetByInt() only support MAP with integer key", nil) 990 } 991 // fast path: use hash to find the key. 992 if opts.StoreChildrenByHash { 993 // TODO: size may change after Set. Use better way to store hash size 994 n, _ := self.Node.len() 995 N := n * 2 996 if cap(self.Next) >= N { 997 if s := getIntHash(&self.Next, uint64(key), N); s != nil { 998 return s 999 } 1000 } 1001 // not find, maybe hash size has changed, try to search from the beginning. 1002 } 1003 for i := range self.Next { 1004 v := &self.Next[i] 1005 if v.Path.t == PathIntKey && v.Path.int() == key { 1006 return v 1007 } 1008 } 1009 return nil 1010 } 1011 1012 // SetByInt set the child node by integer. Only support MAP with integer-type key. 1013 // If the key already exists, it will be overwritten and return true. 1014 // 1015 // If opts.StoreChildrenByHash is true, it will try to use hash (O(1)) to search the key. 1016 // However, if the map hash size has changed, it may fallback to O(n) search. 1017 func (self *PathNode) SetByInt(key int, val Node, opts *Options) (bool, error) { 1018 if err := self.should("SetByInt() only support MAP", thrift.MAP); err != nil { 1019 return false, err 1020 } 1021 if !self.Node.kt.IsInt() { 1022 return false, errPathNode(meta.ErrDismatchType, "SetByInt() only support MAP with integer key", nil) 1023 } 1024 // fast path: use hash to find the key. 1025 if opts.StoreChildrenByHash { 1026 n, _ := self.Node.len() 1027 N := n * 2 1028 if cap(self.Next) >= N { 1029 if s := getIntHash(&self.Next, uint64(key), N); s != nil { 1030 s.Node = val 1031 return true, nil 1032 } 1033 } 1034 // not find, maybe hash size has changed, try to search from the beginning. 1035 } 1036 for i := range self.Next { 1037 v := &self.Next[i] 1038 if v.Path.t == PathIntKey && v.Path.int() == key { 1039 v.Node = val 1040 return true, nil 1041 } 1042 } 1043 self.Next = append(self.Next, PathNode{ 1044 Path: NewPathIntKey(key), 1045 Node: val, 1046 }) 1047 return false, nil 1048 } 1049 1050 // Field get the child node by field id. Only support STRUCT. 1051 // 1052 // If opts.StoreChildrenById is true, it will try to use id (O(1)) as index to search the key. 1053 // However, if the struct fields have changed, it may fallback to O(n) search. 1054 func (self *PathNode) Field(id thrift.FieldID, opts *Options) *PathNode { 1055 if err := self.should("GetById() only support STRUCT", thrift.STRUCT); err != nil { 1056 return err 1057 } 1058 // fast path: use id to find the key. 1059 if opts.StoreChildrenById && int(id) <= StoreChildrenByIdShreshold { 1060 v := &self.Next[id] 1061 if v.Path.t != 0 && v.Path.id() == id { 1062 return v 1063 } 1064 } 1065 // slow path: use linear search to find the id. 1066 for i := StoreChildrenByIdShreshold; i < len(self.Next); i++ { 1067 v := &self.Next[i] 1068 if v.Path.t == PathFieldId && v.Path.id() == id { 1069 return v 1070 } 1071 } 1072 for i := 0; i < len(self.Next) && i < StoreChildrenByIdShreshold; i++ { 1073 v := &self.Next[i] 1074 if v.Path.t == PathFieldId && v.Path.id() == id { 1075 return v 1076 } 1077 } 1078 return nil 1079 } 1080 1081 // SetField set the child node by field id. Only support STRUCT. 1082 // If the key already exists, it will be overwritten and return true. 1083 // 1084 // If opts.StoreChildrenById is true, it will try to use id (O(1)) as index to search the key. 1085 // However, if the struct fields have changed, it may fallback to O(n) search. 1086 func (self *PathNode) SetField(id thrift.FieldID, val Node, opts *Options) (bool, error) { 1087 if err := self.should("GetById() only support STRUCT", thrift.STRUCT); err != nil { 1088 return false, err 1089 } 1090 // fast path: use id to find the key. 1091 if opts.StoreChildrenById && int(id) <= StoreChildrenByIdShreshold { 1092 v := &self.Next[id] 1093 exist := v.Path.t != 0 1094 v.Node = val 1095 return exist, nil 1096 } 1097 // slow path: use linear search to find the id. 1098 for i := StoreChildrenByIdShreshold; i < len(self.Next); i++ { 1099 v := &self.Next[i] 1100 if v.Path.t == PathFieldId && v.Path.id() == id { 1101 v.Node = val 1102 return true, nil 1103 } 1104 } 1105 for i := 0; i < len(self.Next) && i < StoreChildrenByIdShreshold; i++ { 1106 v := &self.Next[i] 1107 if v.Path.t == PathFieldId && v.Path.id() == id { 1108 v.Node = val 1109 return true, nil 1110 } 1111 } 1112 // not find, append to the end. 1113 self.Next = append(self.Next, PathNode{ 1114 Path: NewPathFieldId(id), 1115 Node: val, 1116 }) 1117 return false, nil 1118 } 1119 1120 func (self *PathNode) scanChildren(p *thrift.BinaryProtocol, recurse bool, opts *Options) error { 1121 var con = self.Next[:0] 1122 var v *PathNode 1123 var err error 1124 l := len(con) 1125 c := cap(con) 1126 1127 var tp = StoreChildrenByIdShreshold 1128 switch self.Node.t { 1129 case thrift.STRUCT: 1130 // name, err := p.ReadStructBegin() 1131 for { 1132 _, et, id, e := p.ReadFieldBegin() 1133 if e != nil { 1134 return errNode(meta.ErrRead, "", e) 1135 } 1136 if et == thrift.STOP { 1137 break 1138 } 1139 // OPT: store children by id here, thus we can use id as index to access children. 1140 if opts.StoreChildrenById { 1141 // if id is larger than the threshold, we store children after the threshold. 1142 if int(id) < StoreChildrenByIdShreshold { 1143 l = int(id) 1144 } else { 1145 l = tp 1146 tp += 1 1147 } 1148 } 1149 v, err = self.handleChild(&con, &l, &c, p, recurse, opts, et) 1150 if err != nil { 1151 return err 1152 } 1153 v.Path = NewPathFieldId(thrift.FieldID(id)) 1154 } 1155 case thrift.LIST, thrift.SET: 1156 et, size, e := p.ReadListBegin() 1157 if e != nil { 1158 return errNode(meta.ErrRead, "", e) 1159 } 1160 self.et = et 1161 for i := 0; i < size; i++ { 1162 v, err = self.handleChild(&con, &l, &c, p, recurse, opts, et) 1163 if err != nil { 1164 return err 1165 } 1166 v.Path = NewPathIndex(i) 1167 } 1168 case thrift.MAP: 1169 kt, et, size, e := p.ReadMapBegin() 1170 if e != nil { 1171 return errNode(meta.ErrRead, "", e) 1172 } 1173 1174 self.et = et 1175 self.kt = kt 1176 var conAddr unsafe.Pointer 1177 var N int 1178 1179 if kt == thrift.STRING { 1180 // fast path: use hash to store the key. 1181 if opts.StoreChildrenByHash && size > StoreChildrenByIntHashShreshold { 1182 // NOTE: we use original count*2 as the capacity of the hash table. 1183 N = size * 2 1184 guardPathNodeSlice(&con, N-1) 1185 conAddr = *(*unsafe.Pointer)(unsafe.Pointer(&con)) 1186 c = N 1187 } 1188 for i := 0; i < size; i++ { 1189 key, e := p.ReadString(false) 1190 if e != nil { 1191 return errNode(meta.ErrRead, "", e) 1192 } 1193 // fast path: use hash to store the key. 1194 if N != 0 { 1195 l = seekIntHash(conAddr, caching.StrHash(key), N) 1196 } 1197 v, err = self.handleChild(&con, &l, &c, p, recurse, opts, et) 1198 if err != nil { 1199 return err 1200 } 1201 v.Path = NewPathStrKey(key) 1202 } 1203 } else if kt.IsInt() { 1204 // fast path: use hash to store the key. 1205 if opts.StoreChildrenByHash && size > StoreChildrenByIntHashShreshold { 1206 // NOTE: we use original count*2 as the capacity of the hash table. 1207 N = size * 2 1208 guardPathNodeSlice(&con, N-1) 1209 conAddr = *(*unsafe.Pointer)(unsafe.Pointer(&con)) 1210 c = N 1211 } 1212 for i := 0; i < size; i++ { 1213 key, e := p.ReadInt(kt) 1214 if e != nil { 1215 return errNode(meta.ErrRead, "", e) 1216 } 1217 // fast path: use hash to store the key. 1218 if N != 0 { 1219 l = seekIntHash(conAddr, uint64(key), N) 1220 } 1221 v, err = self.handleChild(&con, &l, &c, p, recurse, opts, et) 1222 if err != nil { 1223 return err 1224 } 1225 v.Path = NewPathIntKey(key) 1226 } 1227 } else { 1228 for i := 0; i < size; i++ { 1229 ks := p.Read 1230 if e := p.Skip(kt, opts.UseNativeSkip); e != nil { 1231 return errNode(meta.ErrRead, "", e) 1232 } 1233 ke := p.Read 1234 v, err = self.handleChild(&con, &l, &c, p, recurse, opts, et) 1235 if err != nil { 1236 return err 1237 } 1238 v.Path = NewPathBinKey(p.Buf[ks:ke]) 1239 } 1240 } 1241 default: 1242 return errNode(meta.ErrUnsupportedType, "", nil) 1243 } 1244 1245 self.Next = con 1246 return nil 1247 }