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  }