github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/node.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 "bytes" 21 "fmt" 22 "sync" 23 "unsafe" 24 25 "github.com/cloudwego/dynamicgo/internal/rt" 26 "github.com/cloudwego/dynamicgo/meta" 27 "github.com/cloudwego/dynamicgo/thrift" 28 ) 29 30 var defaultOpts = &Options{} 31 32 // Node is a generic wrap of raw thrift data 33 type Node struct { 34 t thrift.Type 35 et thrift.Type 36 kt thrift.Type 37 v unsafe.Pointer 38 l int 39 } 40 41 // NewNodeBool create a new node with given type and data 42 // WARN: it WON'T check the correctness of the data 43 func NewNode(t thrift.Type, src []byte) Node { 44 ret := Node{ 45 t: t, 46 l: (len(src)), 47 v: rt.GetBytePtr(src), 48 } 49 if t == thrift.LIST || t == thrift.SET { 50 ret.et = *(*thrift.Type)(unsafe.Pointer(ret.v)) 51 } else if t == thrift.MAP { 52 ret.kt = *(*thrift.Type)(unsafe.Pointer(ret.v)) 53 ret.et = *(*thrift.Type)(rt.AddPtr(ret.v, uintptr(1))) 54 } 55 return ret 56 } 57 58 func (self Node) slice(s int, e int, t thrift.Type) Node { 59 ret := Node{ 60 t: t, 61 l: (e - s), 62 v: rt.AddPtr(self.v, uintptr(s)), 63 } 64 if t == thrift.LIST || t == thrift.SET { 65 ret.et = *(*thrift.Type)(unsafe.Pointer(ret.v)) 66 } else if t == thrift.MAP { 67 ret.kt = *(*thrift.Type)(unsafe.Pointer(ret.v)) 68 ret.et = *(*thrift.Type)(rt.AddPtr(ret.v, uintptr(1))) 69 } 70 return ret 71 } 72 73 func (self Node) offset() unsafe.Pointer { 74 return rt.AddPtr(self.v, uintptr(self.l)) 75 } 76 77 // NewNodeAny convert a go premitive type to Node. 78 // NOTICE: It only accepts LIMITED types. See `thrift.GoType2ThriftType()` for detailed conversion rules. 79 // 80 // opts provides options when making the node. 81 // Notice: only `Option.SliceAsSet` is effective now 82 func NewNodeAny(val interface{}, opts *Options) Node { 83 p := thrift.NewBinaryProtocol(make([]byte, 0, DefaultNodeBufferSize)) 84 if tt, err := p.WriteAny(val, opts.SliceAsSet); err != nil { 85 panic(err) 86 } else { 87 return NewNode(tt, p.Buf) 88 } 89 } 90 91 // NewNodeBool converts a bool value to a BOOL node 92 func NewNodeBool(val bool) Node { 93 buf := make([]byte, 1, 1) 94 thrift.BinaryEncoding{}.EncodeBool(buf, val) 95 return NewNode(thrift.BOOL, buf) 96 } 97 98 // NewNodeInt8 converts a byte value to a BYTE node 99 func NewNodeByte(val byte) Node { 100 buf := make([]byte, 1, 1) 101 thrift.BinaryEncoding{}.EncodeByte(buf, val) 102 return NewNode(thrift.BYTE, buf) 103 } 104 105 // NewNodeInt16 converts a int16 value to a I16 node 106 func NewNodeInt16(val int16) Node { 107 buf := make([]byte, 2, 2) 108 thrift.BinaryEncoding{}.EncodeInt16(buf, val) 109 return NewNode(thrift.I16, buf) 110 } 111 112 // NewNodeInt32 converts a int32 value to a I32 node 113 func NewNodeInt32(val int32) Node { 114 buf := make([]byte, 4, 4) 115 thrift.BinaryEncoding{}.EncodeInt32(buf, val) 116 return NewNode(thrift.I32, buf) 117 } 118 119 // NewNodeInt64 converts a int64 value to a I64 node 120 func NewNodeInt64(val int64) Node { 121 buf := make([]byte, 8, 8) 122 thrift.BinaryEncoding{}.EncodeInt64(buf, val) 123 return NewNode(thrift.I64, buf) 124 } 125 126 // NewNodeDouble converts a float64 value to a DOUBLE node 127 func NewNodeDouble(val float64) Node { 128 buf := make([]byte, 8, 8) 129 thrift.BinaryEncoding{}.EncodeDouble(buf, val) 130 return NewNode(thrift.DOUBLE, buf) 131 } 132 133 // NewNodeString converts a string value to a STRING node 134 func NewNodeString(val string) Node { 135 l := len(val) + 4 136 buf := make([]byte, l, l) 137 thrift.BinaryEncoding{}.EncodeString(buf, val) 138 return NewNode(thrift.STRING, buf) 139 } 140 141 // NewNodeBinary converts a []byte value to a STRING node 142 func NewNodeBinary(val []byte) Node { 143 l := len(val) + 4 144 buf := make([]byte, l, l) 145 thrift.BinaryEncoding{}.EncodeBinary(buf, val) 146 return NewNode(thrift.STRING, buf) 147 } 148 149 // NewNodeList creates a LIST node. 150 // The element thrift type depends on vals' concrete type, 151 // thus there must be at least one val. 152 // 153 // NOTICE: all recursive sub slice will be regard as LIST too 154 func NewNodeList(vals []interface{}) Node { 155 p := thrift.NewBinaryProtocol(make([]byte, 0, len(vals)*DefaultNodeBufferSize)) 156 if _, err := p.WriteAny(vals, false); err != nil { 157 panic(err) 158 } 159 return NewNode(thrift.LIST, p.Buf) 160 } 161 162 // NewNodeSet creates a SET node. 163 // The element thrift type depends on vals' concrete type, 164 // thus there must be at least one val. 165 // 166 // NOTICE: all recursive sub slice will be regard as SET too 167 func NewNodeSet(vals []interface{}) Node { 168 p := thrift.NewBinaryProtocol(make([]byte, 0, len(vals)*DefaultNodeBufferSize)) 169 if _, err := p.WriteAny(vals, true); err != nil { 170 panic(err) 171 } 172 return NewNode(thrift.SET, p.Buf) 173 } 174 175 // NewNodeMap creates a MAP node. 176 // The thrift type of key and element depends on kvs' concrete type, 177 // thus there must be at least one kv. 178 // 179 // opts provides options when making the node. 180 // Notice: only `Option.SliceAsSet` is effective now 181 func NewNodeMap(kvs map[interface{}]interface{}, opts *Options) Node { 182 p := thrift.NewBinaryProtocol(make([]byte, 0, len(kvs)*DefaultNodeBufferSize*2)) 183 if _, err := p.WriteAny(kvs, opts.SliceAsSet); err != nil { 184 panic(err) 185 } 186 return NewNode(thrift.MAP, p.Buf) 187 } 188 189 // NewNodeStruct creates a STRUCT node. 190 // The thrift type of element depends on vals' concrete type, 191 // thus there must be at least one field. 192 // 193 // opts provides options when making the node. 194 // Notice: only `Option.SliceAsSet` is effective now 195 func NewNodeStruct(fields map[thrift.FieldID]interface{}, opts *Options) Node { 196 p := thrift.NewBinaryProtocol(make([]byte, 0, len(fields)*DefaultNodeBufferSize)) 197 if _, err := p.WriteAny(fields, opts.SliceAsSet); err != nil { 198 panic(err) 199 } 200 return NewNode(thrift.STRUCT, p.Buf) 201 } 202 203 // NewTypedNode creates a new Node with the given typ, 204 // including element type (for LIST/SET/MAP) and key type (for MAP), 205 // and its children nodes. 206 // Its children PathNode sholud be according to typ: 207 // - STRUCT: PathTypeFieldId path and any-typed node 208 // - LIST/SET: PathTypeIndex path and et typed node 209 // - MAP: PathStrKey/PathIntKey/PathBinKey according to kt path and et typed node 210 // - scalar(STRING|I08|I16|I32|I64|BOOL|DOUBLE): the children is itself. 211 func NewTypedNode(typ thrift.Type, et thrift.Type, kt thrift.Type, children ...PathNode) (ret Node) { 212 if !typ.Valid() { 213 panic("invalid node type") 214 } 215 if len(children) == 0 { 216 // NOTICE: dummy node just for PathNode.Node to work 217 return newNode(typ, et, kt, nil) 218 } 219 220 switch typ { 221 case thrift.LIST, thrift.SET: 222 if !et.Valid() { 223 panic("invalid element type") 224 } 225 case thrift.MAP: 226 if !et.Valid() { 227 panic("invalid element type") 228 } 229 if !kt.Valid() { 230 panic("invalid key type") 231 } 232 case thrift.STRUCT: 233 break 234 default: 235 if len(children) != 1 { 236 panic("should only pass one children for scalar type!") 237 } 238 return newNode(typ, et, kt, children[0].Node.Raw()) 239 } 240 241 // for nested type, marshal the children to bytes 242 tmp := PathNode{ 243 Next: children, 244 } 245 tmp.Node.t = typ 246 tmp.Node.et = et 247 tmp.Node.kt = kt 248 bs, err := tmp.Marshal(defaultOpts) 249 if err != nil { 250 panic(err) 251 } 252 return newNode(typ, et, kt, bs) 253 } 254 255 func newNode(typ thrift.Type, et thrift.Type, kt thrift.Type, bs []byte) Node { 256 return Node{ 257 t: typ, 258 et: et, 259 kt: kt, 260 v: rt.GetBytePtr(bs), 261 l: len(bs), 262 } 263 } 264 265 // Fork forks the node to a new node, copy underlying data as well 266 func (self Node) Fork() Node { 267 ret := self 268 buf := make([]byte, self.l, self.l) 269 copy(buf, rt.BytesFrom(self.v, self.l, self.l)) 270 ret.v = rt.GetBytePtr(buf) 271 return ret 272 } 273 274 // Type returns the thrift type of the node 275 func (self Node) Type() thrift.Type { 276 return self.t 277 } 278 279 // ElemType returns the thrift type of a LIST/SET/MAP node's element 280 func (self Node) ElemType() thrift.Type { 281 return self.et 282 } 283 284 // KeyType returns the thrift type of a MAP node's key 285 func (self Node) KeyType() thrift.Type { 286 return self.kt 287 } 288 289 func searchFieldId(p *thrift.BinaryProtocol, id thrift.FieldID) (tt thrift.Type, start int, err error) { 290 // if _, err := p.ReadStructBegin(); err != nil { 291 // return 0, start, errNode(meta.ErrReadInput, "", err) 292 // } 293 for { 294 _, t, i, err := p.ReadFieldBegin() 295 if err != nil { 296 return 0, start, errNode(meta.ErrRead, "", err) 297 } 298 if t == thrift.STOP { 299 return thrift.STRUCT, start, errNotFound 300 } 301 if id == thrift.FieldID(i) { 302 start = p.Read 303 tt = t 304 break 305 } 306 if err := p.Skip(t, UseNativeSkipForGet); err != nil { 307 return 0, start, errNode(meta.ErrRead, "", err) 308 } 309 } 310 return 311 } 312 313 func searchIndex(p *thrift.BinaryProtocol, id int, isList bool) (tt thrift.Type, start int, err error) { 314 et, size, err := p.ReadListBegin() 315 if err != nil { 316 return 0, start, errNode(meta.ErrRead, "", err) 317 } 318 if id >= size { 319 if isList { 320 return thrift.LIST, p.Read, errNotFound 321 } else { 322 return thrift.SET, p.Read, errNotFound 323 } 324 } 325 326 //TODO: use direct index calculation for fixed-size list 327 for i := 0; i < id; i++ { 328 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 329 return 0, start, errNode(meta.ErrRead, "", err) 330 } 331 } 332 start = p.Read 333 tt = et 334 return 335 } 336 337 func searchStrKey(p *thrift.BinaryProtocol, id string) (tt thrift.Type, start int, err error) { 338 kt, et, size, err := p.ReadMapBegin() 339 if err != nil { 340 return 0, start, errNode(meta.ErrRead, "", err) 341 } 342 if kt != thrift.STRING { 343 return 0, start, errNode(meta.ErrDismatchType, "map key must be string type", nil) 344 } 345 start = p.Read 346 found := false 347 for i := 0; i < size; i++ { 348 key, err := p.ReadString(false) 349 if err != nil { 350 return 0, start, errNode(meta.ErrRead, "", err) 351 } 352 if key == id { 353 start = p.Read 354 tt = et 355 found = true 356 break 357 } 358 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 359 return 0, start, errNode(meta.ErrRead, "", err) 360 } 361 } 362 if !found { 363 return thrift.MAP, start, errNotFound 364 } 365 return 366 } 367 368 func searchBinKey(p *thrift.BinaryProtocol, id []byte) (tt thrift.Type, start int, err error) { 369 kt, et, size, err := p.ReadMapBegin() 370 if err != nil { 371 return 0, start, errNode(meta.ErrRead, "", err) 372 } 373 start = p.Read 374 found := false 375 for i := 0; i < size; i++ { 376 ks := p.Read 377 if err := p.Skip(kt, UseNativeSkipForGet); err != nil { 378 return 0, start, errNode(meta.ErrRead, "", err) 379 } 380 key := p.Buf[ks:p.Read] 381 if bytes.Equal(key, id) { 382 start = p.Read 383 tt = et 384 found = true 385 break 386 } 387 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 388 return 0, start, errNode(meta.ErrRead, "", err) 389 } 390 } 391 if !found { 392 return thrift.MAP, start, errNotFound 393 } 394 return 395 } 396 397 func searchIntKey(p *thrift.BinaryProtocol, id int) (tt thrift.Type, start int, err error) { 398 kt, et, size, err := p.ReadMapBegin() 399 if err != nil { 400 return 0, start, errNode(meta.ErrRead, "", err) 401 } 402 start = p.Read 403 found := false 404 if !kt.IsInt() { 405 return 0, start, errNode(meta.ErrDismatchType, fmt.Sprintf("map key type %s is not supported", kt), nil) 406 } 407 for i := 0; i < size; i++ { 408 key, err := p.ReadInt(kt) 409 if err != nil { 410 return 0, start, errNode(meta.ErrRead, "", err) 411 } 412 if key == id { 413 start = p.Read 414 tt = et 415 found = true 416 break 417 } 418 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 419 return 0, start, errNode(meta.ErrRead, "", err) 420 } 421 } 422 if !found { 423 return thrift.MAP, start, errNotFound 424 } 425 return 426 } 427 428 // GetByPath searches longitudinally and return a sub node at the given path from the node. 429 // 430 // The path is a list of PathFieldId, PathIndex, PathStrKey, PathBinKey, PathIntKey, 431 // Each path MUST be a valid path type for current layer (e.g. PathFieldId is only valid for STRUCT). 432 // Empty path will return the current node. 433 func (self Node) GetByPath(pathes ...Path) Node { 434 if self.Error() != "" { 435 return self 436 } 437 if len(pathes) == 0 { 438 return self 439 } 440 441 p := thrift.BinaryProtocol{ 442 Buf: self.raw(), 443 } 444 start := 0 445 tt := self.t 446 isList := self.t == thrift.LIST 447 var err error 448 449 for i, path := range pathes { 450 switch path.t { 451 case PathFieldId: 452 tt, start, err = searchFieldId(&p, path.id()) 453 isList = self.t == thrift.LIST 454 case PathFieldName: 455 return errNode(meta.ErrUnsupportedType, "", nil) 456 case PathIndex: 457 tt, start, err = searchIndex(&p, path.int(), isList) 458 case PathStrKey: 459 tt, start, err = searchStrKey(&p, path.str()) 460 case PathIntKey: 461 tt, start, err = searchIntKey(&p, path.int()) 462 case PathBinKey: 463 tt, start, err = searchBinKey(&p, path.bin()) 464 default: 465 return errNode(meta.ErrUnsupportedType, fmt.Sprintf("invalid %dth path: %#v", i, p), nil) 466 } 467 if err != nil { 468 // the last one not foud, return start pointer for inserting on `SetByPath()` here 469 if i == len(pathes)-1 && err == errNotFound { 470 return errNotFoundLast(unsafe.Pointer(uintptr(self.v)+uintptr(start)), tt) 471 } 472 en := err.(Node) 473 return errNode(en.ErrCode().Behavior(), "", err) 474 } 475 } 476 477 if err := p.Skip(tt, UseNativeSkipForGet); err != nil { 478 return errNode(meta.ErrRead, "", err) 479 } 480 return self.slice(start, p.Read, tt) 481 } 482 483 // Field returns a sub node at the given field id from a STRUCT node. 484 func (self Node) Field(id thrift.FieldID) (v Node) { 485 if err := self.should("Field", thrift.STRUCT); err != "" { 486 return errNode(meta.ErrUnsupportedType, err, nil) 487 } 488 it := self.iterFields() 489 if it.Err != nil { 490 return errNode(meta.ErrRead, "", it.Err) 491 } 492 for it.HasNext() { 493 i, t, s, e := it.Next(UseNativeSkipForGet) 494 if i == id { 495 v = self.slice(s, e, t) 496 goto ret 497 } else if it.Err != nil { 498 v = errNode(meta.ErrRead, "", it.Err) 499 goto ret 500 } 501 } 502 v = errNode(meta.ErrNotFound, fmt.Sprintf("field %d is not found in this value", id), errNotFound) 503 ret: 504 // it.Recycle() 505 return 506 } 507 508 // Index returns a sub node at the given index from a LIST/SET node. 509 func (self Node) Index(i int) (v Node) { 510 if err := self.should2("Index", thrift.LIST, thrift.SET); err != "" { 511 return errNode(meta.ErrUnsupportedType, err, nil) 512 } 513 514 // et := self.d.Elem() 515 var s, e int 516 it := self.iterElems() 517 if it.Err != nil { 518 return errNode(meta.ErrRead, "", it.Err) 519 } 520 if i >= it.size { 521 v = errNode(meta.ErrInvalidParam, fmt.Sprintf("index %d exceeds list/set bound", i), nil) 522 goto ret 523 } 524 for j := 0; it.HasNext() && j < i; j++ { 525 it.Next(UseNativeSkipForGet) 526 } 527 if it.Err != nil { 528 return errNode(meta.ErrRead, "", it.Err) 529 } 530 531 s, e = it.Next(UseNativeSkipForGet) 532 v = self.slice(s, e, self.et) 533 ret: 534 // it.Recycle() 535 return 536 } 537 538 // GetByInt returns a sub node at the given int key from a MAP<STRING,xx> node. 539 func (self Node) GetByStr(key string) (v Node) { 540 if err := self.should("Get", thrift.MAP); err != "" { 541 return errNode(meta.ErrUnsupportedType, err, nil) 542 } 543 544 // et := self.d.Elem() 545 // kt := self.d.Key() 546 if self.kt != thrift.STRING { 547 return errNode(meta.ErrUnsupportedType, "Get() only supports STRING key type", nil) 548 } 549 550 it := self.iterPairs() 551 if it.Err != nil { 552 return errNode(meta.ErrRead, "", it.Err) 553 } 554 for it.HasNext() { 555 _, s, ss, e := it.NextStr(UseNativeSkipForGet) 556 if it.Err != nil { 557 v = errNode(meta.ErrRead, "", it.Err) 558 goto ret 559 } 560 if s == key { 561 v = self.slice(ss, e, self.et) 562 goto ret 563 } 564 } 565 v = errNode(meta.ErrNotFound, fmt.Sprintf("key '%s' is not found in this value", key), errNotFound) 566 ret: 567 return 568 } 569 570 // GetByInt returns a sub node at the given int key from a MAP<INT,xx> node. 571 func (self Node) GetByInt(key int) (v Node) { 572 if err := self.should("Get", thrift.MAP); err != "" { 573 return errNode(meta.ErrUnsupportedType, err, nil) 574 } 575 576 // et := self.d.Elem() 577 // kt := self.d.Key() 578 if !self.kt.IsInt() { 579 return errNode(meta.ErrUnsupportedType, "Get() only supports integer key type", nil) 580 } 581 582 it := self.iterPairs() 583 if it.Err != nil { 584 return errNode(meta.ErrRead, "", it.Err) 585 } 586 for it.HasNext() { 587 _, s, ss, e := it.NextInt(UseNativeSkipForGet) 588 if it.Err != nil { 589 v = errNode(meta.ErrRead, "", it.Err) 590 goto ret 591 } 592 if s == key { 593 v = self.slice(ss, e, self.et) 594 goto ret 595 } 596 } 597 v = errNode(meta.ErrNotFound, fmt.Sprintf("key '%d' is not found in this value", key), nil) 598 ret: 599 return 600 } 601 602 // GetByInt returns a sub node at the given bytes key from a MAP node. 603 // The key must be deep equal (bytes.Equal) to the key in the map. 604 func (self Node) GetByRaw(key []byte) (v Node) { 605 if err := self.should("Get", thrift.MAP); err != "" { 606 return errNode(meta.ErrUnsupportedType, err, nil) 607 } 608 609 it := self.iterPairs() 610 if it.Err != nil { 611 return errNode(meta.ErrRead, "", it.Err) 612 } 613 for it.HasNext() { 614 _, s, ss, e := it.NextBin(UseNativeSkipForGet) 615 if it.Err != nil { 616 v = errNode(meta.ErrRead, "", it.Err) 617 goto ret 618 } 619 if bytes.Equal(s, key) { 620 v = self.slice(ss, e, self.et) 621 goto ret 622 } 623 } 624 v = errNode(meta.ErrNotFound, fmt.Sprintf("key '%v' is not found in this value", key), errNotFound) 625 ret: 626 return 627 } 628 629 // Fields returns all sub nodes ids along with the given int path from a STRUCT node. 630 func (self Node) Fields(ids []PathNode, opts *Options) (err error) { 631 if err := self.should("Fields", thrift.STRUCT); err != "" { 632 return errValue(meta.ErrUnsupportedType, err, nil) 633 } 634 if len(ids) == 0 { 635 return nil 636 } 637 638 if opts.ClearDirtyValues { 639 for i := range ids { 640 ids[i].Node = Node{} 641 } 642 } 643 644 it := self.iterFields() 645 if it.Err != nil { 646 return errValue(meta.ErrRead, "", it.Err) 647 } 648 649 need := len(ids) 650 for count := 0; it.HasNext() && count < need; { 651 var p *PathNode 652 i, t, s, e := it.Next(opts.UseNativeSkip) 653 if it.Err != nil { 654 return errValue(meta.ErrRead, "", it.Err) 655 } 656 //TODO: use bitmap to avoid repeatedly scan 657 for j, id := range ids { 658 if id.Path.t == PathFieldId && id.Path.id() == i { 659 p = &ids[j] 660 count += 1 661 break 662 } 663 } 664 if p != nil { 665 p.Node = self.slice(s, e, t) 666 } 667 } 668 // it.Recycle() 669 return 670 } 671 672 // Indexes returns all sub nodes along with the given int path from a LIST/SET node. 673 func (self Node) Indexes(ins []PathNode, opts *Options) (err error) { 674 if err := self.should2("Indexes", thrift.LIST, thrift.SET); err != "" { 675 return errValue(meta.ErrUnsupportedType, err, nil) 676 } 677 if len(ins) == 0 { 678 return nil 679 } 680 681 if opts.ClearDirtyValues { 682 for i := range ins { 683 ins[i].Node = Node{} 684 } 685 } 686 687 et := self.et 688 it := self.iterElems() 689 if it.Err != nil { 690 return errValue(meta.ErrRead, "", it.Err) 691 } 692 693 need := len(ins) 694 for count, i := 0, 0; it.HasNext() && count < need; i++ { 695 s, e := it.Next(opts.UseNativeSkip) 696 if it.Err != nil { 697 return errValue(meta.ErrRead, "", it.Err) 698 } 699 var p *PathNode 700 for j, id := range ins { 701 if id.Path.t != PathIndex { 702 continue 703 } 704 k := id.Path.int() 705 if k >= it.size { 706 continue 707 } 708 if k == i { 709 p = &ins[j] 710 count += 1 711 break 712 } 713 } 714 if p != nil { 715 p.Node = self.slice(s, e, et) 716 } 717 } 718 // it.Recycle() 719 return 720 } 721 722 // Gets returns all sub nodes along with the given key (PathStrKey|PathIntKey|PathBinKey) path from a MAP node. 723 func (self Node) Gets(keys []PathNode, opts *Options) (err error) { 724 if err := self.should("Get", thrift.MAP); err != "" { 725 return errValue(meta.ErrUnsupportedType, err, nil) 726 } 727 if len(keys) == 0 { 728 return nil 729 } 730 731 if opts.ClearDirtyValues { 732 for i := range keys { 733 keys[i].Node = Node{} 734 } 735 } 736 737 et := self.et 738 it := self.iterPairs() 739 if it.Err != nil { 740 return errValue(meta.ErrRead, "", it.Err) 741 } 742 need := len(keys) 743 for count := 0; it.HasNext() && count < need; { 744 for j, id := range keys { 745 if id.Path.Type() == PathStrKey { 746 exp := id.Path.str() 747 _, s, v, e := it.NextStr(opts.UseNativeSkip) 748 if it.Err != nil { 749 return errValue(meta.ErrRead, "", it.Err) 750 } 751 if exp == s { 752 p := &keys[j] 753 count += 1 754 p.Node = self.slice(v, e, et) 755 } 756 } else if id.Path.Type() == PathIntKey { 757 exp := id.Path.int() 758 _, s, v, e := it.NextInt(opts.UseNativeSkip) 759 if it.Err != nil { 760 return errValue(meta.ErrRead, "", it.Err) 761 } 762 if exp == s { 763 p := &keys[j] 764 count += 1 765 p.Node = self.slice(v, e, et) 766 } 767 } else { 768 exp := id.Path.bin() 769 _, s, v, e := it.NextBin(opts.UseNativeSkip) 770 if it.Err != nil { 771 return errValue(meta.ErrRead, "", it.Err) 772 } 773 if bytes.Equal(exp, s) { 774 p := &keys[j] 775 count += 1 776 p.Node = self.slice(v, e, et) 777 } 778 } 779 } 780 } 781 // it.Recycle() 782 return 783 } 784 785 // GetMany searches transversely and returns all the sub nodes along with the given pathes. 786 func (self Node) GetMany(pathes []PathNode, opts *Options) error { 787 if len(pathes) == 0 { 788 return nil 789 } 790 return self.getMany(pathes, opts.ClearDirtyValues, opts) 791 } 792 793 func (self Node) getMany(pathes []PathNode, clearDirty bool, opts *Options) error { 794 if clearDirty { 795 for i := range pathes { 796 pathes[i].Node = Node{} 797 } 798 } 799 p := pathes[0] 800 switch p.Path.t { 801 case PathFieldId: 802 return self.Fields(pathes, opts) 803 case PathIndex: 804 return self.Indexes(pathes, opts) 805 case PathStrKey, PathIntKey, PathBinKey: 806 return self.Gets(pathes, opts) 807 default: 808 return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid path: %#v", p), nil) 809 } 810 } 811 812 // GetTree returns a tree of all sub nodes along with the given path on the tree. 813 // It supports longitudinally search (like GetByPath) and transversely search (like GetMany) both. 814 func (self Node) GetTree(tree *PathNode, opts *Options) error { 815 if tree == nil { 816 panic("nil PathNode tree") 817 } 818 tree.Node = self 819 return tree.Assgin(true, opts) 820 } 821 822 func (self *Node) replace(o Node, n Node) error { 823 // mush ensure target value is same type as source value 824 if o.t != n.t { 825 return meta.NewError(meta.ErrDismatchType, fmt.Sprintf("type mismatch: %s != %s", o.t, n.t), nil) 826 } 827 // export target node to bytes 828 pat := n.raw() 829 830 // divide self's buffer into three slices: 831 // 1. self's slice before the target node 832 // 2. target node's slice 833 // 3. self's slice after the target node 834 s1 := rt.AddPtr(o.v, uintptr(o.l)) 835 l0 := int(uintptr(o.v) - uintptr(self.v)) 836 l1 := len(pat) 837 l2 := int(uintptr(self.v) + uintptr(self.l) - uintptr(s1)) 838 839 // copy three slices into new buffer 840 buf := make([]byte, l0+l1+l2) 841 copy(buf[:l0], rt.BytesFrom(self.v, l0, l0)) 842 copy(buf[l0:l0+l1], pat) 843 copy(buf[l0+l1:l0+l1+l2], rt.BytesFrom(s1, l2, l2)) 844 845 // replace self's entire buffer 846 self.v = rt.GetBytePtr(buf) 847 self.l = int(len(buf)) 848 return nil 849 } 850 851 func (o *Node) setNotFound(path Path, n *Node) error { 852 switch o.kt { 853 case thrift.STRUCT: 854 // add field bytes 855 key := path.ToRaw(n.t) 856 src := n.raw() 857 buf := make([]byte, 0, len(key)+len(src)) 858 buf = append(buf, key...) 859 buf = append(buf, src...) 860 n.l = len(buf) 861 n.v = rt.GetBytePtr(buf) 862 case thrift.LIST, thrift.SET: 863 // modify the original size 864 buf := rt.BytesFrom(rt.SubPtr(o.v, uintptr(4)), 4, 4) 865 size := int(thrift.BinaryEncoding{}.DecodeInt32(buf)) 866 thrift.BinaryEncoding{}.EncodeInt32(buf, int32(size+1)) 867 case thrift.MAP: 868 // modify the original size 869 buf := rt.BytesFrom(rt.SubPtr(o.v, uintptr(4)), 4, 4) 870 size := int(thrift.BinaryEncoding{}.DecodeInt32(buf)) 871 thrift.BinaryEncoding{}.EncodeInt32(buf, int32(size+1)) 872 // add key bytes 873 key := path.ToRaw(n.t) 874 src := n.raw() 875 buf = make([]byte, 0, len(key)+len(src)) 876 buf = append(buf, key...) 877 buf = append(buf, src...) 878 n.l = len(buf) 879 n.v = rt.GetBytePtr(buf) 880 default: 881 return errNode(meta.ErrDismatchType, "simple type node shouldn't have child", nil) 882 } 883 o.t = n.t 884 o.l = 0 885 return nil 886 } 887 888 // SetByPath sets the sub node at the given path. 889 func (self *Node) SetByPath(sub Node, path ...Path) (exist bool, err error) { 890 if len(path) == 0 { 891 *self = sub 892 return true, nil 893 } 894 if sub.IsError() { 895 return false, sub 896 } 897 if err := self.Check(); err != nil { 898 return false, err 899 } 900 // search source node by path 901 var v = self.GetByPath(path...) 902 if v.IsError() { 903 if !v.isErrNotFoundLast() { 904 return false, v 905 } 906 if err := v.setNotFound(path[len(path)-1], &sub); err != nil { 907 return false, err 908 } 909 } else { 910 exist = true 911 } 912 err = self.replace(v, sub) 913 return 914 } 915 916 var pnsPool = sync.Pool{ 917 New: func() interface{} { 918 return &pnSlice{ 919 a: make([]PathNode, 0, DefaultNodeSliceCap), 920 } 921 }, 922 } 923 924 func (self *Node) replaceMany(ps *pnSlice) error { 925 var buf []byte 926 // Sort pathes by original value address 927 ps.Sort() 928 929 // sequentially set new values into buffer according to sorted pathes 930 buf = make([]byte, 0, self.l) 931 last := self.v 932 for i := 0; i < len(ps.a); i++ { 933 lastLen := rt.PtrOffset(ps.a[i].Node.v, last) 934 // copy last slice from original buffer 935 buf = append(buf, rt.BytesFrom(last, lastLen, lastLen)...) 936 // copy new value's buffer into buffer 937 buf = append(buf, ps.b[i].Node.raw()...) 938 // update last index 939 last = ps.a[i].offset() 940 } 941 if tail := self.offset(); uintptr(last) < uintptr(tail) { 942 // copy last slice from original buffer 943 buf = append(buf, rt.BytesFrom(last, rt.PtrOffset(tail, last), rt.PtrOffset(tail, last))...) 944 } 945 946 self.v = rt.GetBytePtr(buf) 947 self.l = int(len(buf)) 948 return nil 949 } 950 951 // SetMany searches longitudinally and sets the sub nodes at the given pathes. 952 func (self *Node) SetMany(pathes []PathNode, opts *Options) (err error) { 953 if len(pathes) == 0 { 954 return nil 955 } 956 if err := self.Check(); err != nil { 957 return err 958 } 959 960 // copy original pathes 961 ps := pnsPool.Get().(*pnSlice) 962 if cap(ps.a) < len(pathes) { 963 ps.a = make([]PathNode, len(pathes)) 964 } else { 965 ps.a = ps.a[:len(pathes)] 966 } 967 copy(ps.a, pathes) 968 ps.b = pathes 969 970 // get original values 971 if err = self.getMany(ps.a, true, opts); err != nil { 972 goto ret 973 } 974 // handle not found values 975 for i, a := range ps.a { 976 if a.IsEmpty() { 977 var sp unsafe.Pointer 978 switch self.t { 979 case thrift.STRUCT: 980 sp = self.v 981 case thrift.LIST, thrift.SET: 982 // element type (1 B) + size (4B) 983 sp = rt.AddPtr(self.v, 5) 984 case thrift.MAP: 985 // element type (1 B) + size (4B) 986 sp = rt.AddPtr(self.v, 6) 987 } 988 ps.a[i].Node = errNotFoundLast(sp, self.t) 989 ps.a[i].Node.setNotFound(a.Path, &ps.b[i].Node) 990 } 991 } 992 993 err = self.replaceMany(ps) 994 ret: 995 ps.b = nil 996 pnsPool.Put(ps) 997 return 998 } 999 1000 func (self *Node) deleteChild(path Path) Node { 1001 p := thrift.BinaryProtocol{} 1002 p.Buf = self.raw() 1003 var s, e int 1004 var tt thrift.Type 1005 switch self.t { 1006 case thrift.STRUCT: 1007 if path.Type() != PathFieldId { 1008 return errNode(meta.ErrDismatchType, "", nil) 1009 } 1010 id := path.id() 1011 for { 1012 s = p.Read 1013 _, t, i, err := p.ReadFieldBegin() 1014 if err != nil { 1015 return errNode(meta.ErrRead, "", err) 1016 } 1017 if t == thrift.STOP { 1018 return errNotFound 1019 } 1020 if err := p.Skip(t, UseNativeSkipForGet); err != nil { 1021 return errNode(meta.ErrRead, "", err) 1022 } 1023 e = p.Read 1024 if id == i { 1025 tt = t 1026 break 1027 } 1028 } 1029 case thrift.LIST, thrift.SET: 1030 if path.Type() != PathIndex { 1031 return errNode(meta.ErrDismatchType, "", nil) 1032 } 1033 id := path.int() 1034 et, size, err := p.ReadListBegin() 1035 if err != nil { 1036 return errNode(meta.ErrRead, "", err) 1037 } 1038 if id >= size { 1039 return errNotFound 1040 } 1041 tt = et 1042 if err := p.ModifyI32(p.Read-4, int32(size-1)); err != nil { 1043 return errNode(meta.ErrWrite, "", err) 1044 } 1045 if d := thrift.TypeSize(et); d > 0 { 1046 s = p.Read + d*id 1047 e = s + d 1048 } else { 1049 for i := 0; i < id; i++ { 1050 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 1051 return errNode(meta.ErrRead, "", err) 1052 } 1053 } 1054 s = p.Read 1055 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 1056 return errNode(meta.ErrRead, "", err) 1057 } 1058 e = p.Read 1059 } 1060 case thrift.MAP: 1061 kt, et, size, err := p.ReadMapBegin() 1062 if err != nil { 1063 return errNode(meta.ErrRead, "", err) 1064 } 1065 id := path.ToRaw(kt) 1066 if id == nil { 1067 return errNode(meta.ErrInvalidParam, "", nil) 1068 } 1069 if err := p.ModifyI32(p.Read-4, int32(size-1)); err != nil { 1070 return errNode(meta.ErrWrite, "", err) 1071 } 1072 tt = et 1073 for i := 0; i < size; i++ { 1074 s = p.Read 1075 if err := p.Skip(kt, UseNativeSkipForGet); err != nil { 1076 return errNode(meta.ErrRead, "", err) 1077 } 1078 key := p.Buf[s:p.Read] 1079 if err := p.Skip(et, UseNativeSkipForGet); err != nil { 1080 return errNode(meta.ErrRead, "", err) 1081 } 1082 e = p.Read 1083 if bytes.Equal(key, id) { 1084 break 1085 } 1086 } 1087 } 1088 1089 return Node{ 1090 t: tt, 1091 v: rt.AddPtr(self.v, uintptr(s)), 1092 l: e - s, 1093 } 1094 } 1095 1096 func (self *Node) UnsetByPath(path ...Path) error { 1097 l := len(path) 1098 if l == 0 { 1099 *self = Node{} 1100 return nil 1101 } 1102 if err := self.Check(); err != nil { 1103 return err 1104 } 1105 // search parent node by path 1106 var v = self.GetByPath(path[:l-1]...) 1107 if v.IsError() { 1108 if v.IsErrNotFound() { 1109 return nil 1110 } 1111 return v 1112 } 1113 ret := v.deleteChild(path[l-1]) 1114 if ret.IsError() { 1115 return ret 1116 } 1117 return self.replace(ret, Node{t: ret.t}) 1118 } 1119 1120 // Children loads all its children and children's children recursively (if recurse is true). 1121 // out is used for store children, and it is always reset to zero length before use. 1122 // 1123 // NOTICE: if opts.NotScanParentNode is true, the parent nodes (PathNode.Node) of complex (LIST/SET/MAP/STRUCT) type won't be assgined data 1124 func (self Node) Children(out *[]PathNode, recurse bool, opts *Options) (err error) { 1125 if self.Error() != "" { 1126 return self 1127 } 1128 if out == nil { 1129 panic("out is nil") 1130 } 1131 // NOTICE: since we only use out for memory reuse, we always reset it to zero. 1132 var p = thrift.BinaryProtocol{ 1133 Buf: self.raw(), 1134 } 1135 var tree = PathNode{ 1136 Node: self, 1137 Next: (*out)[:0], // NOTICE: we reset it to zero. 1138 } 1139 1140 err = tree.scanChildren(&p, recurse, opts) 1141 if err == nil { 1142 *out = tree.Next 1143 } 1144 return err 1145 }