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  }