github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/value.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  	"unsafe"
    22  
    23  	"github.com/cloudwego/dynamicgo/internal/rt"
    24  	"github.com/cloudwego/dynamicgo/meta"
    25  	"github.com/cloudwego/dynamicgo/thrift"
    26  )
    27  
    28  // Value is a generic API wrapper for operations on thrift data.
    29  // Node is the underlying raw bytes.
    30  // Desc is the corresponding type descriptor.
    31  type Value struct {
    32  	Node
    33  	Desc *thrift.TypeDescriptor
    34  }
    35  
    36  // NewValue creates a new Value from a raw byte slice.
    37  func NewValue(desc *thrift.TypeDescriptor, src []byte) Value {
    38  	return Value{
    39  		Node: NewNode(desc.Type(), src),
    40  		Desc: desc,
    41  	}
    42  }
    43  
    44  // NewValueFromNode copy both Node and TypeDescriptor from another Value.
    45  func (self Value) Fork() Value {
    46  	ret := self
    47  	ret.Node = self.Node.Fork()
    48  	return ret
    49  }
    50  
    51  func (self Value) slice(s int, e int, desc *thrift.TypeDescriptor) Value {
    52  	t := desc.Type()
    53  	ret := Value{
    54  		Node: Node{
    55  			t: t,
    56  			l: (e - s),
    57  			v: rt.AddPtr(self.v, uintptr(s)),
    58  		},
    59  		Desc: desc,
    60  	}
    61  	if t == thrift.LIST || t == thrift.SET {
    62  		ret.et = desc.Elem().Type()
    63  	} else if t == thrift.MAP {
    64  		ret.kt = desc.Key().Type()
    65  		ret.et = desc.Elem().Type()
    66  	}
    67  	return ret
    68  }
    69  
    70  func searchFieldName(p *thrift.BinaryProtocol, id string, f *thrift.FieldDescriptor) (tt thrift.Type, start int, err error) {
    71  	// if _, err := p.ReadStructBegin(); err != nil {
    72  	// 	return 0, start, wrapError(meta.ErrReadInput, "", err)
    73  	// }
    74  	for {
    75  		_, t, i, err := p.ReadFieldBegin()
    76  		if err != nil {
    77  			return 0, start, wrapError(meta.ErrRead, "", err)
    78  		}
    79  		if t == thrift.STOP {
    80  			return thrift.STRUCT, start, errNotFound
    81  		}
    82  		if f.ID() == thrift.FieldID(i) {
    83  			// if t != f.Type().Type() {
    84  			// 	return 0, start, wrapError(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil)
    85  			// }
    86  			start = p.Read
    87  			tt = t
    88  			break
    89  		}
    90  		if err := p.Skip(t, UseNativeSkipForGet); err != nil {
    91  			return thrift.STRUCT, start, wrapError(meta.ErrRead, "", err)
    92  		}
    93  	}
    94  	return
    95  }
    96  
    97  // GetByPath searches longitudinally and return a sub value at the given path from the value.
    98  //
    99  // The path is a list of PathFieldId, PathFieldName, PathIndex, PathStrKey, PathBinKey, PathIntKey,
   100  // Each path MUST be a valid path type for current layer (e.g. PathFieldId is only valid for STRUCT).
   101  // Empty path will return the current value.
   102  func (self Value) GetByPath(pathes ...Path) Value {
   103  	if self.Error() != "" {
   104  		return self
   105  	}
   106  
   107  	p := thrift.BinaryProtocol{
   108  		Buf: self.raw(),
   109  	}
   110  	start := 0
   111  	desc := self.Desc
   112  	tt := self.t
   113  	isList := tt == thrift.LIST
   114  	var err error
   115  
   116  	for i, path := range pathes {
   117  		switch path.t {
   118  		case PathFieldId:
   119  			id := path.id()
   120  			tt, start, err = searchFieldId(&p, id)
   121  			desc = desc.Struct().FieldById(id).Type()
   122  			isList = tt == thrift.LIST
   123  		case PathFieldName:
   124  			id := path.str()
   125  			f := desc.Struct().FieldByKey(id)
   126  			if f == nil {
   127  				return errValue(meta.ErrUnknownField, fmt.Sprintf("field name '%s' is not defined in IDL", id), nil)
   128  			}
   129  			tt, start, err = searchFieldName(&p, id, f)
   130  			desc = f.Type()
   131  			isList = tt == thrift.LIST
   132  		case PathIndex:
   133  			tt, start, err = searchIndex(&p, path.int(), isList)
   134  			desc = desc.Elem()
   135  		case PathStrKey:
   136  			tt, start, err = searchStrKey(&p, path.str())
   137  			desc = desc.Elem()
   138  		case PathIntKey:
   139  			tt, start, err = searchIntKey(&p, path.int())
   140  			desc = desc.Elem()
   141  		case PathBinKey:
   142  			tt, start, err = searchBinKey(&p, path.bin())
   143  			desc = desc.Elem()
   144  		default:
   145  			return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid %dth path: %#v", i, p), nil)
   146  		}
   147  		if err != nil {
   148  			// the last one not foud, return start pointer for subsequently inserting operation on `SetByPath()`
   149  			if i == len(pathes)-1 && err == errNotFound {
   150  				return Value{errNotFoundLast(unsafe.Pointer(uintptr(self.v)+uintptr(start)), tt), nil}
   151  			}
   152  			en := err.(Node)
   153  			return errValue(en.ErrCode().Behavior(), "", err)
   154  		}
   155  	}
   156  
   157  	if err := p.Skip(desc.Type(), UseNativeSkipForGet); err != nil {
   158  		return errValue(meta.ErrRead, "", err)
   159  	}
   160  	return self.slice(start, p.Read, desc)
   161  }
   162  
   163  // Field returns a sub node at the given field id from a STRUCT value.
   164  func (self Value) Field(id thrift.FieldID) (v Value) {
   165  	n := self.Node.Field(id)
   166  	if n.IsError() {
   167  		return wrapValue(n, nil)
   168  	}
   169  
   170  	f := self.Desc.Struct().FieldById(id)
   171  	if f == nil {
   172  		return errValue(meta.ErrUnknownField, fmt.Sprintf("field id %d is not defined in IDL", id), nil)
   173  	}
   174  
   175  	return wrapValue(n, f.Type())
   176  }
   177  
   178  // func (self Value) Fields(ids []PathNode, opts *Options) (err error) {
   179  // 	if err := self.should("Fields", thrift.STRUCT); err != "" {
   180  // 		return errValue(meta.ErrUnsupportedType, err, nil)
   181  // 	}
   182  
   183  // 	it := self.iterFields()
   184  // 	if it.Err != nil {
   185  // 		return errValue(meta.ErrReadInput, "", it.Err)
   186  // 	}
   187  
   188  // 	need := len(ids)
   189  // 	for count := 0; it.HasNext() && count < need; {
   190  // 		var p *PathNode
   191  // 		i, t, s, e := it.Next(opts.UseNativeSkip)
   192  // 		if it.Err != nil {
   193  // 			err = errValue(meta.ErrReadInput, "", it.Err)
   194  // 			goto ret
   195  // 		}
   196  // 		f := self.Desc.Struct().FieldById(i)
   197  // 		if f == nil {
   198  // 			if opts.DisallowUnknow {
   199  // 				err = errValue(meta.ErrUnknownField, fmt.Sprintf("field id %d is not defined in IDL", i), nil)
   200  // 				goto ret
   201  // 			}
   202  // 			continue
   203  
   204  // 		}
   205  // 		if t != f.Type().Type() {
   206  // 			err = errValue(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil)
   207  // 			goto ret
   208  // 		}
   209  // 		//TODO: use bitmap to avoid repeatedly scan
   210  // 		for j, id := range ids {
   211  // 			if (id.Path.t == PathFieldId && id.Path.Id() == i) || (id.Path.t == PathFieldName && id.Path.Str() == f.Name()) {
   212  // 				p = &ids[j]
   213  // 				count += 1
   214  // 				break
   215  // 			}
   216  // 		}
   217  // 		if p == nil {
   218  // 			continue
   219  // 		}
   220  // 		p.Node = self.Node.slice(s, e, f.Type().Type())
   221  // 	}
   222  
   223  // ret:
   224  // 	// it.Recycle()
   225  // 	return
   226  // }
   227  
   228  // FieldByName returns a sub node at the given field name from a STRUCT value.
   229  func (self Value) FieldByName(name string) (v Value) {
   230  	if err := self.should("FieldByName", thrift.STRUCT); err != "" {
   231  		return errValue(meta.ErrUnsupportedType, err, nil)
   232  	}
   233  
   234  	f := self.Desc.Struct().FieldByKey(name)
   235  	if f == nil {
   236  		return errValue(meta.ErrUnknownField, fmt.Sprintf("field '%s' is not defined in IDL", name), nil)
   237  	}
   238  
   239  	// not found, try to scan the whole bytes
   240  	it := self.iterFields()
   241  	if it.Err != nil {
   242  		return errValue(meta.ErrRead, "", it.Err)
   243  	}
   244  	for it.HasNext() {
   245  		i, t, s, e := it.Next(UseNativeSkipForGet)
   246  		if i == f.ID() {
   247  			if t != f.Type().Type() {
   248  				v = errValue(meta.ErrDismatchType, fmt.Sprintf("field '%s' expects type %s, buf got type %s", f.Name(), f.Type().Type(), t), nil)
   249  				goto ret
   250  			}
   251  			v = self.slice(s, e, f.Type())
   252  			goto ret
   253  		} else if it.Err != nil {
   254  			v = errValue(meta.ErrRead, "", it.Err)
   255  			goto ret
   256  		}
   257  	}
   258  
   259  	v = errValue(meta.ErrNotFound, fmt.Sprintf("field '%s' is not found in this value", name), errNotFound)
   260  ret:
   261  	// it.Recycle()
   262  	return
   263  }
   264  
   265  // Index returns a sub node at the given index from a LIST value.
   266  func (self Value) Index(i int) (v Value) {
   267  	n := self.Node.Index(i)
   268  	if n.IsError() {
   269  		return wrapValue(n, nil)
   270  	}
   271  	return wrapValue(n, self.Desc.Elem())
   272  }
   273  
   274  // GetByStr returns a sub node at the given string key from a MAP value.
   275  func (self Value) GetByStr(key string) (v Value) {
   276  	n := self.Node.GetByStr(key)
   277  	if n.IsError() {
   278  		return wrapValue(n, nil)
   279  	}
   280  	return wrapValue(n, self.Desc.Elem())
   281  }
   282  
   283  // GetByInt returns a sub node at the given int key from a MAP value.
   284  func (self Value) GetByInt(key int) (v Value) {
   285  	n := self.Node.GetByInt(key)
   286  	if n.IsError() {
   287  		return wrapValue(n, nil)
   288  	}
   289  	return wrapValue(n, self.Desc.Elem())
   290  }
   291  
   292  // func (self Value) GetMany(pathes []PathNode, opts *Options) error {
   293  // 	if len(pathes) == 0 {
   294  // 		return nil
   295  // 	}
   296  // 	p := pathes[0]
   297  // 	switch p.Path.t {
   298  // 	case PathFieldId, PathFieldName:
   299  // 		return self.Fields(pathes, opts)
   300  // 	case PathIndex:
   301  // 		return self.Indexes(pathes, opts)
   302  // 	case PathStrKey, PathIntKey:
   303  // 		return self.Gets(pathes, opts)
   304  // 	case PathObjKey:
   305  // 		panic("not implement yet")
   306  // 	default:
   307  // 		return errValue(meta.ErrUnsupportedType, fmt.Sprintf("invalid path: %#v", p), nil)
   308  // 	}
   309  // }
   310  
   311  // SetByPath searches longitudinally and sets a sub value at the given path from the value.
   312  // exist tells whether the node is already exists.
   313  func (self *Value) SetByPath(sub Value, path ...Path) (exist bool, err error) {
   314  	l := len(path)
   315  	if l == 0 {
   316  		*self = sub
   317  		return true, nil
   318  	}
   319  	if err := self.Check(); err != nil {
   320  		return false, err
   321  	}
   322  	if sub.Error() != "" {
   323  		return false, meta.NewError(meta.ErrInvalidParam, "given node is invalid", sub)
   324  	}
   325  
   326  	// search source node by path
   327  	v := self.GetByPath(path...)
   328  	if v.IsError() {
   329  		if !v.isErrNotFoundLast() {
   330  			return false, v
   331  		}
   332  		p := path[l-1]
   333  		if p.t == PathFieldName {
   334  			desc, err := GetDescByPath(self.Desc, path[:l-1]...)
   335  			if err != nil {
   336  				return false, err
   337  			}
   338  			f := desc.Struct().FieldByKey(p.str())
   339  			p = NewPathFieldId(f.ID())
   340  		}
   341  		if err := v.setNotFound(p, &sub.Node); err != nil {
   342  			return false, err
   343  		}
   344  	} else {
   345  		exist = true
   346  	}
   347  	err = self.replace(v.Node, sub.Node)
   348  	return
   349  }
   350  
   351  // UnsetByPath searches longitudinally and unsets a sub value at the given path from the value.
   352  func (self *Value) UnsetByPath(path ...Path) error {
   353  	l := len(path)
   354  	if l == 0 {
   355  		*self = Value{}
   356  		return nil
   357  	}
   358  	if err := self.Check(); err != nil {
   359  		return err
   360  	}
   361  	// search parent node by path
   362  	var v = self.GetByPath(path[:l-1]...)
   363  	if v.IsError() {
   364  		if v.IsErrNotFound() {
   365  			return nil
   366  		}
   367  		return v
   368  	}
   369  	p := path[l-1]
   370  	if p.t == PathFieldName {
   371  		desc, err := GetDescByPath(self.Desc, path[:l-1]...)
   372  		if err != nil {
   373  			return err
   374  		}
   375  		f := desc.Struct().FieldByKey(p.str())
   376  		p = NewPathFieldId(f.ID())
   377  	}
   378  	ret := v.deleteChild(p)
   379  	if ret.IsError() {
   380  		return ret
   381  	}
   382  	return self.replace(ret, Node{t: ret.t})
   383  }
   384  
   385  // var pathesPool = sync.Pool{
   386  // 	New: func() interface{} {
   387  // 		return &pathSlice{
   388  // 			a: make([]PathNode, 0, defaultNodeSliceCap),
   389  // 		}
   390  // 	},
   391  // }
   392  
   393  // func (self *Value) SetMany(pathes []PathNode, opts *Options) (err error) {
   394  // 	if len(pathes) == 0 {
   395  // 		return nil
   396  // 	}
   397  // 	if err := self.Check(); err != nil {
   398  // 		return err
   399  // 	}
   400  
   401  // 	// copy original pathes
   402  // 	ps := pnsPool.Get().(*pnSlice)
   403  // 	if cap(ps.a) < len(pathes) {
   404  // 		ps.a = make([]PathNode, len(pathes))
   405  // 	} else {
   406  // 		ps.a = ps.a[:len(pathes)]
   407  // 	}
   408  // 	copy(ps.a, pathes)
   409  // 	ps.b = pathes
   410  
   411  // 	// get original values
   412  // 	if err = self.GetMany(ps.a, opts); err != nil {
   413  // 		goto ret
   414  // 	}
   415  
   416  // 	err = self.replaceMany(ps)
   417  // ret:
   418  // 	ps.b = nil
   419  // 	pnsPool.Put(ps)
   420  // 	return
   421  // }
   422  
   423  // MarshalTo marshals self value into a sub value descripted by the to descriptor, alse called as "Cutting".
   424  // Usually, the to descriptor is a subset of self descriptor.
   425  func (self Value) MarshalTo(to *thrift.TypeDescriptor, opts *Options) ([]byte, error) {
   426  	var w = thrift.NewBinaryProtocolBuffer()
   427  	var r = thrift.BinaryProtocol{}
   428  	r.Buf = self.raw()
   429  	var from = self.Desc
   430  	if from.Type() != to.Type() {
   431  		return nil, wrapError(meta.ErrDismatchType, "to descriptor dismatches from descriptor", nil)
   432  	}
   433  	if err := marshalTo(&r, w, from, to, opts); err != nil {
   434  		return nil, err
   435  	}
   436  	ret := make([]byte, len(w.Buf))
   437  	copy(ret, w.Buf)
   438  	thrift.FreeBinaryProtocolBuffer(w)
   439  	return ret, nil
   440  }
   441  
   442  func marshalTo(read *thrift.BinaryProtocol, write *thrift.BinaryProtocol, from *thrift.TypeDescriptor, to *thrift.TypeDescriptor, opts *Options) error {
   443  	switch t := to.Type(); t {
   444  	case thrift.STRUCT:
   445  		if from == to {
   446  			return nil
   447  		}
   448  		var req *thrift.RequiresBitmap
   449  		if !opts.NotCheckRequireNess {
   450  			req = thrift.NewRequiresBitmap()
   451  			to.Struct().Requires().CopyTo(req)
   452  		}
   453  
   454  		for {
   455  			_, tt, i, err := read.ReadFieldBegin()
   456  			if err != nil {
   457  				return wrapError(meta.ErrRead, "", err)
   458  			}
   459  
   460  			if tt == thrift.STOP {
   461  				if !opts.NotCheckRequireNess {
   462  					if err := handleUnsets(*req, to.Struct(), write, opts.WriteDefault); err != nil {
   463  						return err
   464  					}
   465  				}
   466  				if err := write.WriteStructEnd(); err != nil {
   467  					return wrapError(meta.ErrWrite, "", err)
   468  				}
   469  				break
   470  			}
   471  
   472  			ff := from.Struct().FieldById(thrift.FieldID(i))
   473  			if ff == nil {
   474  				if opts.DisallowUnknow {
   475  					return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", i), nil)
   476  				} else {
   477  					// if not set, skip to the next field
   478  					if err := read.Skip(tt, opts.UseNativeSkip); err != nil {
   479  						return wrapError(meta.ErrRead, "", err)
   480  					}
   481  					continue
   482  				}
   483  			}
   484  
   485  			if tt != ff.Type().Type() {
   486  				return wrapError(meta.ErrDismatchType, fmt.Sprintf("field %d expects type %s, buf got type %s", ff.ID(), ff.Type().Type(), thrift.Type(tt)), nil)
   487  			}
   488  			// find corresponding field in the 'to' descriptor
   489  			// TODO: use field name to find the field
   490  			// var tf *thrift.FieldDescriptor
   491  			// if opts.FieldByName {
   492  			// 	tf = to.Struct().FieldByKey(ff.Name())
   493  			// } else {
   494  			tf := to.Struct().FieldById(thrift.FieldID(i))
   495  			// }
   496  			if tf == nil {
   497  				// if not set, skip to the next field
   498  				if err := read.Skip(tt, opts.UseNativeSkip); err != nil {
   499  					return wrapError(meta.ErrRead, "", err)
   500  				}
   501  				continue
   502  			}
   503  			// if tt != tf.Type().Type() {
   504  			// 	return wrapError(meta.ErrDismatchType, fmt.Sprintf("field %d expects type %s, buf got type %s", tf.ID(), tf.Type().Type(), thrift.Type(tt)), nil)
   505  			// }
   506  			if err := write.WriteFieldBegin(tf.Name(), tt, i); err != nil {
   507  				return wrapError(meta.ErrWrite, "", err)
   508  			}
   509  
   510  			if !opts.NotCheckRequireNess {
   511  				req.Set(tf.ID(), thrift.OptionalRequireness)
   512  			}
   513  
   514  			if err := marshalTo(read, write, ff.Type(), tf.Type(), opts); err != nil {
   515  				return err
   516  			}
   517  		}
   518  		if !opts.NotCheckRequireNess {
   519  			thrift.FreeRequiresBitmap(req)
   520  		}
   521  		return nil
   522  	case thrift.LIST, thrift.SET:
   523  		if from.Type() != thrift.LIST && from.Type() != thrift.SET {
   524  			return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type LIST or SET, buf got type %s", from.Type()), nil)
   525  		}
   526  		if to.Elem() == from.Elem() {
   527  			goto skip_val
   528  		}
   529  		et, size, err := read.ReadListBegin()
   530  		if err != nil {
   531  			return wrapError(meta.ErrRead, "", err)
   532  		}
   533  		// if et != to.Elem().Type() || et != from.Elem().Type() {
   534  		// 	return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect elem type %s, buf got type %s", from.Elem().Type(), et), nil)
   535  		// }
   536  		if err := write.WriteListBegin(et, size); err != nil {
   537  			return wrapError(meta.ErrWrite, "", err)
   538  		}
   539  		if size == 0 {
   540  			return nil
   541  		}
   542  		for i := 0; i < size; i++ {
   543  			if err := marshalTo(read, write, from.Elem(), to.Elem(), opts); err != nil {
   544  				return err
   545  			}
   546  		}
   547  		return nil
   548  	case thrift.MAP:
   549  		if from.Type() != thrift.MAP {
   550  			return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect type MAP, buf got type %s", from.Type()), nil)
   551  		}
   552  		if to.Elem() == from.Elem() && to.Key() == from.Key() {
   553  			goto skip_val
   554  		}
   555  		kt, et, size, err := read.ReadMapBegin()
   556  		if err != nil {
   557  			return wrapError(meta.ErrRead, "", err)
   558  		}
   559  		// if et != to.Elem().Type() || et != from.Elem().Type() {
   560  		// 	return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect elem type %s, buf got type %s", from.Elem().Type(), et), nil)
   561  		// }
   562  		// if kt != to.Key().Type() || kt != from.Key().Type() {
   563  		// 	return wrapError(meta.ErrDismatchType, fmt.Sprintf("expect key type %s, buf got type %s", from.Key().Type(), kt), nil)
   564  		// }
   565  		if err := write.WriteMapBegin(kt, et, size); err != nil {
   566  			return wrapError(meta.ErrWrite, "", err)
   567  		}
   568  		if size == 0 {
   569  			return nil
   570  		}
   571  		for i := 0; i < size; i++ {
   572  			if err := marshalTo(read, write, from.Key(), to.Key(), opts); err != nil {
   573  				return err
   574  			}
   575  			if err := marshalTo(read, write, from.Elem(), to.Elem(), opts); err != nil {
   576  				return err
   577  			}
   578  		}
   579  		return nil
   580  	}
   581  
   582  skip_val:
   583  	if to.Type() != from.Type() {
   584  		return meta.NewError(meta.ErrDismatchType, "to descriptor dismatches from descriptor", nil)
   585  	}
   586  	e := read.Read
   587  	if err := read.Skip(to.Type(), opts.UseNativeSkip); err != nil {
   588  		return wrapError(meta.ErrRead, "", err)
   589  	}
   590  	s := read.Read
   591  	write.Buf = append(write.Buf, read.Buf[e:s]...)
   592  	return nil
   593  }
   594  
   595  func handleUnsets(req thrift.RequiresBitmap, desc *thrift.StructDescriptor, p *thrift.BinaryProtocol, writeDefault bool) error {
   596  	return req.CheckRequires(desc, writeDefault, func(f *thrift.FieldDescriptor) error {
   597  		if e := p.WriteFieldBegin(f.Name(), f.Type().Type(), (f.ID())); e != nil {
   598  			return e
   599  		}
   600  		return p.WriteEmpty(f.Type())
   601  	})
   602  }