github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/proto/generic/path.go (about)

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