github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/conv/j2p/decode.go (about)

     1  package j2p
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"sync"
     8  	"unsafe"
     9  
    10  	"github.com/bytedance/sonic/ast"
    11  	"github.com/cloudwego/dynamicgo/conv"
    12  	"github.com/cloudwego/dynamicgo/internal/rt"
    13  	"github.com/cloudwego/dynamicgo/meta"
    14  	"github.com/cloudwego/dynamicgo/proto"
    15  	"github.com/cloudwego/dynamicgo/proto/binary"
    16  )
    17  
    18  // memory resize factor
    19  const (
    20  	defaultStkDepth       = 256
    21  	nilStkType      uint8 = 0
    22  	objStkType      uint8 = 1
    23  	arrStkType      uint8 = 2
    24  	mapStkType      uint8 = 3
    25  )
    26  
    27  const (
    28  	mapkeyFieldNumber   = 1
    29  	mapValueFieldNumber = 2
    30  )
    31  
    32  var (
    33  	vuPool = sync.Pool{
    34  		New: func() interface{} {
    35  			return &visitorUserNode{
    36  				sp:  0,
    37  				stk: make([]visitorUserNodeStack, defaultStkDepth),
    38  			}
    39  		},
    40  	}
    41  )
    42  
    43  func decodeBinary(val string) ([]byte, error) {
    44  	return decodeBase64(val)
    45  }
    46  
    47  // NewvisitorUserNode gets a new visitorUserNode from sync.Pool
    48  // and reuse the buffer in pool
    49  func newVisitorUserNodeBuffer() *visitorUserNode {
    50  	vu := vuPool.Get().(*visitorUserNode)
    51  	for i := 0; i < len(vu.stk); i++ {
    52  		vu.stk[i].state.lenPos = -1
    53  	}
    54  	return vu
    55  }
    56  
    57  // FreevisitorUserNode resets the buffer and puts the visitorUserNode back to sync.Pool
    58  func freeVisitorUserNodePool(vu *visitorUserNode) {
    59  	vu.reset()
    60  	vuPool.Put(vu)
    61  }
    62  
    63  // recycle put the visitorUserNode back to sync.Pool
    64  func (self *visitorUserNode) recycle() {
    65  	self.reset()
    66  	vuPool.Put(self)
    67  }
    68  
    69  // reset resets the buffer and read position
    70  func (self *visitorUserNode) reset() {
    71  	self.sp = 0
    72  	self.p = nil
    73  	for i := 0; i < len(self.stk); i++ {
    74  		self.stk[i].reset()
    75  	}
    76  	self.globalFieldDesc = nil
    77  	self.opts = nil
    78  }
    79  
    80  // visitorUserNode is used to store some conditional variables about Protobuf when parsing json
    81  // Stk: Record MessageDescriptor and PrefixLen when parsing MessageType; Record FieldDescriptor and PairPrefixLen and MapKeyDescriptor when parsing MapType; Record FieldDescriptor and PrefixListLen when parsing List
    82  // Sp: using to Record the level of current stack(stk)
    83  // P: Output of Protobuf BinaryData
    84  // GlobalFieldDesc:After parsing the FieldKey, save the FieldDescriptor
    85  type visitorUserNode struct {
    86  	sp              uint8
    87  	stk             []visitorUserNodeStack
    88  	p               *binary.BinaryProtocol
    89  	globalFieldDesc *proto.FieldDescriptor
    90  	opts *conv.Options
    91  }
    92  
    93  // keep hierarchy when parsing, objStkType represents Message and arrStkType represents List and mapStkType represents Map
    94  type visitorUserNodeStack struct {
    95  	typ   uint8
    96  	state visitorUserNodeState
    97  }
    98  
    99  func (stk *visitorUserNodeStack) reset() {
   100  	stk.typ = nilStkType
   101  	stk.state.lenPos = -1
   102  	stk.state.msgDesc = nil
   103  	stk.state.fieldDesc = nil
   104  }
   105  
   106  // push FieldDescriptor、position of prefixLen into stack
   107  func (self *visitorUserNode) push(isMap bool, isObj bool, isList bool, desc *proto.FieldDescriptor, pos int) error {
   108  	err := self.incrSP()
   109  	t := nilStkType
   110  	if isMap {
   111  		t = mapStkType
   112  	} else if isObj {
   113  		t = objStkType
   114  	} else if isList {
   115  		t = arrStkType
   116  	}
   117  
   118  	self.stk[self.sp] = visitorUserNodeStack{typ: t, state: visitorUserNodeState{
   119  		msgDesc:   nil,
   120  		fieldDesc: desc,
   121  		lenPos:    pos,
   122  	}}
   123  	return err
   124  }
   125  
   126  // After parsing MessageType/MapType/ListType, pop stack
   127  func (self *visitorUserNode) pop() {
   128  	self.stk[self.sp].reset()
   129  	self.sp--
   130  }
   131  
   132  // combine of Descriptor and position of prefixLength
   133  type visitorUserNodeState struct {
   134  	msgDesc   *proto.MessageDescriptor
   135  	fieldDesc *proto.FieldDescriptor
   136  	lenPos    int
   137  }
   138  
   139  func (self *visitorUserNode) decode(bytes []byte, desc *proto.TypeDescriptor) ([]byte, error) {
   140  	// init initial visitorUserNodeState, may be MessageDescriptor or FieldDescriptor
   141  	switch desc.Type() {
   142  	case proto.MESSAGE:
   143  		convDesc := desc.Message()
   144  		self.stk[self.sp].state = visitorUserNodeState{msgDesc: convDesc, fieldDesc: nil, lenPos: -1}
   145  		self.stk[self.sp].typ = objStkType
   146  	}
   147  	str := rt.Mem2Str(bytes)
   148  	if err := ast.Preorder(str, self, nil); err != nil {
   149  		return nil, err
   150  	}
   151  	return self.result()
   152  }
   153  
   154  func (self *visitorUserNode) result() ([]byte, error) {
   155  	if self.sp != 0 {
   156  		return nil, fmt.Errorf("incorrect sp: %d", self.sp)
   157  	}
   158  	return self.p.RawBuf(), nil
   159  }
   160  
   161  func (self *visitorUserNode) incrSP() error {
   162  	self.sp++
   163  	if self.sp == 0 {
   164  		return fmt.Errorf("reached max depth: %d", len(self.stk))
   165  	}
   166  	return nil
   167  }
   168  
   169  func (self *visitorUserNode) OnNull() error {
   170  	// self.stk[self.sp].val = &visitorUserNull{}
   171  	if err := self.incrSP(); err != nil {
   172  		return err
   173  	}
   174  	return self.onValueEnd()
   175  }
   176  
   177  func (self *visitorUserNode) OnBool(v bool) error {
   178  	var err error
   179  	if self.globalFieldDesc == nil {
   180  		return newError(meta.ErrConvert, "self.globalFieldDescriptor is nil, type Onbool", nil)
   181  	}
   182  	// TODO
   183  	if err = self.p.AppendTagByKind(self.globalFieldDesc.Number(), self.globalFieldDesc.Kind()); err != nil {
   184  		return err
   185  	}
   186  	if err = self.p.WriteBool(v); err != nil {
   187  		return err
   188  	}
   189  	return self.onValueEnd()
   190  }
   191  
   192  // Parse stringType/bytesType
   193  func (self *visitorUserNode) OnString(v string) error {
   194  	var err error
   195  	top := self.stk[self.sp].state.fieldDesc
   196  	fieldDesc := self.globalFieldDesc
   197  	if fieldDesc == nil && top != nil && top.Type().IsList() {
   198  		fieldDesc = top
   199  	}
   200  
   201  	if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   202  		return err
   203  	}
   204  	// convert string、bytesType
   205  	switch fieldDesc.Kind() {
   206  	case proto.BytesKind:
   207  		// JSON format string data needs to be decoded via Base64x
   208  		bytesData, err := decodeBinary(v)
   209  		if err != nil {
   210  			return err
   211  		}
   212  		if err = self.p.WriteBytes(bytesData); err != nil {
   213  			return err
   214  		}
   215  	case proto.StringKind:
   216  		if err = self.p.WriteString(v); err != nil {
   217  			return err
   218  		}
   219  	default:
   220  		return newError(meta.ErrDismatchType, "param isn't stringType", nil)
   221  	}
   222  	if self.globalFieldDesc != nil {
   223  		return self.onValueEnd()
   224  	}
   225  	return err
   226  }
   227  
   228  func (self *visitorUserNode) OnInt64(v int64, n json.Number) error {
   229  	var err error
   230  	top := self.stk[self.sp]
   231  	fieldDesc := self.globalFieldDesc
   232  	// case PackedList(List<int32/int64/...), get fieldDescriptor from Stack
   233  	if self.globalFieldDesc == nil && top.typ == arrStkType {
   234  		fieldDesc = top.state.fieldDesc
   235  	}
   236  
   237  	// packed list no need to write tag
   238  	if !fieldDesc.Type().IsList() {
   239  		if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   240  			return err
   241  		}
   242  	}
   243  
   244  	switch fieldDesc.Kind() {
   245  	case proto.Int32Kind, proto.Sint32Kind, proto.Sfixed32Kind, proto.Fixed32Kind:
   246  		convertData := *(*int32)(unsafe.Pointer(&v))
   247  
   248  		if err = self.p.WriteInt32(convertData); err != nil {
   249  			return err
   250  		}
   251  	case proto.Uint32Kind:
   252  		convertData := *(*uint32)(unsafe.Pointer(&v))
   253  		if err = self.p.WriteUint32(convertData); err != nil {
   254  			return err
   255  		}
   256  	case proto.Uint64Kind:
   257  		convertData := *(*uint64)(unsafe.Pointer(&v))
   258  		if err = self.p.WriteUint64(convertData); err != nil {
   259  			return err
   260  		}
   261  	case proto.Int64Kind:
   262  		if err = self.p.WriteInt64(v); err != nil {
   263  			return err
   264  		}
   265  	case proto.FloatKind:
   266  		if err = self.p.WriteFloat(float32(v)); err != nil {
   267  			return err
   268  		}
   269  	case proto.DoubleKind:
   270  		if err = self.p.WriteDouble(float64(v)); err != nil {
   271  			return err
   272  		}
   273  
   274  	default:
   275  		return newError(meta.ErrDismatchType, "param isn't intType", nil)
   276  	}
   277  	// globalFieldDesc must belong to MessageDescriptor
   278  	if self.globalFieldDesc != nil {
   279  		err = self.onValueEnd()
   280  	}
   281  	return err
   282  }
   283  
   284  func (self *visitorUserNode) OnFloat64(v float64, n json.Number) error {
   285  	var err error
   286  	top := self.stk[self.sp]
   287  	fieldDesc := self.globalFieldDesc
   288  
   289  	if self.globalFieldDesc == nil && top.typ == arrStkType {
   290  		fieldDesc = top.state.fieldDesc
   291  	}
   292  	switch fieldDesc.Kind() {
   293  	case proto.FloatKind:
   294  		convertData := *(*float32)(unsafe.Pointer(&v))
   295  		if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   296  			return err
   297  		}
   298  		if err = self.p.WriteFloat(convertData); err != nil {
   299  			return err
   300  		}
   301  	case proto.DoubleKind:
   302  		convertData := *(*float64)(unsafe.Pointer(&v))
   303  		if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   304  			return err
   305  		}
   306  		if err = self.p.WriteDouble(convertData); err != nil {
   307  			return err
   308  		}
   309  	case proto.Int32Kind:
   310  		convertData := int32(v)
   311  		if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   312  			return err
   313  		}
   314  		if err = self.p.WriteInt32(convertData); err != nil {
   315  			return err
   316  		}
   317  	case proto.Int64Kind:
   318  		convertData := int64(v)
   319  		if err = self.p.AppendTagByKind(fieldDesc.Number(), fieldDesc.Kind()); err != nil {
   320  			return err
   321  		}
   322  		if err = self.p.WriteInt64(convertData); err != nil {
   323  			return err
   324  		}
   325  	default:
   326  		return newError(meta.ErrDismatchType, "param isn't floatType", nil)
   327  	}
   328  	if self.globalFieldDesc != nil {
   329  		err = self.onValueEnd()
   330  	}
   331  	return err
   332  }
   333  
   334  // Start Parsing JSONObject, which may correspond to Protobuf Map or Protobuf Message
   335  //  1. Get fieldDescriptor from globalFieldDesc first, corresponding to Message/Map embedded in a Message
   336  //  2. Then get fieldDesc from the top of stack, corresponding to Message embedded in List
   337  //  3. When Field is Message type, encode Tag and PrefixLen, and push FieldDescriptor and PrefixLen to the stack.
   338  //     When Field is Map type, only perform pressing stack operation.
   339  func (self *visitorUserNode) OnObjectBegin(capacity int) error {
   340  	var err error
   341  	fieldDesc := self.globalFieldDesc
   342  	top := self.stk[self.sp]
   343  	curNodeLenPos := -1
   344  
   345  	// case List<Message>, get fieldDescriptor
   346  	if self.globalFieldDesc == nil && top.typ == arrStkType {
   347  		fieldDesc = top.state.fieldDesc
   348  	}
   349  
   350  	if fieldDesc != nil {
   351  		if fieldDesc.Type().IsMap() {
   352  			// case Map, push MapDesc
   353  			if err = self.push(true, false, false, fieldDesc, curNodeLenPos); err != nil {
   354  				return err
   355  			}
   356  		} else {
   357  			// case Message, encode Tag、PrefixLen, push MessageDesc、PrefixLen
   358  			if err = self.p.AppendTag(fieldDesc.Number(), proto.BytesType); err != nil {
   359  				return meta.NewError(meta.ErrWrite, "append prefix tag failed", nil)
   360  			}
   361  			self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf)
   362  			if err = self.push(false, true, false, fieldDesc, curNodeLenPos); err != nil {
   363  				return err
   364  			}
   365  		}
   366  	}
   367  	return err
   368  }
   369  
   370  // MapKey maybe int32/sint32/uint32/uint64 etc....
   371  func (self *visitorUserNode) encodeMapKey(key string, t proto.Type) error {
   372  	switch t {
   373  	case proto.INT32, proto.SINT32, proto.SFIX32, proto.FIX32:
   374  		t, _ := strconv.ParseInt(key, 10, 32)
   375  		if err := self.p.WriteInt32(int32(t)); err != nil {
   376  			return err
   377  		}
   378  	case proto.UINT32:
   379  		t, _ := strconv.ParseInt(key, 10, 32)
   380  		if err := self.p.WriteUint32(uint32(t)); err != nil {
   381  			return err
   382  		}
   383  	case proto.UINT64:
   384  		t, _ := strconv.ParseInt(key, 10, 64)
   385  		if err := self.p.WriteUint64(uint64(t)); err != nil {
   386  			return err
   387  		}
   388  	case proto.INT64:
   389  		t, _ := strconv.ParseInt(key, 10, 64)
   390  		if err := self.p.WriteInt64(int64(t)); err != nil {
   391  			return err
   392  		}
   393  	case proto.BOOL:
   394  		t, _ := strconv.ParseBool(key)
   395  		if err := self.p.WriteBool(t); err != nil {
   396  			return err
   397  		}
   398  	case proto.STRING:
   399  		if err := self.p.WriteString(key); err != nil {
   400  			return err
   401  		}
   402  	default:
   403  		return newError(meta.ErrDismatchType, "invalid mapKeyDescriptor Type", nil)
   404  	}
   405  
   406  	return nil
   407  }
   408  
   409  // Start Parsing JSONField, which may correspond to Protobuf MessageField or Protobuf MapKey
   410  //  1. The initial layer obtains the MessageFieldDescriptor, saves it to globalFieldDesc and exits;
   411  //  2. The inner layer performs different operations depending on the top-of-stack descriptor type
   412  //     2.1 The top of the stack is MessageType, which exits after saving globalFieldDesc;
   413  //     2.2 The top of the stack is MapType, write PairTag, PairLen, MapKey, MapKeyLen, and MapKeyData; save MapDesc、PairPrefixLen into stack; save MapValueDescriptor into globalFieldDesc;
   414  //     2.3 The top of the stack is ListType, which exits after saving globalFieldDesc;
   415  func (self *visitorUserNode) OnObjectKey(key string) error {
   416  	var err error
   417  	var top *visitorUserNodeStack
   418  	var curDesc proto.FieldDescriptor
   419  	curNodeLenPos := -1
   420  
   421  	// get stack top, and recognize currentDescriptor type
   422  	top = &self.stk[self.sp]
   423  	if top.state.msgDesc != nil {
   424  		// first hierarchy
   425  		rootDesc := top.state.msgDesc
   426  		fd := rootDesc.ByJSONName(key)
   427  		if fd == nil {
   428  			if !self.opts.DisallowUnknownField {
   429  				return newError(meta.ErrUnknownField, fmt.Sprintf("json key '%s' is unknown", key), err)
   430  			} else {
   431  				// todo
   432  				return nil
   433  			}
   434  		}
   435  		curDesc = *fd
   436  	} else {
   437  		fieldDesc := top.state.fieldDesc
   438  		// case MessageField
   439  		if top.typ == objStkType {
   440  			fd := fieldDesc.Message().ByJSONName(key)
   441  			if fd == nil {
   442  				if !self.opts.DisallowUnknownField {
   443  					return newError(meta.ErrUnknownField, fmt.Sprintf("json key '%s' is unknown", key), err)
   444  				} else {
   445  					// todo
   446  					return nil
   447  				}
   448  			}
   449  			curDesc = *fd
   450  		} else if top.typ == mapStkType {
   451  			// case MapKey, write PairTag、PairLen、MapKeyTag、MapKeyLen、MapKeyData, push MapDesc into stack
   452  
   453  			// encode PairTag、PairLen
   454  			fd := top.state.fieldDesc;
   455  			if err := self.p.AppendTag(fd.Number(), proto.BytesType); err != nil {
   456  				return newError(meta.ErrWrite, fmt.Sprintf("field '%s' encode pair tag faield", fd.Name()), err)
   457  			}
   458  			self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf)
   459  
   460  			// encode MapKeyTag、MapKeyLen、MapKeyData
   461  			mapKeyDesc := fieldDesc.MapKey()
   462  			if err := self.p.AppendTag(mapkeyFieldNumber, mapKeyDesc.WireType()); err != nil {
   463  				return newError(meta.ErrUnsupportedType, fmt.Sprintf("field '%s' encode map key tag faield", fd.Name()), err)
   464  			}
   465  
   466  			if err := self.encodeMapKey(key, mapKeyDesc.Type()); err != nil {
   467  				return newError(meta.ErrUnsupportedType, fmt.Sprintf("field '%s' encode map key faield", fd.Name()), err)
   468  			}
   469  
   470  			// push MapDesc into stack
   471  			if err = self.push(true, false, false, top.state.fieldDesc, curNodeLenPos); err != nil {
   472  				return err
   473  			}
   474  			// save MapValueDesc into globalFieldDesc
   475  			curDesc = *fieldDesc.Message().ByNumber(mapValueFieldNumber)
   476  		} else if top.typ == arrStkType {
   477  			// case List<Message>
   478  			curDesc = *top.state.fieldDesc
   479  		}
   480  	}
   481  	self.globalFieldDesc = &curDesc
   482  	return err
   483  }
   484  
   485  // After parsing JSONObject, write back prefixLen of Message
   486  func (self *visitorUserNode) OnObjectEnd() error {
   487  	top := &self.stk[self.sp]
   488  	// root layer no need to write tag and len
   489  	if top.state.lenPos != -1 {
   490  		self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos)
   491  	}
   492  	return self.onValueEnd()
   493  }
   494  
   495  // Start Parsing JSONArray, which may correspond to ProtoBuf PackedList、UnPackedList
   496  // 1. If PackedList, Encode ListTag、PrefixLen
   497  // 2. push ListDescriptor、PrefixLen(UnPackedList is -1) into stack
   498  func (self *visitorUserNode) OnArrayBegin(capacity int) error {
   499  	var err error
   500  	curNodeLenPos := -1
   501  	if self.globalFieldDesc != nil {
   502  		// PackedList: encode Tag、Len
   503  		if self.globalFieldDesc.Type().IsPacked() {
   504  			if err = self.p.AppendTag(self.globalFieldDesc.Number(), proto.BytesType); err != nil {
   505  				return meta.NewError(meta.ErrWrite, "append prefix tag failed", nil)
   506  			}
   507  			self.p.Buf, curNodeLenPos = binary.AppendSpeculativeLength(self.p.Buf)
   508  		}
   509  		if err = self.push(false, false, true, self.globalFieldDesc, curNodeLenPos); err != nil {
   510  			return err
   511  		}
   512  	}
   513  	return err
   514  }
   515  
   516  // After Parsing JSONArray, writing back PrefixLen If PackedList
   517  func (self *visitorUserNode) OnArrayEnd() error {
   518  	var top *visitorUserNodeStack
   519  	top = &self.stk[self.sp]
   520  	// case PackedList
   521  	if (top.state.lenPos != -1) && top.state.fieldDesc.Type().IsPacked() {
   522  		self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos)
   523  	}
   524  	return self.onValueEnd()
   525  }
   526  
   527  // After parsing one JSON field, maybe basicType(string/int/float/bool/bytes) or complexType(message/map/list)
   528  // 1. When type is basicType, note that the format of Map<basicType, basicType>, needs to write back PariPrefixLen of the current pair;
   529  // 2. When type is MessageType, current Message may belong to Map<any, Message> or Message{Message}, note that Map<int, Message>, needs to write back PairPrefixLen of current pair;
   530  // 3. When type is MapType/ListType, only execute pop operation;
   531  func (self *visitorUserNode) onValueEnd() error {
   532  	if self.sp == 0 && self.globalFieldDesc == nil {
   533  		return nil
   534  	}
   535  	top := self.stk[self.sp]
   536  
   537  	// basic Type
   538  	if self.globalFieldDesc != nil {
   539  		self.globalFieldDesc = nil
   540  		// basic Type belong to MapValue
   541  		// rewrite pairlen in one kv-item of map
   542  		if top.typ == mapStkType {
   543  			self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, top.state.lenPos)
   544  			self.pop()
   545  		}
   546  		return nil
   547  	}
   548  
   549  	// complexType Type
   550  	if top.typ == objStkType {
   551  		self.pop()
   552  		// Message belong to Map<int, Message>、Message{Message}
   553  		ntop := self.stk[self.sp]
   554  		if ntop.typ == mapStkType {
   555  			self.p.Buf = binary.FinishSpeculativeLength(self.p.Buf, ntop.state.lenPos)
   556  			self.pop()
   557  		}
   558  	} else if top.typ == arrStkType {
   559  		self.pop()
   560  	} else if top.typ == mapStkType {
   561  		self.pop()
   562  	} else {
   563  		return newError(meta.ErrWrite, "disMatched ValueEnd", nil)
   564  	}
   565  	return nil
   566  }