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

     1  package p2j
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/cloudwego/dynamicgo/http"
     8  	"github.com/cloudwego/dynamicgo/internal/json"
     9  	"github.com/cloudwego/dynamicgo/internal/rt"
    10  	"github.com/cloudwego/dynamicgo/meta"
    11  	"github.com/cloudwego/dynamicgo/proto"
    12  	"github.com/cloudwego/dynamicgo/proto/binary"
    13  	"google.golang.org/protobuf/reflect/protoreflect"
    14  )
    15  
    16  const (
    17  	_GUARD_SLICE_FACTOR = 2
    18  )
    19  
    20  func wrapError(code meta.ErrCode, msg string, err error) error {
    21  	return meta.NewError(code, msg, err)
    22  }
    23  
    24  //go:noinline
    25  func unwrapError(msg string, err error) error {
    26  	if v, ok := err.(meta.Error); ok {
    27  		return wrapError(v.Code, msg, err)
    28  	} else {
    29  		return wrapError(meta.ErrConvert, msg, err)
    30  	}
    31  }
    32  
    33  func (self *BinaryConv) do(ctx context.Context, src []byte, desc *proto.TypeDescriptor, out *[]byte, resp http.ResponseSetter) (err error) {
    34  	//NOTICE: output buffer must be larger than src buffer
    35  	rt.GuardSlice(out, len(src)*_GUARD_SLICE_FACTOR)
    36  
    37  	var p = binary.BinaryProtocol{
    38  		Buf: src,
    39  	}
    40  
    41  	// when desc is Singular/Map/List
    42  	if desc.Type() != proto.MESSAGE {
    43  		wtyp := proto.Kind2Wire[protoreflect.Kind(desc.Type())]
    44  		return self.doRecurse(ctx, desc, out, resp, &p, wtyp)
    45  	}
    46  
    47  	// when desc is Message
    48  	messageDesc := desc.Message()
    49  	comma := false
    50  
    51  	*out = json.EncodeObjectBegin(*out)
    52  
    53  	for p.Read < len(src) {
    54  		// Parse Tag to preprocess Descriptor does not have the field
    55  		fieldId, typeId, _, e := p.ConsumeTag()
    56  		if e != nil {
    57  			return wrapError(meta.ErrRead, "", e)
    58  		}
    59  
    60  		fd := messageDesc.ByNumber(fieldId)
    61  		if fd == nil {
    62  			if self.opts.DisallowUnknownField {
    63  				return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", fieldId), nil)
    64  			}
    65  			if e := p.Skip(typeId, self.opts.UseNativeSkip); e != nil {
    66  				return wrapError(meta.ErrRead, "", e)
    67  			}
    68  			continue
    69  		}
    70  
    71  		if comma {
    72  			*out = json.EncodeObjectComma(*out)
    73  		} else {
    74  			comma = true
    75  		}
    76  
    77  		// NOTICE: always use jsonName here, because jsonName always equals to name by default
    78  		*out = json.EncodeString(*out, fd.JSONName())
    79  		*out = json.EncodeObjectColon(*out)
    80  		// Parse ProtoData and encode into json format
    81  		err := self.doRecurse(ctx, fd.Type(), out, resp, &p, typeId)
    82  		if err != nil {
    83  			return unwrapError(fmt.Sprintf("converting field %s of MESSAGE %s failed", fd.Name(), fd.Kind()), err)
    84  		}
    85  	}
    86  
    87  	*out = json.EncodeObjectEnd(*out)
    88  	return err
    89  }
    90  
    91  // Parse ProtoData into JSONData by DescriptorType
    92  func (self *BinaryConv) doRecurse(ctx context.Context, fd *proto.TypeDescriptor, out *[]byte, resp http.ResponseSetter, p *binary.BinaryProtocol, typeId proto.WireType) error {
    93  	switch {
    94  	case (*fd).IsList():
    95  		return self.unmarshalList(ctx, resp, p, typeId, out, fd)
    96  	case (*fd).IsMap():
    97  		return self.unmarshalMap(ctx, resp, p, typeId, out, fd)
    98  	default:
    99  		return self.unmarshalSingular(ctx, resp, p, out, fd)
   100  	}
   101  }
   102  
   103  // parse Singular/MessageType
   104  // field tag is processed outside before doRecurse
   105  // Singular format:	[(L)V]
   106  // Message format: [Length][[Tag][(L)V] [Tag][(L)V]....]
   107  func (self *BinaryConv) unmarshalSingular(ctx context.Context, resp http.ResponseSetter, p *binary.BinaryProtocol, out *[]byte, fd *proto.TypeDescriptor) (err error) {
   108  	switch fd.Type() {
   109  	case proto.BOOL:
   110  		v, e := p.ReadBool()
   111  		if e != nil {
   112  			return wrapError(meta.ErrRead, "unmarshal Boolkind error", e)
   113  		}
   114  		*out = json.EncodeBool(*out, v)
   115  	case proto.ENUM:
   116  		v, e := p.ReadEnum()
   117  		if e != nil {
   118  			return wrapError(meta.ErrRead, "unmarshal Enumkind error", e)
   119  		}
   120  		*out = json.EncodeInt64(*out, int64(v))
   121  	case proto.INT32:
   122  		v, e := p.ReadInt32()
   123  		if e != nil {
   124  			return wrapError(meta.ErrRead, "unmarshal Int32kind error", e)
   125  		}
   126  		*out = json.EncodeInt64(*out, int64(v))
   127  	case proto.SINT32:
   128  		v, e := p.ReadSint32()
   129  		if e != nil {
   130  			return wrapError(meta.ErrRead, "unmarshal Sint32kind error", e)
   131  		}
   132  		*out = json.EncodeInt64(*out, int64(v))
   133  	case proto.UINT32:
   134  		v, e := p.ReadUint32()
   135  		if e != nil {
   136  			return wrapError(meta.ErrRead, "unmarshal Uint32kind error", e)
   137  		}
   138  		*out = json.EncodeInt64(*out, int64(v))
   139  	case proto.FIX32:
   140  		v, e := p.ReadFixed32()
   141  		if e != nil {
   142  			return wrapError(meta.ErrRead, "unmarshal Fixed32kind error", e)
   143  		}
   144  		*out = json.EncodeInt64(*out, int64(v))
   145  	case proto.SFIX32:
   146  		v, e := p.ReadSfixed32()
   147  		if e != nil {
   148  			return wrapError(meta.ErrRead, "unmarshal Sfixed32kind error", e)
   149  		}
   150  		*out = json.EncodeInt64(*out, int64(v))
   151  	case proto.INT64:
   152  		v, e := p.ReadInt64()
   153  		if e != nil {
   154  			return wrapError(meta.ErrRead, "unmarshal Int64kind error", e)
   155  		}
   156  		if self.opts.String2Int64 {
   157  			*out = append(*out, '"')
   158  			*out = json.EncodeInt64(*out, int64(v))
   159  			*out = append(*out, '"')
   160  		} else {
   161  			*out = json.EncodeInt64(*out, int64(v))
   162  		}
   163  	case proto.SINT64:
   164  		v, e := p.ReadInt64()
   165  		if e != nil {
   166  			return wrapError(meta.ErrRead, "unmarshal Sint64kind error", e)
   167  		}
   168  		*out = json.EncodeInt64(*out, int64(v))
   169  	case proto.UINT64:
   170  		v, e := p.ReadUint64()
   171  		if e != nil {
   172  			return wrapError(meta.ErrRead, "unmarshal Uint64kind error", e)
   173  		}
   174  		*out = json.EncodeInt64(*out, int64(v))
   175  	case proto.SFIX64:
   176  		v, e := p.ReadSfixed64()
   177  		if e != nil {
   178  			return wrapError(meta.ErrRead, "unmarshal Sfixed64kind error", e)
   179  		}
   180  		*out = json.EncodeInt64(*out, int64(v))
   181  	case proto.FLOAT:
   182  		v, e := p.ReadFloat()
   183  		if e != nil {
   184  			return wrapError(meta.ErrRead, "unmarshal Floatkind error", e)
   185  		}
   186  		*out = json.EncodeFloat64(*out, float64(v))
   187  	case proto.DOUBLE:
   188  		v, e := p.ReadDouble()
   189  		if e != nil {
   190  			return wrapError(meta.ErrRead, "unmarshal Doublekind error", e)
   191  		}
   192  		*out = json.EncodeFloat64(*out, float64(v))
   193  	case proto.STRING:
   194  		v, e := p.ReadString(false)
   195  		if e != nil {
   196  			return wrapError(meta.ErrRead, "unmarshal Stringkind error", e)
   197  		}
   198  		*out = json.EncodeString(*out, v)
   199  	case proto.BYTE:
   200  		v, e := p.ReadBytes()
   201  		if e != nil {
   202  			return wrapError(meta.ErrRead, "unmarshal Byteskind error", e)
   203  		}
   204  		*out = json.EncodeBaniry(*out, v)
   205  	case proto.MESSAGE:
   206  		l, e := p.ReadLength()
   207  		if e != nil {
   208  			return wrapError(meta.ErrRead, "unmarshal Byteskind error", e)
   209  		}
   210  		message := (*fd).Message()
   211  		comma := false
   212  		start := p.Read
   213  
   214  		*out = json.EncodeObjectBegin(*out)
   215  
   216  		for p.Read < start+l {
   217  			fieldId, typeId, _, e := p.ConsumeTag()
   218  			if e != nil {
   219  				return wrapError(meta.ErrRead, "", e)
   220  			}
   221  
   222  			fd := message.ByNumber(fieldId)
   223  			if fd == nil {
   224  				if self.opts.DisallowUnknownField {
   225  					return wrapError(meta.ErrUnknownField, fmt.Sprintf("unknown field %d", fieldId), nil)
   226  				}
   227  				if e := p.Skip(typeId, self.opts.UseNativeSkip); e != nil {
   228  					return wrapError(meta.ErrRead, "", e)
   229  				}
   230  				continue
   231  			}
   232  
   233  			if comma {
   234  				*out = json.EncodeObjectComma(*out)
   235  			} else {
   236  				comma = true
   237  			}
   238  
   239  			*out = json.EncodeString(*out, fd.JSONName())
   240  			*out = json.EncodeObjectColon(*out)
   241  
   242  			// parse MessageFieldValue recursive
   243  			err := self.doRecurse(ctx, fd.Type(), out, resp, p, typeId)
   244  			if err != nil {
   245  				return unwrapError(fmt.Sprintf("converting field %s of MESSAGE %s failed", fd.Name(), fd.Kind()), err)
   246  			}
   247  		}
   248  		*out = json.EncodeObjectEnd(*out)
   249  	default:
   250  		return wrapError(meta.ErrUnsupportedType, fmt.Sprintf("unknown descriptor type %s", fd.Type()), nil)
   251  	}
   252  	return
   253  }
   254  
   255  // parse ListType
   256  // Packed List format: [Tag][Length][Value Value Value Value Value]....
   257  // Unpacked List format: [Tag][Length][Value] [Tag][Length][Value]....
   258  func (self *BinaryConv) unmarshalList(ctx context.Context, resp http.ResponseSetter, p *binary.BinaryProtocol, typeId proto.WireType, out *[]byte, fd *proto.TypeDescriptor) (err error) {
   259  	*out = json.EncodeArrayBegin(*out)
   260  
   261  	fileldNumber := fd.BaseId()
   262  	// packedList(format):[Tag] [Length] [Value Value Value Value Value]
   263  	if typeId == proto.BytesType && (*fd).IsPacked() {
   264  		len, err := p.ReadLength()
   265  		if err != nil {
   266  			return wrapError(meta.ErrRead, "unmarshal List Length error", err)
   267  		}
   268  		start := p.Read
   269  		// parse Value repeated
   270  		for p.Read < start+len {
   271  			self.unmarshalSingular(ctx, resp, p, out, fd.Elem())
   272  			if p.Read != start && p.Read != start+len {
   273  				*out = json.EncodeArrayComma(*out)
   274  			}
   275  		}
   276  	} else {
   277  		// unpackedList(format):[Tag][Length][Value] [Tag][Length][Value]....
   278  		self.unmarshalSingular(ctx, resp, p, out, fd.Elem())
   279  		for p.Read < len(p.Buf) {
   280  			elementFieldNumber, _, tagLen, err := p.ConsumeTagWithoutMove()
   281  			if err != nil {
   282  				return wrapError(meta.ErrRead, "consume list child Tag error", err)
   283  			}
   284  			// List parse end, pay attention to remove the last ','
   285  			if elementFieldNumber != fileldNumber {
   286  				break
   287  			}
   288  			*out = json.EncodeArrayComma(*out)
   289  			p.Read += tagLen
   290  			self.unmarshalSingular(ctx, resp, p, out, fd.Elem())
   291  		}
   292  	}
   293  
   294  	*out = json.EncodeArrayEnd(*out)
   295  	return nil
   296  }
   297  
   298  // parse MapType
   299  // Map bytes format: [Pairtag][Pairlength][keyTag(L)V][valueTag(L)V] [Pairtag][Pairlength][T(L)V][T(L)V]...
   300  // Pairtag = MapFieldnumber << 3 | wiretype:BytesType
   301  func (self *BinaryConv) unmarshalMap(ctx context.Context, resp http.ResponseSetter, p *binary.BinaryProtocol, typeId proto.WireType, out *[]byte, fd *proto.TypeDescriptor) (err error) {
   302  	fileldNumber := (*fd).BaseId()
   303  	_, lengthErr := p.ReadLength()
   304  	if lengthErr != nil {
   305  		return wrapError(meta.ErrRead, "parse Tag length error", err)
   306  	}
   307  
   308  	*out = json.EncodeObjectBegin(*out)
   309  
   310  	// parse first k-v pair, [KeyTag][KeyLength][KeyValue][ValueTag][ValueLength][ValueValue]
   311  	_, _, _, keyErr := p.ConsumeTag()
   312  	if keyErr != nil {
   313  		return wrapError(meta.ErrRead, "parse MapKey Tag error", err)
   314  	}
   315  	mapKeyDesc := fd.Key()
   316  	isIntKey := (mapKeyDesc.Type() == proto.INT32) || (mapKeyDesc.Type() == proto.INT64) || (mapKeyDesc.Type() == proto.UINT32) || (mapKeyDesc.Type() == proto.UINT64)
   317  	if isIntKey {
   318  		*out = append(*out, '"')
   319  	}
   320  	if self.unmarshalSingular(ctx, resp, p, out, mapKeyDesc) != nil {
   321  		return wrapError(meta.ErrRead, "parse MapKey Value error", err)
   322  	}
   323  	if isIntKey {
   324  		*out = append(*out, '"')
   325  	}
   326  	*out = json.EncodeObjectColon(*out)
   327  	_, _, _, valueErr := p.ConsumeTag()
   328  	if valueErr != nil {
   329  		return wrapError(meta.ErrRead, "parse MapValue Tag error", err)
   330  	}
   331  	mapValueDesc := fd.Elem()
   332  	if self.unmarshalSingular(ctx, resp, p, out, mapValueDesc) != nil {
   333  		return wrapError(meta.ErrRead, "parse MapValue Value error", err)
   334  	}
   335  
   336  	// parse the remaining k-v pairs
   337  	for p.Read < len(p.Buf) {
   338  		pairNumber, _, tagLen, err := p.ConsumeTagWithoutMove()
   339  		if err != nil {
   340  			return wrapError(meta.ErrRead, "consume list child Tag error", err)
   341  		}
   342  		// parse second Tag
   343  		if pairNumber != fileldNumber {
   344  			break
   345  		}
   346  		p.Read += tagLen
   347  		*out = json.EncodeObjectComma(*out)
   348  		// parse second length
   349  		_, lengthErr := p.ReadLength()
   350  		if lengthErr != nil {
   351  			return wrapError(meta.ErrRead, "parse Tag length error", err)
   352  		}
   353  		// parse second [KeyTag][KeyLength][KeyValue][ValueTag][ValueLength][ValueValue]
   354  		_, _, _, keyErr = p.ConsumeTag()
   355  		if keyErr != nil {
   356  			return wrapError(meta.ErrRead, "parse MapKey Tag error", err)
   357  		}
   358  		if isIntKey {
   359  			*out = append(*out, '"')
   360  		}
   361  		if self.unmarshalSingular(ctx, resp, p, out, mapKeyDesc) != nil {
   362  			return wrapError(meta.ErrRead, "parse MapKey Value error", err)
   363  		}
   364  		if isIntKey {
   365  			*out = append(*out, '"')
   366  		}
   367  		*out = json.EncodeObjectColon(*out)
   368  		_, _, _, valueErr = p.ConsumeTag()
   369  		if valueErr != nil {
   370  			return wrapError(meta.ErrRead, "parse MapValue Tag error", err)
   371  		}
   372  		if self.unmarshalSingular(ctx, resp, p, out, mapValueDesc) != nil {
   373  			return wrapError(meta.ErrRead, "parse MapValue Value error", err)
   374  		}
   375  	}
   376  
   377  	*out = json.EncodeObjectEnd(*out)
   378  	return nil
   379  }