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

     1  package generic
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"unsafe"
     7  
     8  	"github.com/cloudwego/dynamicgo/internal/rt"
     9  	"github.com/cloudwego/dynamicgo/meta"
    10  	"github.com/cloudwego/dynamicgo/proto"
    11  	"github.com/cloudwego/dynamicgo/proto/binary"
    12  	"github.com/cloudwego/dynamicgo/proto/protowire"
    13  )
    14  
    15  const defaultBytesSize = 64
    16  
    17  type Value struct {
    18  	Node
    19  	Desc *proto.TypeDescriptor
    20  	IsRoot  bool
    21  }
    22  
    23  var (
    24  	pnsPool = sync.Pool{
    25  		New: func() interface{} {
    26  			return &pnSlice{
    27  				a: make([]PathNode, 0, DefaultNodeSliceCap),
    28  			}
    29  		},
    30  	}
    31  	bytesPool = sync.Pool{
    32  		New: func() interface{} {
    33  			return make([]byte, 0, defaultBytesSize)
    34  		},
    35  	}
    36  )
    37  
    38  func NewBytesFromPool() []byte {
    39  	return bytesPool.Get().([]byte)
    40  }
    41  
    42  func FreeBytesToPool(b []byte) {
    43  	b = b[:0]
    44  	bytesPool.Put(b)
    45  }
    46  
    47  func NewRootValue(desc *proto.TypeDescriptor, src []byte) Value {
    48  	return Value{
    49  		Node: NewNode(proto.MESSAGE, src),
    50  		Desc: desc,
    51  		IsRoot: true,
    52  	}
    53  }
    54  
    55  // only for basic Node
    56  func NewValue(desc *proto.TypeDescriptor, src []byte) Value {
    57  	return Value{
    58  		Node: NewNode(desc.Type(), src),
    59  		Desc: desc,
    60  	}
    61  }
    62  
    63  // only for LIST/MAP parent Node
    64  func NewComplexValue(desc *proto.TypeDescriptor, src []byte) Value {
    65  	t := desc.Type()
    66  	et := proto.UNKNOWN
    67  	kt := proto.UNKNOWN
    68  	if t == proto.LIST {
    69  		et = desc.Elem().Type()
    70  	} else if t == proto.MAP {
    71  		t = proto.MAP
    72  		et = desc.Elem().Type()
    73  		kt = desc.Key().Type()
    74  	} else {
    75  		panic("only used for list/map node")
    76  	}
    77  
    78  	return Value{
    79  		Node: NewComplexNode(t, et, kt, src),
    80  		Desc: desc,
    81  	}
    82  }
    83  
    84  
    85  // NewValueFromNode copy both Node and TypeDescriptor from another Value.
    86  func (self Value) Fork() Value {
    87  	ret := self
    88  	ret.Node = self.Node.Fork()
    89  	return ret
    90  }
    91  
    92  
    93  func (self Value) sliceWithDesc(s int, e int, desc *proto.TypeDescriptor) Value {
    94  	node := self.sliceNodeWithDesc(s, e, desc)
    95  	return Value{Node: node, Desc: desc}
    96  }
    97  
    98  // searchFieldId in MESSAGE Node
    99  // if id is found, return the field tag position, otherwise return the end of p.Buf
   100  func searchFieldId(p *binary.BinaryProtocol, id proto.FieldNumber, messageLen int) (int, error) {
   101  	start := p.Read
   102  	for p.Read < start+messageLen {
   103  		fieldNumber, wireType, tagLen, err := p.ConsumeTagWithoutMove()
   104  		if err != nil {
   105  			return 0, err
   106  		}
   107  
   108  		if fieldNumber == id {
   109  			return p.Read, nil
   110  		}
   111  		p.Read += tagLen
   112  
   113  		if err := p.Skip(wireType, false); err != nil {
   114  			return 0, errNode(meta.ErrRead, "searchFieldId: skip field error.", err)
   115  		}
   116  	}
   117  	return p.Read, errNotFound
   118  }
   119  
   120  // searchIndex in LIST Node
   121  // packed: if idx is found, return the element[V] value start position, otherwise return the end of p.Buf
   122  // unpacked: if idx is found, return the element[TLV] tag position, otherwise return the end of p.Buf
   123  func searchIndex(p *binary.BinaryProtocol, idx int, elementWireType proto.WireType, isPacked bool, fieldNumber proto.FieldNumber) (int, error) {
   124  	// packed list
   125  	cnt := 0
   126  	result := p.Read
   127  	if isPacked {
   128  		// read length
   129  		length, err := p.ReadLength()
   130  		if err != nil {
   131  			return 0, err
   132  		}
   133  		// read list
   134  		start := p.Read
   135  		for p.Read < start+length && cnt < idx {
   136  			if err := p.Skip(elementWireType, false); err != nil {
   137  				return 0, errNode(meta.ErrRead, "searchIndex: skip packed list element error.", err)
   138  			}
   139  			cnt++
   140  		}
   141  		result = p.Read
   142  	} else {
   143  		// normal Type : [tag][(length)][value][tag][(length)][value][tag][(length)][value]....
   144  		for p.Read < len(p.Buf) && cnt < idx {
   145  			// don't move p.Read and judge whether readList completely
   146  			if err := p.Skip(elementWireType, false); err != nil {
   147  				return 0, errNode(meta.ErrRead, "searchIndex: skip unpacked list element error.", err)
   148  			}
   149  			cnt++
   150  			if p.Read < len(p.Buf) {
   151  				// don't move p.Read and judge whether readList completely
   152  				elementFieldNumber, _, n, err := p.ConsumeTagWithoutMove()
   153  				if err != nil {
   154  					return 0, err
   155  				}
   156  				if elementFieldNumber != fieldNumber {
   157  					break
   158  				}
   159  				if cnt < idx {
   160  					p.Read += n
   161  				}
   162  				result = p.Read + n
   163  			}
   164  		}
   165  
   166  	}
   167  
   168  	if cnt < idx {
   169  		return p.Read, errNotFound
   170  	}
   171  
   172  	return result, nil
   173  }
   174  
   175  // searchIntKey in MAP Node
   176  // if key is found, return the value tag position, otherwise return the end of p.Buf
   177  func searchIntKey(p *binary.BinaryProtocol, key int, keyType proto.Type, mapFieldNumber proto.FieldNumber) (int, error) {
   178  	exist := false
   179  	start := p.Read
   180  	for p.Read < len(p.Buf) {
   181  		if _, err := p.ReadLength(); err != nil {
   182  			return 0, wrapError(meta.ErrRead, "searchIntKey: read pair length failed", nil)
   183  		}
   184  
   185  		if _, _, _, keyTagErr := p.ConsumeTag(); keyTagErr != nil {
   186  			return 0, wrapError(meta.ErrRead, "searchIntKey: read key tag failed", nil)
   187  		}
   188  
   189  		k, err := p.ReadInt(keyType)
   190  		if err != nil {
   191  			return 0, wrapError(meta.ErrRead, "searchIntKey: can not read map key", nil)
   192  		}
   193  
   194  		if k == key {
   195  			exist = true
   196  			start = p.Read // p.Read will point to value tag
   197  			break
   198  		}
   199  
   200  		_, valueWireType, _, valueTagErr := p.ConsumeTag()
   201  		if valueTagErr != nil {
   202  			return 0, wrapError(meta.ErrRead, "searchIntKey: read value tag failed", nil)
   203  		}
   204  
   205  		// if key not match, skip value
   206  		if err := p.Skip(valueWireType, false); err != nil {
   207  			return 0, errNode(meta.ErrRead, "searchIntKey: searchIntKey: can not read value.", err)
   208  		}
   209  
   210  		if p.Read >= len(p.Buf) {
   211  			break
   212  		}
   213  
   214  		// don't move p.Read and judge whether readList completely
   215  		elementFieldNumber, _, n, err := p.ConsumeTagWithoutMove()
   216  		if err != nil {
   217  			return 0, err
   218  		}
   219  		if elementFieldNumber != mapFieldNumber {
   220  			break
   221  		}
   222  		p.Read += n
   223  	}
   224  	if !exist {
   225  		return p.Read, errNotFound
   226  	}
   227  	return start, nil
   228  }
   229  
   230  // searchStrKey in MAP Node
   231  // if key is found, return the value tag position, otherwise return the end of p.Buf
   232  func searchStrKey(p *binary.BinaryProtocol, key string, keyType proto.Type, mapFieldNumber proto.FieldNumber) (int, error) {
   233  	exist := false
   234  	start := p.Read
   235  
   236  	for p.Read < len(p.Buf) {
   237  		if _, err := p.ReadLength(); err != nil {
   238  			return 0, wrapError(meta.ErrRead, "searchStrKey: read pair length failed", nil)
   239  		}
   240  
   241  		if _, _, _, keyTagErr := p.ConsumeTag(); keyTagErr != nil {
   242  			return 0, wrapError(meta.ErrRead, "searchStrKey: read key tag failed", nil)
   243  		}
   244  
   245  		k, err := p.ReadString(false)
   246  		if err != nil {
   247  			return 0, wrapError(meta.ErrRead, "searchStrKey: can not read map key", nil)
   248  		}
   249  
   250  		if k == key {
   251  			exist = true
   252  			start = p.Read // p.Read will point to value tag
   253  			break
   254  		}
   255  
   256  		_, valueWireType, _, valueTagErr := p.ConsumeTag()
   257  		if valueTagErr != nil {
   258  			return 0, wrapError(meta.ErrRead, "searchStrKey: read value tag failed", nil)
   259  		}
   260  
   261  		// if key not match, skip value
   262  		if err := p.Skip(valueWireType, false); err != nil {
   263  			return 0, errNode(meta.ErrRead, "searchStrKey: searchStrKey: can not read value.", err)
   264  		}
   265  
   266  		if p.Read >= len(p.Buf) {
   267  			break
   268  		}
   269  
   270  		// don't move p.Read and judge whether readList completely
   271  		elementFieldNumber, _, n, err := p.ConsumeTagWithoutMove()
   272  		if err != nil {
   273  			return 0, err
   274  		}
   275  		if elementFieldNumber != mapFieldNumber {
   276  			break
   277  		}
   278  		p.Read += n
   279  	}
   280  	if !exist {
   281  		return p.Read, errNotFound
   282  	}
   283  	return start, nil
   284  }
   285  
   286  func (self Value) GetByPath(pathes ...Path) Value {
   287  	value, _ := self.getByPath(pathes...)
   288  	return value
   289  }
   290  
   291  func (self Value) GetByPathWithAddress(pathes ...Path) (Value, []int) {
   292  	return self.getByPath(pathes...)
   293  }
   294  
   295  // inner use
   296  func (self Value) getByPath(pathes ...Path) (Value, []int) {
   297  	address := make([]int, len(pathes))
   298  	start := 0
   299  	var err error
   300  	tt := self.t
   301  	kt := self.kt
   302  	et := self.et
   303  	size := 0
   304  	desc := self.Desc
   305  	isRoot := self.IsRoot
   306  	if len(pathes) == 0 {
   307  		return self, address
   308  	}
   309  
   310  	if self.Error() != "" {
   311  		return self, address
   312  	}
   313  
   314  	p := binary.BinaryProtocol{
   315  		Buf: self.raw(),
   316  	}
   317  
   318  	if !isRoot {
   319  		if self.t == proto.LIST || self.t == proto.MAP {
   320  			p.ConsumeTag()
   321  		}
   322  	}
   323  
   324  	for i, path := range pathes {
   325  		switch path.t {
   326  		case PathFieldId:
   327  			id := path.id()
   328  			messageLen := 0
   329  			if isRoot {
   330  				messageLen = len(p.Buf)
   331  				isRoot = false
   332  			} else {
   333  				Len, err := p.ReadLength()
   334  				if err != nil {
   335  					return errValue(meta.ErrRead, "GetByPath: read field length failed.", err), address
   336  				}
   337  				messageLen += Len
   338  			}
   339  
   340  			fd := desc.Message().ByNumber(id)
   341  			if fd != nil {
   342  				desc = fd.Type()
   343  				tt = desc.Type()
   344  			}
   345  
   346  			start, err = searchFieldId(&p, id, messageLen)
   347  			if err == errNotFound {
   348  				tt = proto.MESSAGE
   349  			}
   350  		case PathFieldName:
   351  			name := path.str()
   352  			messageLen := 0
   353  			if isRoot {
   354  				messageLen = len(p.Buf)
   355  				isRoot = false
   356  			} else {
   357  				Len, err := p.ReadLength()
   358  				if err != nil {
   359  					return errValue(meta.ErrRead, "GetByPath: read field length failed.", err), address
   360  				}
   361  				messageLen += Len
   362  			}
   363  
   364  			fd := desc.Message().ByName(name)
   365  			if fd == nil {
   366  				return errValue(meta.ErrUnknownField, fmt.Sprintf("field name '%s' is not defined in IDL", name), nil), address
   367  			}
   368  
   369  			desc = fd.Type()
   370  			tt = desc.Type()
   371  			start, err = searchFieldId(&p, fd.Number(), messageLen)
   372  			if err == errNotFound {
   373  				tt = proto.MESSAGE
   374  			}
   375  		case PathIndex:
   376  			elementWireType := desc.Elem().WireType()
   377  			isPacked := desc.IsPacked()
   378  			start, err = searchIndex(&p, path.int(), elementWireType, isPacked, desc.BaseId())
   379  			tt = desc.Elem().Type()
   380  			if err == errNotFound {
   381  				tt = proto.LIST
   382  			}
   383  		case PathStrKey:
   384  			mapFieldNumber := desc.BaseId()
   385  			start, err = searchStrKey(&p, path.str(), proto.STRING, mapFieldNumber)
   386  			tt = desc.Elem().Type()
   387  			valueDesc := desc.Elem()
   388  			desc = valueDesc
   389  			if err == errNotFound {
   390  				tt = proto.MAP
   391  			}
   392  		case PathIntKey:
   393  			keyType := desc.Key().Type()
   394  			mapFieldNumber := desc.BaseId()
   395  			start, err = searchIntKey(&p, path.int(), keyType, mapFieldNumber)
   396  			tt = desc.Elem().Type()
   397  			valueDesc := desc.Elem()
   398  			desc = valueDesc
   399  			if err == errNotFound {
   400  				tt = proto.MAP
   401  			}
   402  		default:
   403  			return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid %dth path: %#v", i, p), nil), address
   404  		}
   405  		// after search function, p.Read will always point to the tag position except when packed list element
   406  		address[i] = start
   407  
   408  		if err != nil {
   409  			// the last one not foud, return start pointer for subsequently inserting operation on `SetByPath()`
   410  			if i == len(pathes)-1 && err == errNotFound {
   411  				return Value{errNotFoundLast(unsafe.Pointer(uintptr(self.v)+uintptr(start)), tt), nil, false}, address
   412  			}
   413  			en := err.(Node)
   414  			return errValue(en.ErrCode().Behavior(), "invalid value node.", err), address
   415  		}
   416  		// if not the last one, it must be a complex node, so need to skip tag
   417  		if i != len(pathes)-1 {
   418  			if _, _, _, err := p.ConsumeTag(); err != nil {
   419  				return errValue(meta.ErrRead, "invalid field tag failed.", err), address
   420  			}
   421  		}
   422  
   423  	}
   424  
   425  	// check the result node type to get the right slice bytes
   426  	switch tt {
   427  	case proto.MAP:
   428  		kt = desc.Key().Type()
   429  		et = desc.Elem().Type()
   430  		if s, err := p.SkipAllElements(desc.BaseId(), desc.IsPacked()); err != nil {
   431  			en := err.(Node)
   432  			return errValue(en.ErrCode().Behavior(), "invalid map node.", err), address
   433  		} else {
   434  			size = s
   435  		}
   436  	case proto.LIST:
   437  		et = desc.Elem().Type()
   438  		if s, err := p.SkipAllElements(desc.BaseId(), desc.IsPacked()); err != nil {
   439  			en := err.(Node)
   440  			return errValue(en.ErrCode().Behavior(), "invalid list node.", err), address
   441  		} else {
   442  			size = s
   443  		}
   444  	default:
   445  		// node condition: field element, list element, map value element
   446  		var skipType proto.WireType
   447  		
   448  		// only packed list element no tag to skip
   449  		if desc.IsPacked() == false {
   450  			if _, _, _, err := p.ConsumeTag(); err != nil {
   451  				return errValue(meta.ErrRead, "invalid field tag.", err), address
   452  			}
   453  			start = p.Read
   454  		}
   455  		
   456  		if desc.Type() != proto.LIST{
   457  			skipType = desc.WireType()
   458  		} else {
   459  			skipType = desc.Elem().WireType()
   460  			desc = desc.Elem()
   461  		}
   462  
   463  		if err := p.Skip(skipType, false); err != nil {
   464  			return errValue(meta.ErrRead, "skip field error.", err), address
   465  		}
   466  	}
   467  
   468  	return wrapValue(self.Node.sliceComplex(start, p.Read, tt, kt, et, size), desc), address
   469  }
   470  
   471  // SetByPath searches longitudinally and sets a sub value at the given path from the value.
   472  // exist tells whether the node is already exists.
   473  func (self *Value) SetByPath(sub Node, path ...Path) (exist bool, err error) {
   474  	l := len(path)
   475  	if l == 0 {
   476  		if self.t != sub.t {
   477  			return false, errValue(meta.ErrDismatchType, "self node type is not equal to sub node type.", nil)
   478  		}
   479  		self.Node = sub // it means replace the root value ?
   480  		return true, nil
   481  	}
   482  
   483  	if err := self.Check(); err != nil {
   484  		return false, err
   485  	}
   486  
   487  	if self.Error() != "" {
   488  		return false, wrapError(meta.ErrInvalidParam, "given node is invalid.", sub)
   489  	}
   490  
   491  	// search source node by path
   492  	v, address := self.getByPath(path...)
   493  	if v.IsError() {
   494  		if !v.isErrNotFoundLast() {
   495  			return false, v
   496  		}
   497  
   498  		// find target node descriptor
   499  		targetPath := path[l-1]
   500  		desc, err := getDescByPath(self.Desc, path[:l-1]...)
   501  		// var fd *proto.FieldDescriptor
   502  		if err != nil {
   503  			return false, err
   504  		}
   505  
   506  		// exchange PathFieldName to create PathFieldId
   507  		if targetPath.t == PathFieldName {
   508  			f := desc.Message().ByName(targetPath.str())
   509  			targetPath = NewPathFieldId(f.Number())
   510  			desc = f.Type()
   511  		}
   512  		
   513  		// set sub node bytes by path and descriptor to check whether the node need to append tag
   514  		if err := v.setNotFound(targetPath, &sub, desc); err != nil {
   515  			return false, err
   516  		}
   517  	} else {
   518  		exist = true
   519  	}
   520  
   521  	originLen := len(self.raw()) // root buf length
   522  	err = self.replace(v.Node, sub) // replace ErrorNode bytes by sub Node bytes
   523  	isPacked := path[l-1].t == PathIndex && sub.t.IsPacked()
   524  	self.updateByteLen(originLen, address, isPacked, path...)
   525  	return
   526  }
   527  
   528  // update parent node bytes length
   529  func (self *Value) updateByteLen(originLen int, address []int, isPacked bool, path ...Path) {
   530  	afterLen := self.l
   531  	diffLen := afterLen - originLen
   532  	previousType := proto.UNKNOWN
   533  
   534  	for i := len(address) - 1; i >= 0; i-- {
   535  		// notice: when i == len(address) - 1, it do not change bytes length because it has been changed in replace function, just change previousType
   536  		pathType := path[i].t
   537  		addressPtr := address[i]
   538  		if previousType == proto.MESSAGE || (previousType == proto.LIST && isPacked) {
   539  			newBytes := NewBytesFromPool()
   540  			// tag
   541  			buf := rt.BytesFrom(rt.AddPtr(self.v, uintptr(addressPtr)), self.l-addressPtr, self.l-addressPtr)
   542  			_, tagOffset := protowire.ConsumeVarint(buf)
   543  			// length
   544  			length, lenOffset := protowire.ConsumeVarint(buf[tagOffset:])
   545  			newLength := int(length) + diffLen
   546  			newBytes = protowire.AppendVarint(newBytes, uint64(newLength))
   547  			// length == 0 means had been deleted all the data in the field
   548  			if newLength == 0 {
   549  				newBytes = newBytes[:0]
   550  			}
   551  
   552  			subLen := len(newBytes) - lenOffset
   553  
   554  			if subLen == 0 {
   555  				// no need to change length
   556  				copy(buf[tagOffset:tagOffset+lenOffset], newBytes)
   557  				continue
   558  			}
   559  
   560  			// split length
   561  			srcHead := rt.AddPtr(self.v, uintptr(addressPtr+tagOffset))
   562  			if newLength == 0 {
   563  				// delete tag
   564  				srcHead = rt.AddPtr(self.v, uintptr(addressPtr))
   565  				subLen -= tagOffset
   566  			}
   567  
   568  			srcTail := rt.AddPtr(self.v, uintptr(addressPtr+tagOffset+lenOffset))
   569  			l0 := int(uintptr(srcHead) - uintptr(self.v))
   570  			l1 := len(newBytes)
   571  			l2 := int(uintptr(self.v) + uintptr(self.l) - uintptr(srcTail))
   572  
   573  			// copy three slices into new buffer
   574  			newBuf := make([]byte, l0+l1+l2)
   575  			copy(newBuf[:l0], rt.BytesFrom(self.v, l0, l0))
   576  			copy(newBuf[l0:l0+l1], newBytes)
   577  			copy(newBuf[l0+l1:l0+l1+l2], rt.BytesFrom(srcTail, l2, l2))
   578  			self.v = rt.GetBytePtr(newBuf)
   579  			self.l = int(len(newBuf))
   580  			if isPacked {
   581  				isPacked = false
   582  			}
   583  			diffLen += subLen
   584  			FreeBytesToPool(newBytes)
   585  		}
   586  
   587  		if pathType == PathStrKey || pathType == PathIntKey {
   588  			previousType = proto.MAP
   589  		} else if pathType == PathIndex {
   590  			previousType = proto.LIST
   591  		} else {
   592  			previousType = proto.MESSAGE
   593  		}
   594  	}
   595  }
   596  
   597  // UnsetByPath searches longitudinally and unsets a sub value at the given path from the value.
   598  func (self *Value) UnsetByPath(path ...Path) error {
   599  	l := len(path)
   600  	if l == 0 {
   601  		*self = Value{}
   602  		return nil
   603  	}
   604  	if err := self.Check(); err != nil {
   605  		return err
   606  	}
   607  
   608  	// search target node by path
   609  	var parentValue, address = self.getByPath(path[:l-1]...)
   610  	if parentValue.IsError() {
   611  		if parentValue.IsErrNotFound() {
   612  			print(address)
   613  			return nil
   614  		}
   615  		return parentValue
   616  	}
   617  
   618  	p := path[l-1]
   619  	var desc *proto.TypeDescriptor
   620  	var err error
   621  	
   622  	desc, err = getDescByPath(self.Desc, path[:l-1]...)
   623  	if err != nil {
   624  		return err
   625  	}
   626  	isPacked := desc.IsPacked()
   627  	
   628  	if p.t == PathFieldName {
   629  		f := desc.Message().ByName(p.str())
   630  		p = NewPathFieldId(f.Number())
   631  	} 
   632  
   633  	ret, position := parentValue.findDeleteChild(p)
   634  	if ret.IsError() {
   635  		return ret
   636  	}
   637  
   638  	originLen := len(self.raw())
   639  	if err := self.replace(ret, Node{t: ret.t}); err != nil {
   640  		return errValue(meta.ErrWrite, "replace node by empty node failed", err)
   641  	}
   642  	address = append(address, position) // must add one address align with path length
   643  	self.updateByteLen(originLen, address, isPacked, path...)
   644  	return nil
   645  }
   646  
   647  func (self *Value) findDeleteChild(path Path) (Node, int) {
   648  	tt := self.t // in fact, no need to judge which type
   649  	valueLen := self.l
   650  	exist := false
   651  	var start, end int
   652  
   653  	switch self.t {
   654  	case proto.MESSAGE:
   655  		it := self.iterFields()
   656  		// if not root node
   657  		if !self.IsRoot {
   658  			if l, err := it.p.ReadLength(); err != nil {
   659  				return errNode(meta.ErrRead, "", err), -1
   660  			} else {
   661  				valueLen = l
   662  			}
   663  		}
   664  		start = valueLen // start initial at the end of the message
   665  		end = 0          // end initial at the begin of the message
   666  
   667  		// previous has change PathFieldName to PathFieldId
   668  		if path.Type() != PathFieldId {
   669  			return errNode(meta.ErrDismatchType, "path type is not PathFieldId", nil), -1
   670  		}
   671  
   672  		messageStart := it.p.Read
   673  		id := path.id()
   674  		for it.p.Read < messageStart+valueLen {
   675  			fieldStart := it.p.Read
   676  			fieldNumber, wireType, _, tagErr := it.p.ConsumeTag()
   677  			if tagErr != nil {
   678  				return errNode(meta.ErrRead, "", tagErr), -1
   679  			}
   680  			if err := it.p.Skip(wireType, false); err != nil {
   681  				return errNode(meta.ErrRead, "", err), -1
   682  			}
   683  			fieldEnd := it.p.Read
   684  			// get all items of the same fieldNumber, find the min start and max end, because the fieldNumber may be repeated
   685  			if id == fieldNumber {
   686  				exist = true
   687  				if fieldStart < start {
   688  					start = fieldStart
   689  				}
   690  				if fieldEnd > end {
   691  					end = fieldEnd
   692  				}
   693  			}
   694  		}
   695  		if !exist {
   696  			return errNotFound, -1
   697  		}
   698  	case proto.LIST:
   699  		it := self.iterElems()
   700  		listIndex := 0
   701  		if path.Type() != PathIndex {
   702  			return errNode(meta.ErrDismatchType, "path type is not PathIndex", nil), -1
   703  		}
   704  		idx := path.int()
   705  
   706  		elemType := self.Desc.Elem().WireType()
   707  		size, err := self.Len()
   708  		if err != nil {
   709  			return errNode(meta.ErrRead, "", err), -1
   710  		}
   711  
   712  		// size = 0 maybe list in lazy load, need to check idx
   713  		if size > 0 && idx >= size {
   714  			return errNotFound, -1
   715  		}
   716  		// packed : [ListTag][ListLen][(l)v][(l)v][(l)v][(l)v].....
   717  		if self.Desc.IsPacked() {
   718  			if _, _, _, err := it.p.ConsumeTag(); err != nil {
   719  				return errNode(meta.ErrRead, "", err), -1
   720  			}
   721  
   722  			if _, lengthErr := it.p.ReadLength(); lengthErr != nil {
   723  				return errNode(meta.ErrRead, "", lengthErr), -1
   724  			}
   725  
   726  			for it.p.Read < valueLen && listIndex <= idx {
   727  				start = it.p.Read
   728  				if err := it.p.Skip(elemType, false); err != nil {
   729  					return errNode(meta.ErrRead, "", err), -1
   730  				}
   731  				end = it.p.Read
   732  				listIndex++
   733  			}
   734  		} else {
   735  			// unpacked : [tag][l][v][tag][l][v][tag][l][v][tag][l][v]....
   736  			for it.p.Read < valueLen && listIndex <= idx {
   737  				start = it.p.Read
   738  				if _, _, _, err := it.p.ConsumeTag(); err != nil {
   739  					return errNode(meta.ErrRead, "", err), -1
   740  				}
   741  
   742  				if err := it.p.Skip(elemType, false); err != nil {
   743  					return errNode(meta.ErrRead, "", err), -1
   744  				}
   745  				end = it.p.Read
   746  				listIndex++
   747  			}
   748  		}
   749  	case proto.MAP:
   750  		it := self.iterPairs()
   751  
   752  		if self.kt == proto.STRING {
   753  			key := path.str()
   754  			for it.p.Read < valueLen {
   755  				start = it.p.Read
   756  				// pair
   757  				if _, _, _, err := it.p.ConsumeTag(); err != nil {
   758  					return errNode(meta.ErrRead, "", err), -1
   759  				}
   760  				if _, err := it.p.ReadLength(); err != nil {
   761  					return errNode(meta.ErrRead, "", err), -1
   762  				}
   763  
   764  				// key
   765  				if _, _, _, err := it.p.ConsumeTag(); err != nil {
   766  					return errNode(meta.ErrRead, "", err), -1
   767  				}
   768  				k, err := it.p.ReadString(false)
   769  				if err != nil {
   770  					return errNode(meta.ErrRead, "", err), -1
   771  				}
   772  
   773  				// value
   774  				_, valueWire, _, _ := it.p.ConsumeTag()
   775  				if err := it.p.Skip(valueWire, false); err != nil {
   776  					return errNode(meta.ErrRead, "", err), -1
   777  				}
   778  				end = it.p.Read
   779  				if k == key {
   780  					exist = true
   781  					break
   782  				}
   783  			}
   784  		} else if self.kt.IsInt() {
   785  			key := path.Int()
   786  			for it.p.Read < valueLen {
   787  				start = it.p.Read
   788  
   789  				if _, _, _, err := it.p.ConsumeTag(); err != nil {
   790  					return errNode(meta.ErrRead, "", err), -1
   791  				}
   792  
   793  				if _, err := it.p.ReadLength(); err != nil {
   794  					return errNode(meta.ErrRead, "", err), -1
   795  				}
   796  
   797  				// key
   798  				if _, _, _, err := it.p.ConsumeTag(); err != nil {
   799  					return errNode(meta.ErrRead, "", err), -1
   800  				}
   801  
   802  				k, err := it.p.ReadInt(self.kt)
   803  				if err != nil {
   804  					return errNode(meta.ErrRead, "", err), -1
   805  				}
   806  
   807  				//value
   808  				_, valueWire, _, _ := it.p.ConsumeTag()
   809  				if err := it.p.Skip(valueWire, false); err != nil {
   810  					return errNode(meta.ErrRead, "", err), -1
   811  				}
   812  				end = it.p.Read
   813  				if k == key {
   814  					exist = true
   815  					break
   816  				}
   817  			}
   818  		}
   819  		if !exist {
   820  			return errNotFound, -1
   821  		}
   822  	default:
   823  		return errNotFound, -1
   824  	}
   825  	return Node{
   826  		t: tt,
   827  		v: rt.AddPtr(self.v, uintptr(start)),
   828  		l: end - start,
   829  	}, start
   830  }
   831  
   832  // MarshalTo marshals self value into a sub value descripted by the to descriptor, alse called as "Cutting".
   833  // Usually, the to descriptor is a subset of self descriptor.
   834  func (self Value) MarshalTo(to *proto.TypeDescriptor, opts *Options) ([]byte, error) {
   835  	var w = binary.NewBinaryProtocolBuffer()
   836  	var r = binary.BinaryProtocol{}
   837  	r.Buf = self.raw()
   838  	var from = self.Desc
   839  	messageLen := len(r.Buf)
   840  	if err := marshalTo(&r, w, from, to, opts, messageLen); err != nil {
   841  		return nil, err
   842  	}
   843  	ret := make([]byte, len(w.Buf))
   844  	copy(ret, w.Buf)
   845  	binary.FreeBinaryProtocol(w)
   846  	return ret, nil
   847  }
   848  
   849  func marshalTo(read *binary.BinaryProtocol, write *binary.BinaryProtocol, from *proto.TypeDescriptor, to *proto.TypeDescriptor, opts *Options, massageLen int) error {
   850  	tail := read.Read + massageLen
   851  	for read.Read < tail {
   852  		fieldNumber, wireType, _, _ := read.ConsumeTag()
   853  		fromField := from.Message().ByNumber(fieldNumber)
   854  
   855  		if fromField == nil {
   856  			if opts.DisallowUnknown {
   857  				return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", fieldNumber), nil)
   858  			} else {
   859  				// if not set, skip to the next field
   860  				if err := read.Skip(wireType, opts.UseNativeSkip); err != nil {
   861  					return wrapError(meta.ErrRead, "", err)
   862  				}
   863  				continue
   864  			}
   865  		}
   866  
   867  		toField := to.Message().ByNumber(fieldNumber)
   868  
   869  		if toField == nil {
   870  			// if not set, skip to the next field
   871  			if err := read.Skip(wireType, opts.UseNativeSkip); err != nil {
   872  				return wrapError(meta.ErrRead, "", err)
   873  			}
   874  			continue
   875  		}
   876  
   877  		fromType := fromField.Kind()
   878  		toType := toField.Kind()
   879  		if fromType != toType {
   880  			return wrapError(meta.ErrDismatchType, "to descriptor dismatches from descriptor", nil)
   881  		}
   882  
   883  		// when FieldDescriptor.Kind() == MessageKind, it contained 3 conditions: message list, message map value, message;
   884  		if fromType == proto.MessageKind {
   885  			fromDesc := fromField.Type()
   886  			toDesc := toField.Type()
   887  			// message list
   888  			if fromDesc.Type() == proto.LIST{
   889  				fromDesc = fromDesc.Elem()
   890  				toDesc = toDesc.Elem()
   891  			}
   892  
   893  			write.AppendTag(fieldNumber, wireType)
   894  			var pos int
   895  			subMessageLen, err := read.ReadLength()
   896  			if err != nil {
   897  				return wrapError(meta.ErrRead, "", err)
   898  			}
   899  			write.Buf, pos = binary.AppendSpeculativeLength(write.Buf)
   900  			marshalTo(read, write, fromDesc, toDesc, opts, subMessageLen)
   901  			write.Buf = binary.FinishSpeculativeLength(write.Buf, pos)
   902  		} else {
   903  			start := read.Read
   904  			if err := read.Skip(wireType, opts.UseNativeSkip); err != nil {
   905  				return wrapError(meta.ErrRead, "", err)
   906  			}
   907  			end := read.Read
   908  			value := read.Buf[start:end]
   909  
   910  			write.AppendTag(fieldNumber, wireType)
   911  			write.Buf = append(write.Buf, value...)
   912  		}
   913  	}
   914  	return nil
   915  }
   916  
   917  // GetByInt returns a sub node at the given key from a MAP value.
   918  func (self Value) GetByStr(key string) (v Value) {
   919  	n := self.Node.GetByStr(key)
   920  	vd := self.Desc.Elem()
   921  	if n.IsError() {
   922  		return wrapValue(n, nil)
   923  	}
   924  	return wrapValue(n, vd)
   925  }
   926  
   927  // GetByInt returns a sub node at the given key from a MAP value.
   928  func (self Value) GetByInt(key int) (v Value) {
   929  	n := self.Node.GetByInt(key)
   930  	vd := self.Desc.Elem()
   931  	if n.IsError() {
   932  		return wrapValue(n, nil)
   933  	}
   934  	return wrapValue(n, vd)
   935  }
   936  
   937  // Index returns a sub node at the given index from a LIST value.
   938  func (self Value) Index(i int) (v Value) {
   939  	n := self.Node.Index(i)
   940  	if n.IsError() {
   941  		return wrapValue(n, nil)
   942  	}
   943  	v = wrapValue(n, self.Desc.Elem())
   944  	return
   945  }
   946  
   947  // FieldByName returns a sub node at the given field name from a MESSAGE value.
   948  func (self Value) FieldByName(name string) (v Value) {
   949  	if err := self.should("FieldByName", proto.MESSAGE); err != "" {
   950  		return errValue(meta.ErrUnsupportedType, err, nil)
   951  	}
   952  
   953  	it := self.iterFields()
   954  	if !self.IsRoot {
   955  		if _, err := it.p.ReadLength(); err != nil {
   956  			return errValue(meta.ErrRead, "", err)
   957  		}
   958  	}
   959  
   960  	f := self.Desc.Message().ByName(name)
   961  	if f == nil {
   962  		return errValue(meta.ErrUnknownField, fmt.Sprintf("field '%s' is not defined in IDL", name), nil)
   963  	}
   964  
   965  	// not found, try to scan the whole bytes
   966  
   967  	if it.Err != nil {
   968  		return errValue(meta.ErrRead, "", it.Err)
   969  	}
   970  	for it.HasNext() {
   971  		i, wt, s, e, tagPos := it.Next(UseNativeSkipForGet)
   972  		if i == f.Number() {
   973  			typDesc := f.Type()
   974  			if typDesc.IsMap() || typDesc.IsList() {
   975  				it.p.Read = tagPos
   976  				if _, err := it.p.SkipAllElements(i, typDesc.IsPacked()); err != nil {
   977  					return errValue(meta.ErrRead, "SkipAllElements in LIST/MAP failed", err)
   978  				}
   979  				s = tagPos
   980  				e = it.p.Read
   981  
   982  				v = self.sliceWithDesc(s, e, typDesc)
   983  				goto ret
   984  			}
   985  
   986  			t := proto.Kind2Wire[f.Kind()]
   987  			if wt != t {
   988  				v = errValue(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", string(f.Name()), t, wt), nil)
   989  				goto ret
   990  			}
   991  			v = self.sliceWithDesc(s, e, typDesc)
   992  			goto ret
   993  		} else if it.Err != nil {
   994  			v = errValue(meta.ErrRead, "", it.Err)
   995  			goto ret
   996  		}
   997  	}
   998  
   999  	v = errValue(meta.ErrNotFound, fmt.Sprintf("field '%s' is not found in this value", name), errNotFound)
  1000  ret:
  1001  	// it.Recycle()
  1002  	return
  1003  }
  1004  
  1005  // Field returns a sub node at the given field id from a MESSAGE value.
  1006  func (self Value) Field(id proto.FieldNumber) (v Value) {
  1007  	rootLayer := self.IsRoot
  1008  	msgDesc := self.Desc.Message()
  1009  	 
  1010  	n, d := self.Node.Field(id, rootLayer, msgDesc)
  1011  
  1012  	if n.IsError() {
  1013  		return wrapValue(n, nil)
  1014  	}
  1015  	return wrapValue(n, d.Type())
  1016  }
  1017  
  1018  // GetMany searches transversely and returns all the sub nodes along with the given pathes.
  1019  func (self Value) GetMany(pathes []PathNode, opts *Options) error {
  1020  	if len(pathes) == 0 {
  1021  		return nil
  1022  	}
  1023  	return self.getMany(pathes, opts.ClearDirtyValues, opts)
  1024  }
  1025  
  1026  func (self Value) getMany(pathes []PathNode, clearDirty bool, opts *Options) error {
  1027  	if clearDirty {
  1028  		for i := range pathes {
  1029  			pathes[i].Node = Node{}
  1030  		}
  1031  	}
  1032  	p := pathes[0]
  1033  	switch p.Path.t {
  1034  	case PathFieldId:
  1035  		return self.Fields(pathes, opts)
  1036  	case PathIndex:
  1037  		return self.Indexes(pathes, opts)
  1038  	case PathStrKey, PathIntKey, PathBinKey:
  1039  		return self.Gets(pathes, opts)
  1040  	default:
  1041  		return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid path: %#v", p), nil)
  1042  	}
  1043  }
  1044  
  1045  func (self Value) Fields(ids []PathNode, opts *Options) error {
  1046  	rootLayer := self.IsRoot
  1047  	msgDesc := self.Desc.Message()
  1048  
  1049  	err := self.Node.Fields(ids, rootLayer, msgDesc, opts)
  1050  	return err
  1051  }
  1052  
  1053  // SetMany: set a list of sub nodes at the given pathes from the value.
  1054  // root *Value: the root Node
  1055  // self *Value: the current Node (maybe root Node)
  1056  // address []int: the address from target Nodes to the root Node
  1057  // path ...Path: the path from root Node to target Nodes
  1058  func (self *Value) SetMany(pathes []PathNode, opts *Options, root *Value, address []int, path ...Path) (err error) {
  1059  	if len(pathes) == 0 {
  1060  		return nil
  1061  	}
  1062  
  1063  	if err := self.Check(); err != nil {
  1064  		return err
  1065  	}
  1066  
  1067  	// copy original pathes
  1068  	ps := pnsPool.Get().(*pnSlice)
  1069  	if cap(ps.a) < len(pathes) {
  1070  		ps.a = make([]PathNode, len(pathes))
  1071  	} else {
  1072  		ps.a = ps.a[:len(pathes)]
  1073  	}
  1074  	copy(ps.a, pathes)
  1075  	ps.b = pathes
  1076  	originLen := len(self.raw()) // current buf length
  1077  	rootLen := len(root.raw())   // root buf length
  1078  	isPacked := self.Desc.IsPacked()
  1079  
  1080  	// get original values
  1081  	if err = self.getMany(ps.a, true, opts); err != nil {
  1082  		goto ret
  1083  	}
  1084  
  1085  	// handle not found values
  1086  	for i, a := range ps.a {
  1087  		if a.IsUnKnown() {
  1088  			var sp unsafe.Pointer
  1089  			if self.t.IsComplex() {
  1090  				sp = rt.AddPtr(self.v, uintptr(self.l))
  1091  			}
  1092  			ps.a[i].Node = errNotFoundLast(sp, self.t)
  1093  			ps.a[i].Node.setNotFound(a.Path, &ps.b[i].Node, self.Desc)
  1094  			if self.t == proto.LIST || self.t == proto.MAP {
  1095  				self.size += 1
  1096  			}
  1097  		}
  1098  	}
  1099  
  1100  	// if current is not root node, update current Node length
  1101  	if !self.IsRoot {
  1102  		err = self.replaceMany(ps)
  1103  		if self.t == proto.LIST && isPacked {
  1104  			currentAdd := []int{0, -1}
  1105  			currentPath := []Path{NewPathIndex(-1), NewPathIndex(-1)}
  1106  			self.updateByteLen(originLen, currentAdd, isPacked, currentPath...)
  1107  		} else if self.t == proto.MESSAGE {
  1108  			buf := self.raw()
  1109  			_, lenOffset := protowire.ConsumeVarint(buf)
  1110  			byteLen := len(buf) - lenOffset
  1111  			newLen := protowire.AppendVarint(nil, uint64(byteLen))
  1112  			// newLen + buf[lenOffset:]
  1113  			l0 := len(newLen)
  1114  			l1 := byteLen
  1115  			newBuf := make([]byte, l0+l1)
  1116  			copy(newBuf[:l0], newLen)
  1117  			copy(newBuf[l0:], buf[lenOffset:])
  1118  			self.v = rt.GetBytePtr(newBuf)
  1119  			self.l = int(len(newBuf))
  1120  		}
  1121  	}
  1122  
  1123  	// update root length
  1124  	err = root.replaceMany(ps)
  1125  	root.updateByteLen(rootLen, address, isPacked, path...)
  1126  ret:
  1127  	ps.b = nil
  1128  	pnsPool.Put(ps)
  1129  	return
  1130  }