github.com/cloudwego/kitex@v0.9.0/pkg/generic/thrift/write.go (about) 1 /* 2 * Copyright 2021 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 thrift 18 19 import ( 20 "context" 21 "encoding/base64" 22 "encoding/json" 23 "fmt" 24 25 "github.com/apache/thrift/lib/go/thrift" 26 "github.com/tidwall/gjson" 27 28 "github.com/cloudwego/kitex/pkg/generic/descriptor" 29 "github.com/cloudwego/kitex/pkg/generic/proto" 30 "github.com/cloudwego/kitex/pkg/remote/codec/perrors" 31 ) 32 33 type writerOption struct { 34 requestBase *Base // request base from metahandler 35 // decoding Base64 to binary 36 binaryWithBase64 bool 37 } 38 39 type writer func(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error 40 41 type fieldGetter func(val interface{}, field *descriptor.FieldDescriptor) (interface{}, bool) 42 43 var mapGetter fieldGetter = func(val interface{}, field *descriptor.FieldDescriptor) (interface{}, bool) { 44 st := val.(map[string]interface{}) 45 ret, ok := st[field.FieldName()] 46 return ret, ok 47 } 48 49 var pbGetter fieldGetter = func(val interface{}, field *descriptor.FieldDescriptor) (interface{}, bool) { 50 st := val.(proto.Message) 51 ret, err := st.TryGetFieldByNumber(int(field.ID)) 52 return ret, err == nil 53 } 54 55 func typeOf(sample interface{}, t *descriptor.TypeDescriptor, opt *writerOption) (descriptor.Type, writer, error) { 56 tt := t.Type 57 switch v := sample.(type) { 58 case bool: 59 return descriptor.BOOL, writeBool, nil 60 case int8, byte: 61 return descriptor.I08, writeInt8, nil 62 case int16: 63 return descriptor.I16, writeInt16, nil 64 case int32: 65 var err error 66 // data from pb decode 67 switch tt { 68 case descriptor.I08: 69 if v&0xff != v { 70 err = fmt.Errorf("value is beyond range of i8: %v", v) 71 } 72 return tt, writeInt32AsInt8, err 73 case descriptor.I16: 74 if v&0xffff != v { 75 err = fmt.Errorf("value is beyond range of i16: %v", v) 76 } 77 return tt, writeInt32AsInt16, err 78 } 79 return descriptor.I32, writeInt32, nil 80 case int64: 81 return descriptor.I64, writeInt64, nil 82 case float64: 83 // maybe come from json decode 84 switch tt { 85 case descriptor.I08, descriptor.I16, descriptor.I32, descriptor.I64, descriptor.DOUBLE: 86 return tt, writeJSONFloat64, nil 87 } 88 case json.Number: 89 switch tt { 90 case descriptor.I08, descriptor.I16, descriptor.I32, descriptor.I64, descriptor.DOUBLE: 91 return tt, writeJSONNumber, nil 92 } 93 case string: 94 // maybe a base64 string encoded from binary 95 if t.Name == "binary" && opt.binaryWithBase64 { 96 return descriptor.STRING, writeBase64Binary, nil 97 } 98 // maybe a json number string 99 return descriptor.STRING, writeString, nil 100 case []byte: 101 if tt == descriptor.LIST { 102 return descriptor.LIST, writeBinaryList, nil 103 } 104 return descriptor.STRING, writeBinary, nil 105 case []interface{}: 106 return descriptor.LIST, writeList, nil 107 case map[interface{}]interface{}: 108 return descriptor.MAP, writeInterfaceMap, nil 109 case map[string]interface{}: 110 // 4: optional map<i64, ReqItem> req_items (api.body='req_items') 111 // need parse string into int64 112 switch tt { 113 case descriptor.STRUCT: 114 return descriptor.STRUCT, writeStruct, nil 115 case descriptor.MAP: 116 return descriptor.MAP, writeStringMap, nil 117 } 118 case proto.Message: 119 return descriptor.STRUCT, writeStruct, nil 120 case *descriptor.HTTPRequest: 121 return descriptor.STRUCT, writeHTTPRequest, nil 122 case *gjson.Result: 123 return descriptor.STRUCT, writeJSON, nil 124 case nil, descriptor.Void: // nil and Void 125 return descriptor.VOID, writeVoid, nil 126 } 127 return 0, nil, fmt.Errorf("unsupported type:%T, expected type:%s", sample, tt) 128 } 129 130 func typeJSONOf(data *gjson.Result, t *descriptor.TypeDescriptor, opt *writerOption) (v interface{}, w writer, err error) { 131 tt := t.Type 132 defer func() { 133 if r := recover(); r != nil { 134 err = perrors.NewProtocolErrorWithType(perrors.InvalidData, fmt.Sprintf("json convert error:%#+v", r)) 135 } 136 }() 137 switch tt { 138 case descriptor.BOOL: 139 v = data.Bool() 140 w = writeBool 141 return 142 case descriptor.I08: 143 v = int8(data.Int()) 144 w = writeInt8 145 return 146 case descriptor.I16: 147 v = int16(data.Int()) 148 w = writeInt16 149 return 150 case descriptor.I32: 151 v = int32(data.Int()) 152 w = writeInt32 153 return 154 case descriptor.I64: 155 v = data.Int() 156 w = writeInt64 157 return 158 case descriptor.DOUBLE: 159 v = data.Float() 160 w = writeJSONFloat64 161 return 162 case descriptor.STRING: 163 v = data.String() 164 if t.Name == "binary" && opt.binaryWithBase64 { 165 w = writeBase64Binary 166 } else { 167 w = writeString 168 } 169 return 170 // case descriptor.BINARY: 171 // return writeBinary, nil 172 case descriptor.SET, descriptor.LIST: 173 v = data.Array() 174 w = writeJSONList 175 return 176 case descriptor.MAP: 177 v = data.Map() 178 w = writeStringJSONMap 179 return 180 case descriptor.STRUCT: 181 v = data 182 w = writeJSON 183 return 184 case descriptor.VOID: // nil and Void 185 v = data 186 w = writeVoid 187 return 188 } 189 return 0, nil, fmt.Errorf("data:%#v, expected type:%s, err:%#v", data, tt, err) 190 } 191 192 func nextWriter(sample interface{}, t *descriptor.TypeDescriptor, opt *writerOption) (writer, error) { 193 tt, fn, err := typeOf(sample, t, opt) 194 if err != nil { 195 return nil, err 196 } 197 if t.Type == thrift.SET && tt == thrift.LIST { 198 tt = thrift.SET 199 } 200 return fn, assertType(t.Type, tt) 201 } 202 203 func nextJSONWriter(data *gjson.Result, t *descriptor.TypeDescriptor, opt *writerOption) (interface{}, writer, error) { 204 v, fn, err := typeJSONOf(data, t, opt) 205 if err != nil { 206 return nil, nil, err 207 } 208 return v, fn, nil 209 } 210 211 func writeEmptyValue(out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 212 switch t.Type { 213 case descriptor.BOOL: 214 return out.WriteBool(false) 215 case descriptor.I08: 216 return out.WriteByte(0) 217 case descriptor.I16: 218 return out.WriteI16(0) 219 case descriptor.I32: 220 return out.WriteI32(0) 221 case descriptor.I64: 222 return out.WriteI64(0) 223 case descriptor.DOUBLE: 224 return out.WriteDouble(0) 225 case descriptor.STRING: 226 if t.Name == "binary" && opt.binaryWithBase64 { 227 return out.WriteBinary([]byte{}) 228 } else { 229 return out.WriteString("") 230 } 231 case descriptor.LIST, descriptor.SET: 232 if err := out.WriteListBegin(t.Elem.Type.ToThriftTType(), 0); err != nil { 233 return err 234 } 235 return out.WriteListEnd() 236 case descriptor.MAP: 237 if err := out.WriteMapBegin(t.Key.Type.ToThriftTType(), t.Elem.Type.ToThriftTType(), 0); err != nil { 238 return err 239 } 240 return out.WriteMapEnd() 241 case descriptor.STRUCT: 242 if err := out.WriteStructBegin(t.Name); err != nil { 243 return err 244 } 245 if err := out.WriteFieldStop(); err != nil { 246 return err 247 } 248 return out.WriteStructEnd() 249 case descriptor.VOID: 250 return nil 251 } 252 return fmt.Errorf("unsupported type:%T", t) 253 } 254 255 func wrapStructWriter(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 256 if err := out.WriteStructBegin(t.Struct.Name); err != nil { 257 return err 258 } 259 for name, field := range t.Struct.FieldsByName { 260 if field.IsException { 261 // generic server ignore the exception, because no description for exception 262 // generic handler just return error 263 continue 264 } 265 if val != nil { 266 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 267 return err 268 } 269 writer, err := nextWriter(val, field.Type, opt) 270 if err != nil { 271 return fmt.Errorf("nextWriter of field[%s] error %w", name, err) 272 } 273 if err := writer(ctx, val, out, field.Type, opt); err != nil { 274 return fmt.Errorf("writer of field[%s] error %w", name, err) 275 } 276 if err := out.WriteFieldEnd(); err != nil { 277 return err 278 } 279 } 280 } 281 if err := out.WriteFieldStop(); err != nil { 282 return err 283 } 284 return out.WriteStructEnd() 285 } 286 287 func wrapJSONWriter(ctx context.Context, val *gjson.Result, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 288 if err := out.WriteStructBegin(t.Struct.Name); err != nil { 289 return err 290 } 291 for name, field := range t.Struct.FieldsByName { 292 if field.IsException { 293 // generic server ignore the exception, because no description for exception 294 // generic handler just return error 295 continue 296 } 297 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 298 return err 299 } 300 v, writer, err := nextJSONWriter(val, field.Type, opt) 301 if err != nil { 302 return fmt.Errorf("nextJSONWriter of field[%s] error %w", name, err) 303 } 304 if err := writer(ctx, v, out, field.Type, opt); err != nil { 305 return fmt.Errorf("writer of field[%s] error %w", name, err) 306 } 307 if err := out.WriteFieldEnd(); err != nil { 308 return err 309 } 310 } 311 if err := out.WriteFieldStop(); err != nil { 312 return err 313 } 314 return out.WriteStructEnd() 315 } 316 317 func writeVoid(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 318 return writeStruct(ctx, map[string]interface{}{}, out, t, opt) 319 } 320 321 func writeBool(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 322 return out.WriteBool(val.(bool)) 323 } 324 325 func writeInt8(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 326 switch val := val.(type) { 327 case int8: 328 return out.WriteByte(val) 329 case uint8: 330 return out.WriteByte(int8(val)) 331 default: 332 return fmt.Errorf("unsupported type: %T", val) 333 } 334 } 335 336 func writeJSONNumber(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 337 jn := val.(json.Number) 338 switch t.Type { 339 case thrift.I08: 340 i, err := jn.Int64() 341 if err != nil { 342 return err 343 } 344 return writeInt8(ctx, int8(i), out, t, opt) 345 case thrift.I16: 346 i, err := jn.Int64() 347 if err != nil { 348 return err 349 } 350 return writeInt16(ctx, int16(i), out, t, opt) 351 case thrift.I32: 352 i, err := jn.Int64() 353 if err != nil { 354 return err 355 } 356 return writeInt32(ctx, int32(i), out, t, opt) 357 case thrift.I64: 358 i, err := jn.Int64() 359 if err != nil { 360 return err 361 } 362 return writeInt64(ctx, i, out, t, opt) 363 case thrift.DOUBLE: 364 i, err := jn.Float64() 365 if err != nil { 366 return err 367 } 368 return writeFloat64(ctx, i, out, t, opt) 369 } 370 return nil 371 } 372 373 func writeJSONFloat64(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 374 i := val.(float64) 375 switch t.Type { 376 case thrift.I08: 377 return writeInt8(ctx, int8(i), out, t, opt) 378 case thrift.I16: 379 return writeInt16(ctx, int16(i), out, t, opt) 380 case thrift.I32: 381 return writeInt32(ctx, int32(i), out, t, opt) 382 case thrift.I64: 383 return writeInt64(ctx, int64(i), out, t, opt) 384 case thrift.DOUBLE: 385 return writeFloat64(ctx, i, out, t, opt) 386 } 387 return fmt.Errorf("need number type, but got: %s", t.Type) 388 } 389 390 func writeInt16(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 391 return out.WriteI16(val.(int16)) 392 } 393 394 func writeInt32(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 395 return out.WriteI32(val.(int32)) 396 } 397 398 func writeInt32AsInt8(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 399 return out.WriteByte(int8(val.(int32))) 400 } 401 402 func writeInt32AsInt16(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 403 return out.WriteI16(int16(val.(int32))) 404 } 405 406 func writeInt64(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 407 return out.WriteI64(val.(int64)) 408 } 409 410 func writeFloat64(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 411 return out.WriteDouble(val.(float64)) 412 } 413 414 func writeString(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 415 return out.WriteString(val.(string)) 416 } 417 418 func writeBase64Binary(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 419 bytes, err := base64.StdEncoding.DecodeString(val.(string)) 420 if err != nil { 421 return err 422 } 423 return out.WriteBinary(bytes) 424 } 425 426 func writeBinary(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 427 return out.WriteBinary(val.([]byte)) 428 } 429 430 func writeBinaryList(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 431 l := val.([]byte) 432 length := len(l) 433 if err := out.WriteListBegin(t.Elem.Type.ToThriftTType(), length); err != nil { 434 return err 435 } 436 for _, b := range l { 437 if err := out.WriteByte(int8(b)); err != nil { 438 return err 439 } 440 } 441 return out.WriteListEnd() 442 } 443 444 func writeList(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 445 l := val.([]interface{}) 446 length := len(l) 447 if err := out.WriteListBegin(t.Elem.Type.ToThriftTType(), length); err != nil { 448 return err 449 } 450 if length == 0 { 451 return out.WriteListEnd() 452 } 453 var ( 454 writer writer 455 err error 456 ) 457 for _, elem := range l { 458 if elem == nil { 459 if err = writeEmptyValue(out, t.Elem, opt); err != nil { 460 return err 461 } 462 } else { 463 if writer == nil { 464 if writer, err = nextWriter(elem, t.Elem, opt); err != nil { 465 return err 466 } 467 } 468 if err := writer(ctx, elem, out, t.Elem, opt); err != nil { 469 return err 470 } 471 } 472 } 473 return out.WriteListEnd() 474 } 475 476 func writeJSONList(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 477 l := val.([]gjson.Result) 478 length := len(l) 479 if err := out.WriteListBegin(t.Elem.Type.ToThriftTType(), length); err != nil { 480 return err 481 } 482 if length == 0 { 483 return out.WriteListEnd() 484 } 485 for _, elem := range l { 486 v, writer, err := nextJSONWriter(&elem, t.Elem, opt) 487 if err != nil { 488 return err 489 } 490 if err := writer(ctx, v, out, t.Elem, opt); err != nil { 491 return err 492 } 493 } 494 return out.WriteListEnd() 495 } 496 497 func writeInterfaceMap(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 498 m := val.(map[interface{}]interface{}) 499 length := len(m) 500 if err := out.WriteMapBegin(t.Key.Type.ToThriftTType(), t.Elem.Type.ToThriftTType(), length); err != nil { 501 return err 502 } 503 if length == 0 { 504 return out.WriteMapEnd() 505 } 506 var ( 507 keyWriter writer 508 elemWriter writer 509 err error 510 ) 511 for key, elem := range m { 512 if keyWriter == nil { 513 if keyWriter, err = nextWriter(key, t.Key, opt); err != nil { 514 return err 515 } 516 } 517 if err := keyWriter(ctx, key, out, t.Key, opt); err != nil { 518 return err 519 } 520 if elem == nil { 521 if err = writeEmptyValue(out, t.Elem, opt); err != nil { 522 return err 523 } 524 } else { 525 if elemWriter == nil { 526 if elemWriter, err = nextWriter(elem, t.Elem, opt); err != nil { 527 return err 528 } 529 } 530 if err := elemWriter(ctx, elem, out, t.Elem, opt); err != nil { 531 return err 532 } 533 } 534 } 535 return out.WriteMapEnd() 536 } 537 538 func writeStringMap(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 539 m := val.(map[string]interface{}) 540 length := len(m) 541 if err := out.WriteMapBegin(t.Key.Type.ToThriftTType(), t.Elem.Type.ToThriftTType(), length); err != nil { 542 return err 543 } 544 if length == 0 { 545 return out.WriteMapEnd() 546 } 547 548 var ( 549 keyWriter writer 550 elemWriter writer 551 ) 552 for key, elem := range m { 553 _key, err := buildinTypeFromString(key, t.Key) 554 if err != nil { 555 return err 556 } 557 if keyWriter == nil { 558 if keyWriter, err = nextWriter(_key, t.Key, opt); err != nil { 559 return err 560 } 561 } 562 if err := keyWriter(ctx, _key, out, t.Key, opt); err != nil { 563 return err 564 } 565 if elem == nil { 566 if err = writeEmptyValue(out, t.Elem, opt); err != nil { 567 return err 568 } 569 } else { 570 if elemWriter == nil { 571 if elemWriter, err = nextWriter(elem, t.Elem, opt); err != nil { 572 return err 573 } 574 } 575 if err := elemWriter(ctx, elem, out, t.Elem, opt); err != nil { 576 return err 577 } 578 } 579 } 580 return out.WriteMapEnd() 581 } 582 583 func writeStringJSONMap(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 584 m := val.(map[string]gjson.Result) 585 length := len(m) 586 if err := out.WriteMapBegin(t.Key.Type.ToThriftTType(), t.Elem.Type.ToThriftTType(), length); err != nil { 587 return err 588 } 589 if length == 0 { 590 return out.WriteMapEnd() 591 } 592 593 var ( 594 keyWriter writer 595 elemWriter writer 596 v interface{} 597 ) 598 for key, elem := range m { 599 _key, err := buildinTypeFromString(key, t.Key) 600 if err != nil { 601 return err 602 } 603 if keyWriter == nil { 604 if keyWriter, err = nextWriter(_key, t.Key, opt); err != nil { 605 return err 606 } 607 } 608 if v, elemWriter, err = nextJSONWriter(&elem, t.Elem, opt); err != nil { 609 return err 610 } 611 if err := keyWriter(ctx, _key, out, t.Key, opt); err != nil { 612 return err 613 } 614 615 if err := elemWriter(ctx, v, out, t.Elem, opt); err != nil { 616 return err 617 } 618 } 619 return out.WriteMapEnd() 620 } 621 622 func writeRequestBase(ctx context.Context, val interface{}, out thrift.TProtocol, field *descriptor.FieldDescriptor, opt *writerOption) error { 623 if st, ok := val.(map[string]interface{}); ok { 624 // copy from user's Extra 625 if ext, ok := st["Extra"]; ok { 626 switch v := ext.(type) { 627 case map[string]interface{}: 628 // from http json 629 for key, value := range v { 630 if _, ok := opt.requestBase.Extra[key]; !ok { 631 if vStr, ok := value.(string); ok { 632 if opt.requestBase.Extra == nil { 633 opt.requestBase.Extra = map[string]string{} 634 } 635 opt.requestBase.Extra[key] = vStr 636 } 637 } 638 } 639 case map[interface{}]interface{}: 640 // from struct map 641 for key, value := range v { 642 if kStr, ok := key.(string); ok { 643 if _, ok := opt.requestBase.Extra[kStr]; !ok { 644 if vStr, ok := value.(string); ok { 645 if opt.requestBase.Extra == nil { 646 opt.requestBase.Extra = map[string]string{} 647 } 648 opt.requestBase.Extra[kStr] = vStr 649 } 650 } 651 } 652 } 653 } 654 } 655 } 656 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 657 return err 658 } 659 if err := opt.requestBase.Write(out); err != nil { 660 return err 661 } 662 return out.WriteFieldEnd() 663 } 664 665 // writeStruct iter with Descriptor, can check the field's required and others 666 func writeStruct(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 667 var fg fieldGetter 668 switch val.(type) { 669 case map[string]interface{}: 670 fg = mapGetter 671 case proto.Message: 672 fg = pbGetter 673 } 674 675 err := out.WriteStructBegin(t.Struct.Name) 676 if err != nil { 677 return err 678 } 679 for name, field := range t.Struct.FieldsByName { 680 elem, ok := fg(val, field) 681 if field.Type.IsRequestBase && opt.requestBase != nil { 682 if err := writeRequestBase(ctx, elem, out, field, opt); err != nil { 683 return err 684 } 685 continue 686 } 687 688 // empty fields 689 if elem == nil || !ok { 690 if !field.Optional { 691 // empty fields don't need value-mapping here, since writeEmptyValue decides zero value based on Thrift type 692 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 693 return err 694 } 695 if err := writeEmptyValue(out, field.Type, opt); err != nil { 696 return fmt.Errorf("field (%d/%s) error: %w", field.ID, name, err) 697 } 698 if err := out.WriteFieldEnd(); err != nil { 699 return err 700 } 701 } 702 } else { // normal fields 703 if field.ValueMapping != nil { 704 elem, err = field.ValueMapping.Request(ctx, elem, field) 705 if err != nil { 706 return err 707 } 708 } 709 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 710 return err 711 } 712 writer, err := nextWriter(elem, field.Type, opt) 713 if err != nil { 714 return fmt.Errorf("nextWriter of field[%s] error %w", name, err) 715 } 716 if err := writer(ctx, elem, out, field.Type, opt); err != nil { 717 return fmt.Errorf("writer of field[%s] error %w", name, err) 718 } 719 if err := out.WriteFieldEnd(); err != nil { 720 return err 721 } 722 } 723 } 724 725 if err := out.WriteFieldStop(); err != nil { 726 return err 727 } 728 return out.WriteStructEnd() 729 } 730 731 func writeHTTPRequest(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 732 req := val.(*descriptor.HTTPRequest) 733 defer func() { 734 if req.Params != nil { 735 req.Params.Recycle() 736 } 737 }() 738 if err := out.WriteStructBegin(t.Struct.Name); err != nil { 739 return err 740 } 741 for name, field := range t.Struct.FieldsByName { 742 v, err := requestMappingValue(ctx, req, field) 743 if err != nil { 744 return err 745 } 746 if field.Type.IsRequestBase && opt.requestBase != nil { 747 if err := writeRequestBase(ctx, v, out, field, opt); err != nil { 748 return err 749 } 750 continue 751 } 752 753 if v == nil { 754 if !field.Optional { 755 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 756 return err 757 } 758 if err := writeEmptyValue(out, field.Type, opt); err != nil { 759 return fmt.Errorf("field (%d/%s) error: %w", field.ID, name, err) 760 } 761 if err := out.WriteFieldEnd(); err != nil { 762 return err 763 } 764 } 765 } else { 766 if field.ValueMapping != nil { 767 v, err = field.ValueMapping.Request(ctx, v, field) 768 if err != nil { 769 return err 770 } 771 } 772 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 773 return err 774 } 775 writer, err := nextWriter(v, field.Type, opt) 776 if err != nil { 777 return fmt.Errorf("nextWriter of field[%s] error %w", name, err) 778 } 779 if err := writer(ctx, v, out, field.Type, opt); err != nil { 780 return fmt.Errorf("writer of field[%s] error %w", name, err) 781 } 782 if err := out.WriteFieldEnd(); err != nil { 783 return err 784 } 785 } 786 } 787 788 if err := out.WriteFieldStop(); err != nil { 789 return err 790 } 791 return out.WriteStructEnd() 792 } 793 794 func writeJSON(ctx context.Context, val interface{}, out thrift.TProtocol, t *descriptor.TypeDescriptor, opt *writerOption) error { 795 data := val.(*gjson.Result) 796 err := out.WriteStructBegin(t.Struct.Name) 797 if err != nil { 798 return err 799 } 800 for name, field := range t.Struct.FieldsByName { 801 elem := data.Get(name) 802 if field.Type.IsRequestBase && opt.requestBase != nil { 803 elemI := elem.Value() 804 if err := writeRequestBase(ctx, elemI, out, field, opt); err != nil { 805 return err 806 } 807 continue 808 } 809 810 if elem.Type == gjson.Null { 811 if !field.Optional { 812 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 813 return err 814 } 815 if err := writeEmptyValue(out, field.Type, opt); err != nil { 816 return fmt.Errorf("field (%d/%s) error: %w", field.ID, name, err) 817 } 818 if err := out.WriteFieldEnd(); err != nil { 819 return err 820 } 821 } 822 } else { 823 v, writer, err := nextJSONWriter(&elem, field.Type, opt) 824 if err != nil { 825 return fmt.Errorf("nextWriter of field[%s] error %w", name, err) 826 } 827 if err := out.WriteFieldBegin(field.Name, field.Type.Type.ToThriftTType(), int16(field.ID)); err != nil { 828 return err 829 } 830 if err := writer(ctx, v, out, field.Type, opt); err != nil { 831 return fmt.Errorf("writer of field[%s] error %w", name, err) 832 } 833 if err := out.WriteFieldEnd(); err != nil { 834 return err 835 } 836 } 837 } 838 839 if err := out.WriteFieldStop(); err != nil { 840 return err 841 } 842 return out.WriteStructEnd() 843 }