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 }