From 04b3c60a717742e58db6e627ed1dd11c4c6b0496 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 17:42:25 +0800 Subject: [PATCH 01/20] chore: move to internal --- {pkg => internal}/generic/thrift/base.go | 0 {pkg => internal}/generic/thrift/parse.go | 0 {pkg => internal}/generic/thrift/parse_test.go | 0 pkg/generic/json_test/generic_test.go | 2 +- pkg/generic/thriftidl_provider.go | 2 +- pkg/generic/thriftidl_provider_test.go | 2 +- 6 files changed, 3 insertions(+), 3 deletions(-) rename {pkg => internal}/generic/thrift/base.go (100%) rename {pkg => internal}/generic/thrift/parse.go (100%) rename {pkg => internal}/generic/thrift/parse_test.go (100%) diff --git a/pkg/generic/thrift/base.go b/internal/generic/thrift/base.go similarity index 100% rename from pkg/generic/thrift/base.go rename to internal/generic/thrift/base.go diff --git a/pkg/generic/thrift/parse.go b/internal/generic/thrift/parse.go similarity index 100% rename from pkg/generic/thrift/parse.go rename to internal/generic/thrift/parse.go diff --git a/pkg/generic/thrift/parse_test.go b/internal/generic/thrift/parse_test.go similarity index 100% rename from pkg/generic/thrift/parse_test.go rename to internal/generic/thrift/parse_test.go diff --git a/pkg/generic/json_test/generic_test.go b/pkg/generic/json_test/generic_test.go index a439592b91..8443fd9536 100644 --- a/pkg/generic/json_test/generic_test.go +++ b/pkg/generic/json_test/generic_test.go @@ -33,11 +33,11 @@ import ( "github.com/cloudwego/kitex/client/callopt" "github.com/cloudwego/kitex/client/genericclient" + "github.com/cloudwego/kitex/internal/generic/thrift" kt "github.com/cloudwego/kitex/internal/mocks/thrift" "github.com/cloudwego/kitex/internal/test" "github.com/cloudwego/kitex/pkg/generic" "github.com/cloudwego/kitex/pkg/generic/descriptor" - "github.com/cloudwego/kitex/pkg/generic/thrift" "github.com/cloudwego/kitex/server" "github.com/cloudwego/kitex/transport" ) diff --git a/pkg/generic/thriftidl_provider.go b/pkg/generic/thriftidl_provider.go index b43d54eb41..ffa77f9946 100644 --- a/pkg/generic/thriftidl_provider.go +++ b/pkg/generic/thriftidl_provider.go @@ -26,8 +26,8 @@ import ( dthrift "github.com/cloudwego/dynamicgo/thrift" "github.com/cloudwego/thriftgo/parser" + "github.com/cloudwego/kitex/internal/generic/thrift" "github.com/cloudwego/kitex/pkg/generic/descriptor" - "github.com/cloudwego/kitex/pkg/generic/thrift" "github.com/cloudwego/kitex/pkg/klog" ) diff --git a/pkg/generic/thriftidl_provider_test.go b/pkg/generic/thriftidl_provider_test.go index c14074241f..f29d478bd4 100644 --- a/pkg/generic/thriftidl_provider_test.go +++ b/pkg/generic/thriftidl_provider_test.go @@ -22,8 +22,8 @@ import ( dthrift "github.com/cloudwego/dynamicgo/thrift" + "github.com/cloudwego/kitex/internal/generic/thrift" "github.com/cloudwego/kitex/internal/test" - "github.com/cloudwego/kitex/pkg/generic/thrift" ) func TestAbsPath(t *testing.T) { From 91a9bcdb9c18be8301e35fadece30cff6427a10b Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 17:52:38 +0800 Subject: [PATCH 02/20] chore: move generic proto to internal --- internal/generic/thrift/http_pb.go | 1 + internal/generic/thrift/read.go | 1 + internal/generic/thrift/read_test.go | 1 + internal/generic/thrift/write.go | 1 + internal/generic/thrift/write_test.go | 1 + 5 files changed, 5 insertions(+) diff --git a/internal/generic/thrift/http_pb.go b/internal/generic/thrift/http_pb.go index 8e3e4c221c..f2174d920d 100644 --- a/internal/generic/thrift/http_pb.go +++ b/internal/generic/thrift/http_pb.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "github.com/cloudwego/kitex/internal/generic/proto" "io" "github.com/cloudwego/gopkg/protocol/thrift" diff --git a/internal/generic/thrift/read.go b/internal/generic/thrift/read.go index 4b4bb3378c..6952551e55 100644 --- a/internal/generic/thrift/read.go +++ b/internal/generic/thrift/read.go @@ -20,6 +20,7 @@ import ( "context" "encoding/base64" "fmt" + "github.com/cloudwego/kitex/internal/generic/proto" "reflect" "github.com/cloudwego/gopkg/protocol/thrift" diff --git a/internal/generic/thrift/read_test.go b/internal/generic/thrift/read_test.go index 2a77e120ee..a8b7e25fe9 100644 --- a/internal/generic/thrift/read_test.go +++ b/internal/generic/thrift/read_test.go @@ -20,6 +20,7 @@ import ( "context" "encoding/base64" "fmt" + "github.com/cloudwego/kitex/internal/generic/proto" "reflect" "testing" diff --git a/internal/generic/thrift/write.go b/internal/generic/thrift/write.go index bb2c27a9aa..344e49217d 100644 --- a/internal/generic/thrift/write.go +++ b/internal/generic/thrift/write.go @@ -21,6 +21,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "github.com/cloudwego/kitex/internal/generic/proto" "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" diff --git a/internal/generic/thrift/write_test.go b/internal/generic/thrift/write_test.go index 9545fe66c5..56633d8829 100644 --- a/internal/generic/thrift/write_test.go +++ b/internal/generic/thrift/write_test.go @@ -20,6 +20,7 @@ import ( "context" "encoding/base64" "encoding/json" + "github.com/cloudwego/kitex/internal/generic/proto" "testing" "github.com/cloudwego/gopkg/protocol/thrift" From f64bfe61b532db28cbaaaf326a5e13567f270815 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 18:13:34 +0800 Subject: [PATCH 03/20] fix: import --- internal/generic/thrift/http_pb.go | 1 - internal/generic/thrift/read.go | 1 - internal/generic/thrift/read_test.go | 1 - 3 files changed, 3 deletions(-) diff --git a/internal/generic/thrift/http_pb.go b/internal/generic/thrift/http_pb.go index f2174d920d..8e3e4c221c 100644 --- a/internal/generic/thrift/http_pb.go +++ b/internal/generic/thrift/http_pb.go @@ -20,7 +20,6 @@ import ( "context" "errors" "fmt" - "github.com/cloudwego/kitex/internal/generic/proto" "io" "github.com/cloudwego/gopkg/protocol/thrift" diff --git a/internal/generic/thrift/read.go b/internal/generic/thrift/read.go index 6952551e55..4b4bb3378c 100644 --- a/internal/generic/thrift/read.go +++ b/internal/generic/thrift/read.go @@ -20,7 +20,6 @@ import ( "context" "encoding/base64" "fmt" - "github.com/cloudwego/kitex/internal/generic/proto" "reflect" "github.com/cloudwego/gopkg/protocol/thrift" diff --git a/internal/generic/thrift/read_test.go b/internal/generic/thrift/read_test.go index a8b7e25fe9..2a77e120ee 100644 --- a/internal/generic/thrift/read_test.go +++ b/internal/generic/thrift/read_test.go @@ -20,7 +20,6 @@ import ( "context" "encoding/base64" "fmt" - "github.com/cloudwego/kitex/internal/generic/proto" "reflect" "testing" From 0453290a9629074755242eb48d5677d7d419170c Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 22:40:34 +0800 Subject: [PATCH 04/20] fix: import --- internal/generic/thrift/write.go | 1 - internal/generic/thrift/write_test.go | 1 - 2 files changed, 2 deletions(-) diff --git a/internal/generic/thrift/write.go b/internal/generic/thrift/write.go index 344e49217d..bb2c27a9aa 100644 --- a/internal/generic/thrift/write.go +++ b/internal/generic/thrift/write.go @@ -21,7 +21,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/cloudwego/kitex/internal/generic/proto" "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" diff --git a/internal/generic/thrift/write_test.go b/internal/generic/thrift/write_test.go index 56633d8829..9545fe66c5 100644 --- a/internal/generic/thrift/write_test.go +++ b/internal/generic/thrift/write_test.go @@ -20,7 +20,6 @@ import ( "context" "encoding/base64" "encoding/json" - "github.com/cloudwego/kitex/internal/generic/proto" "testing" "github.com/cloudwego/gopkg/protocol/thrift" From 4bb397160cc4879a79dca9915238ffa4bf50f2f7 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Tue, 30 Jul 2024 15:37:38 +0800 Subject: [PATCH 05/20] refactor: replace base with gopkg base --- pkg/generic/json_test/generic_test.go | 2 +- {internal => pkg}/generic/thrift/parse.go | 0 {internal => pkg}/generic/thrift/parse_test.go | 0 pkg/generic/thriftidl_provider.go | 2 +- pkg/generic/thriftidl_provider_test.go | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename {internal => pkg}/generic/thrift/parse.go (100%) rename {internal => pkg}/generic/thrift/parse_test.go (100%) diff --git a/pkg/generic/json_test/generic_test.go b/pkg/generic/json_test/generic_test.go index 8443fd9536..91e935992b 100644 --- a/pkg/generic/json_test/generic_test.go +++ b/pkg/generic/json_test/generic_test.go @@ -21,6 +21,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "github.com/cloudwego/kitex/pkg/generic/thrift" "math" "net" "reflect" @@ -33,7 +34,6 @@ import ( "github.com/cloudwego/kitex/client/callopt" "github.com/cloudwego/kitex/client/genericclient" - "github.com/cloudwego/kitex/internal/generic/thrift" kt "github.com/cloudwego/kitex/internal/mocks/thrift" "github.com/cloudwego/kitex/internal/test" "github.com/cloudwego/kitex/pkg/generic" diff --git a/internal/generic/thrift/parse.go b/pkg/generic/thrift/parse.go similarity index 100% rename from internal/generic/thrift/parse.go rename to pkg/generic/thrift/parse.go diff --git a/internal/generic/thrift/parse_test.go b/pkg/generic/thrift/parse_test.go similarity index 100% rename from internal/generic/thrift/parse_test.go rename to pkg/generic/thrift/parse_test.go diff --git a/pkg/generic/thriftidl_provider.go b/pkg/generic/thriftidl_provider.go index ffa77f9946..1a0568699c 100644 --- a/pkg/generic/thriftidl_provider.go +++ b/pkg/generic/thriftidl_provider.go @@ -19,6 +19,7 @@ package generic import ( "context" "fmt" + "github.com/cloudwego/kitex/pkg/generic/thrift" "path/filepath" "sync" @@ -26,7 +27,6 @@ import ( dthrift "github.com/cloudwego/dynamicgo/thrift" "github.com/cloudwego/thriftgo/parser" - "github.com/cloudwego/kitex/internal/generic/thrift" "github.com/cloudwego/kitex/pkg/generic/descriptor" "github.com/cloudwego/kitex/pkg/klog" ) diff --git a/pkg/generic/thriftidl_provider_test.go b/pkg/generic/thriftidl_provider_test.go index f29d478bd4..e10ca1c668 100644 --- a/pkg/generic/thriftidl_provider_test.go +++ b/pkg/generic/thriftidl_provider_test.go @@ -17,12 +17,12 @@ package generic import ( + "github.com/cloudwego/kitex/pkg/generic/thrift" "strings" "testing" dthrift "github.com/cloudwego/dynamicgo/thrift" - "github.com/cloudwego/kitex/internal/generic/thrift" "github.com/cloudwego/kitex/internal/test" ) From e82491fa519040f877d46bd32af1c2b8693eb4c7 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Tue, 30 Jul 2024 15:43:29 +0800 Subject: [PATCH 06/20] fix: import --- pkg/generic/json_test/generic_test.go | 2 +- pkg/generic/thriftidl_provider.go | 2 +- pkg/generic/thriftidl_provider_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/generic/json_test/generic_test.go b/pkg/generic/json_test/generic_test.go index 91e935992b..a439592b91 100644 --- a/pkg/generic/json_test/generic_test.go +++ b/pkg/generic/json_test/generic_test.go @@ -21,7 +21,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/cloudwego/kitex/pkg/generic/thrift" "math" "net" "reflect" @@ -38,6 +37,7 @@ import ( "github.com/cloudwego/kitex/internal/test" "github.com/cloudwego/kitex/pkg/generic" "github.com/cloudwego/kitex/pkg/generic/descriptor" + "github.com/cloudwego/kitex/pkg/generic/thrift" "github.com/cloudwego/kitex/server" "github.com/cloudwego/kitex/transport" ) diff --git a/pkg/generic/thriftidl_provider.go b/pkg/generic/thriftidl_provider.go index 1a0568699c..b43d54eb41 100644 --- a/pkg/generic/thriftidl_provider.go +++ b/pkg/generic/thriftidl_provider.go @@ -19,7 +19,6 @@ package generic import ( "context" "fmt" - "github.com/cloudwego/kitex/pkg/generic/thrift" "path/filepath" "sync" @@ -28,6 +27,7 @@ import ( "github.com/cloudwego/thriftgo/parser" "github.com/cloudwego/kitex/pkg/generic/descriptor" + "github.com/cloudwego/kitex/pkg/generic/thrift" "github.com/cloudwego/kitex/pkg/klog" ) diff --git a/pkg/generic/thriftidl_provider_test.go b/pkg/generic/thriftidl_provider_test.go index e10ca1c668..c14074241f 100644 --- a/pkg/generic/thriftidl_provider_test.go +++ b/pkg/generic/thriftidl_provider_test.go @@ -17,13 +17,13 @@ package generic import ( - "github.com/cloudwego/kitex/pkg/generic/thrift" "strings" "testing" dthrift "github.com/cloudwego/dynamicgo/thrift" "github.com/cloudwego/kitex/internal/test" + "github.com/cloudwego/kitex/pkg/generic/thrift" ) func TestAbsPath(t *testing.T) { From 8b17951c4fdc9c88c9a21175182df0d90c1e2fae Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Thu, 25 Jul 2024 09:58:19 +0800 Subject: [PATCH 07/20] refactor: remove apache tprotocol from generic --- pkg/generic/thrift/base.go | 695 +++++++++++++++++++++++++++++++++++++ 1 file changed, 695 insertions(+) create mode 100644 pkg/generic/thrift/base.go diff --git a/pkg/generic/thrift/base.go b/pkg/generic/thrift/base.go new file mode 100644 index 0000000000..07fd7ac002 --- /dev/null +++ b/pkg/generic/thrift/base.go @@ -0,0 +1,695 @@ +/* + * Copyright 2021 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package thrift + +import ( + "fmt" + + "github.com/cloudwego/gopkg/protocol/thrift" + + "github.com/cloudwego/kitex/pkg/protocol/bthrift" +) + +type TrafficEnv struct { + Open bool `thrift:"Open,1" json:"Open"` + + Env string `thrift:"Env,2" json:"Env"` +} + +func NewTrafficEnv() *TrafficEnv { + return &TrafficEnv{ + Open: false, + Env: "", + } +} + +func (p *TrafficEnv) GetOpen() bool { + return p.Open +} + +func (p *TrafficEnv) GetEnv() string { + return p.Env +} + +func (p *TrafficEnv) SetOpen(val bool) { + p.Open = val +} + +func (p *TrafficEnv) SetEnv(val string) { + p.Env = val +} + +var fieldIDToName_TrafficEnv = map[int16]string{ + 1: "Open", + 2: "Env", +} + +func (p *TrafficEnv) Read(iprot *thrift.BinaryReader) (err error) { + var fieldTypeId thrift.TType + var fieldId int16 + + for { + fieldTypeId, fieldId, err = iprot.ReadFieldBegin() + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + + switch fieldId { + case 1: + if fieldTypeId == thrift.BOOL { + if err = p.ReadField1(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 2: + if fieldTypeId == thrift.STRING { + if err = p.ReadField2(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + default: + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + } + + return nil +ReadFieldBeginError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TrafficEnv[fieldId]), err) +SkipFieldError: + return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +} + +func (p *TrafficEnv) ReadField1(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadBool(); err != nil { + return err + } else { + p.Open = v + } + return nil +} + +func (p *TrafficEnv) ReadField2(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.Env = v + } + return nil +} + +func (p *TrafficEnv) Write(oprot *thrift.BinaryWriter) (err error) { + if p != nil { + p.writeField1(oprot) + p.writeField2(oprot) + } + oprot.WriteFieldStop() + return nil +} + +func (p *TrafficEnv) writeField1(oprot *thrift.BinaryWriter) { + oprot.WriteFieldBegin(thrift.BOOL, 1) + oprot.WriteBool(p.Open) +} + +func (p *TrafficEnv) writeField2(oprot *thrift.BinaryWriter) { + oprot.WriteFieldBegin(thrift.STRING, 2) + oprot.WriteString(p.Env) +} + +func (p *TrafficEnv) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TrafficEnv(%+v)", *p) +} + +type Base struct { + LogID string `thrift:"LogID,1" json:"LogID"` + + Caller string `thrift:"Caller,2" json:"Caller"` + + Addr string `thrift:"Addr,3" json:"Addr"` + + Client string `thrift:"Client,4" json:"Client"` + + TrafficEnv *TrafficEnv `thrift:"TrafficEnv,5" json:"TrafficEnv,omitempty"` + + Extra map[string]string `thrift:"Extra,6" json:"Extra,omitempty"` +} + +func NewBase() *Base { + return &Base{ + LogID: "", + Caller: "", + Addr: "", + Client: "", + } +} + +func (p *Base) GetLogID() string { + return p.LogID +} + +func (p *Base) GetCaller() string { + return p.Caller +} + +func (p *Base) GetAddr() string { + return p.Addr +} + +func (p *Base) GetClient() string { + return p.Client +} + +var Base_TrafficEnv_DEFAULT *TrafficEnv + +func (p *Base) GetTrafficEnv() *TrafficEnv { + if !p.IsSetTrafficEnv() { + return Base_TrafficEnv_DEFAULT + } + return p.TrafficEnv +} + +var Base_Extra_DEFAULT map[string]string + +func (p *Base) GetExtra() map[string]string { + if !p.IsSetExtra() { + return Base_Extra_DEFAULT + } + return p.Extra +} + +func (p *Base) SetLogID(val string) { + p.LogID = val +} + +func (p *Base) SetCaller(val string) { + p.Caller = val +} + +func (p *Base) SetAddr(val string) { + p.Addr = val +} + +func (p *Base) SetClient(val string) { + p.Client = val +} + +func (p *Base) SetTrafficEnv(val *TrafficEnv) { + p.TrafficEnv = val +} + +func (p *Base) SetExtra(val map[string]string) { + p.Extra = val +} + +var fieldIDToName_Base = map[int16]string{ + 1: "LogID", + 2: "Caller", + 3: "Addr", + 4: "Client", + 5: "TrafficEnv", + 6: "Extra", +} + +func (p *Base) IsSetTrafficEnv() bool { + return p.TrafficEnv != nil +} + +func (p *Base) IsSetExtra() bool { + return p.Extra != nil +} + +func (p *Base) Read(iprot *thrift.BinaryReader) (err error) { + var fieldTypeId thrift.TType + var fieldId int16 + + for { + fieldTypeId, fieldId, err = iprot.ReadFieldBegin() + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + + switch fieldId { + case 1: + if fieldTypeId == thrift.STRING { + if err = p.ReadField1(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 2: + if fieldTypeId == thrift.STRING { + if err = p.ReadField2(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 3: + if fieldTypeId == thrift.STRING { + if err = p.ReadField3(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 4: + if fieldTypeId == thrift.STRING { + if err = p.ReadField4(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 5: + if fieldTypeId == thrift.STRUCT { + if err = p.ReadField5(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 6: + if fieldTypeId == thrift.MAP { + if err = p.ReadField6(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + default: + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + } + + return nil +ReadFieldBeginError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Base[fieldId]), err) +SkipFieldError: + return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +} + +func (p *Base) ReadField1(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.LogID = v + } + return nil +} + +func (p *Base) ReadField2(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.Caller = v + } + return nil +} + +func (p *Base) ReadField3(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.Addr = v + } + return nil +} + +func (p *Base) ReadField4(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.Client = v + } + return nil +} + +func (p *Base) ReadField5(iprot *thrift.BinaryReader) error { + p.TrafficEnv = NewTrafficEnv() + if err := p.TrafficEnv.Read(iprot); err != nil { + return err + } + return nil +} + +func (p *Base) ReadField6(iprot *thrift.BinaryReader) error { + _, _, size, err := iprot.ReadMapBegin() + if err != nil { + return err + } + p.Extra = make(map[string]string, size) + for i := 0; i < size; i++ { + var _key string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _key = v + } + + var _val string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _val = v + } + + p.Extra[_key] = _val + } + return nil +} + +func (p *Base) Write(oprot *thrift.BinaryWriter) (err error) { + var fieldId int16 + if p != nil { + if err = p.writeField1(oprot); err != nil { + fieldId = 1 + goto WriteFieldError + } + if err = p.writeField2(oprot); err != nil { + fieldId = 2 + goto WriteFieldError + } + if err = p.writeField3(oprot); err != nil { + fieldId = 3 + goto WriteFieldError + } + if err = p.writeField4(oprot); err != nil { + fieldId = 4 + goto WriteFieldError + } + if err = p.writeField5(oprot); err != nil { + fieldId = 5 + goto WriteFieldError + } + if err = p.writeField6(oprot); err != nil { + fieldId = 6 + goto WriteFieldError + } + + } + oprot.WriteFieldStop() + return nil +WriteFieldError: + return bthrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err) +} + +func (p *Base) writeField1(oprot *thrift.BinaryWriter) (err error) { + oprot.WriteFieldBegin(thrift.STRING, 1) + oprot.WriteString(p.LogID) + return nil +} + +func (p *Base) writeField2(oprot *thrift.BinaryWriter) (err error) { + oprot.WriteFieldBegin(thrift.STRING, 2) + oprot.WriteString(p.Caller) + return nil +} + +func (p *Base) writeField3(oprot *thrift.BinaryWriter) (err error) { + oprot.WriteFieldBegin(thrift.STRING, 3) + oprot.WriteString(p.Addr) + return nil +} + +func (p *Base) writeField4(oprot *thrift.BinaryWriter) (err error) { + oprot.WriteFieldBegin(thrift.STRING, 4) + oprot.WriteString(p.Client) + return nil +} + +func (p *Base) writeField5(oprot *thrift.BinaryWriter) (err error) { + if p.IsSetTrafficEnv() { + oprot.WriteFieldBegin(thrift.STRUCT, 5) + if err = p.TrafficEnv.Write(oprot); err != nil { + return err + } + } + return nil +} + +func (p *Base) writeField6(oprot *thrift.BinaryWriter) (err error) { + if p.IsSetExtra() { + oprot.WriteFieldBegin(thrift.MAP, 6) + oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)) + for k, v := range p.Extra { + oprot.WriteString(k) + oprot.WriteString(v) + } + } + return nil +} + +func (p *Base) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Base(%+v)", *p) +} + +type BaseResp struct { + StatusMessage string `thrift:"StatusMessage,1" json:"StatusMessage"` + + StatusCode int32 `thrift:"StatusCode,2" json:"StatusCode"` + + Extra map[string]string `thrift:"Extra,3" json:"Extra,omitempty"` +} + +func NewBaseResp() *BaseResp { + return &BaseResp{ + StatusMessage: "", + StatusCode: 0, + } +} + +func (p *BaseResp) GetStatusMessage() string { + return p.StatusMessage +} + +func (p *BaseResp) GetStatusCode() int32 { + return p.StatusCode +} + +var BaseResp_Extra_DEFAULT map[string]string + +func (p *BaseResp) GetExtra() map[string]string { + if !p.IsSetExtra() { + return BaseResp_Extra_DEFAULT + } + return p.Extra +} + +func (p *BaseResp) SetStatusMessage(val string) { + p.StatusMessage = val +} + +func (p *BaseResp) SetStatusCode(val int32) { + p.StatusCode = val +} + +func (p *BaseResp) SetExtra(val map[string]string) { + p.Extra = val +} + +var fieldIDToName_BaseResp = map[int16]string{ + 1: "StatusMessage", + 2: "StatusCode", + 3: "Extra", +} + +func (p *BaseResp) IsSetExtra() bool { + return p.Extra != nil +} + +func (p *BaseResp) Read(iprot *thrift.BinaryReader) (err error) { + var fieldTypeId thrift.TType + var fieldId int16 + + for { + fieldTypeId, fieldId, err = iprot.ReadFieldBegin() + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + + switch fieldId { + case 1: + if fieldTypeId == thrift.STRING { + if err = p.ReadField1(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 2: + if fieldTypeId == thrift.I32 { + if err = p.ReadField2(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + case 3: + if fieldTypeId == thrift.MAP { + if err = p.ReadField3(iprot); err != nil { + goto ReadFieldError + } + } else { + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + default: + if err = iprot.Skip(fieldTypeId); err != nil { + goto SkipFieldError + } + } + } + + return nil +ReadFieldBeginError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_BaseResp[fieldId]), err) +SkipFieldError: + return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +} + +func (p *BaseResp) ReadField1(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadString(); err != nil { + return err + } else { + p.StatusMessage = v + } + return nil +} + +func (p *BaseResp) ReadField2(iprot *thrift.BinaryReader) error { + if v, err := iprot.ReadI32(); err != nil { + return err + } else { + p.StatusCode = v + } + return nil +} + +func (p *BaseResp) ReadField3(iprot *thrift.BinaryReader) error { + _, _, size, err := iprot.ReadMapBegin() + if err != nil { + return err + } + p.Extra = make(map[string]string, size) + for i := 0; i < size; i++ { + var _key string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _key = v + } + + var _val string + if v, err := iprot.ReadString(); err != nil { + return err + } else { + _val = v + } + + p.Extra[_key] = _val + } + return nil +} + +func (p *BaseResp) Write(oprot *thrift.BinaryWriter) (err error) { + if p != nil { + p.writeField1(oprot) + p.writeField2(oprot) + p.writeField3(oprot) + } + oprot.WriteFieldStop() + return nil +} + +func (p *BaseResp) writeField1(oprot *thrift.BinaryWriter) { + oprot.WriteFieldBegin(thrift.STRING, 1) + oprot.WriteString(p.StatusMessage) +} + +func (p *BaseResp) writeField2(oprot *thrift.BinaryWriter) { + oprot.WriteFieldBegin(thrift.I32, 2) + oprot.WriteI32(p.StatusCode) +} + +func (p *BaseResp) writeField3(oprot *thrift.BinaryWriter) { + if p.IsSetExtra() { + oprot.WriteFieldBegin(thrift.MAP, 3) + oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)) + for k, v := range p.Extra { + oprot.WriteString(k) + oprot.WriteString(v) + } + } +} + +func (p *BaseResp) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("BaseResp(%+v)", *p) +} From f230fab2fd743ace1c5bbfc04755b73c4b6dd684 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Fri, 26 Jul 2024 17:04:56 +0800 Subject: [PATCH 08/20] chore: define mtInfo --- client/genericclient/client.go | 5 +++-- client/genericclient/stream.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/genericclient/client.go b/client/genericclient/client.go index e032371df7..9412da7be0 100644 --- a/client/genericclient/client.go +++ b/client/genericclient/client.go @@ -97,7 +97,8 @@ type genericServiceClient struct { func (gc *genericServiceClient) GenericCall(ctx context.Context, method string, request interface{}, callOptions ...callopt.Option) (response interface{}, err error) { ctx = client.NewCtxWithCallOptions(ctx, callOptions) - _args := gc.svcInfo.MethodInfo(method).NewArgs().(*generic.Args) + mtInfo := gc.svcInfo.MethodInfo(method) + _args := mtInfo.NewArgs().(*generic.Args) _args.Method = method _args.Request = request @@ -109,7 +110,7 @@ func (gc *genericServiceClient) GenericCall(ctx context.Context, method string, return nil, gc.kClient.Call(ctx, mt.Name, _args, nil) } - _result := gc.svcInfo.MethodInfo(method).NewResult().(*generic.Result) + _result := mtInfo.NewResult().(*generic.Result) if err = gc.kClient.Call(ctx, mt.Name, _args, _result); err != nil { return } diff --git a/client/genericclient/stream.go b/client/genericclient/stream.go index c568e0b281..aeb862b69c 100644 --- a/client/genericclient/stream.go +++ b/client/genericclient/stream.go @@ -149,8 +149,9 @@ func NewServerStreaming(ctx context.Context, genericCli Client, method string, r if err != nil { return nil, err } - ss := &serverStreamingClient{stream, gCli.svcInfo.MethodInfo(method)} - _args := gCli.svcInfo.MethodInfo(method).NewArgs().(*generic.Args) + mtInfo := gCli.svcInfo.MethodInfo(method) + ss := &serverStreamingClient{stream, mtInfo} + _args := mtInfo.NewArgs().(*generic.Args) _args.Method = method _args.Request = req if err = ss.Stream.SendMsg(_args); err != nil { From 90715a05fe1011834a08479b2f7a67e7bf9eb397 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Fri, 26 Jul 2024 17:14:39 +0800 Subject: [PATCH 09/20] test: add tests for json thrift generic streaming --- internal/mocks/thrift/gen.sh | 4 + internal/mocks/thrift/k-stream.go | 1900 +++++++++++++++++ internal/mocks/thrift/stream.go | 864 ++++++++ internal/mocks/thrift/stream.thrift | 19 + .../grpcjsonthrift_test/generic_init.go | 420 ++++ .../grpcjsonthrift_test/generic_test.go | 269 +++ .../grpcjsonthrift_test/idl/api.thrift | 19 + 7 files changed, 3495 insertions(+) create mode 100644 internal/mocks/thrift/k-stream.go create mode 100644 internal/mocks/thrift/stream.go create mode 100644 internal/mocks/thrift/stream.thrift create mode 100644 pkg/generic/grpcjsonthrift_test/generic_init.go create mode 100644 pkg/generic/grpcjsonthrift_test/generic_test.go create mode 100644 pkg/generic/grpcjsonthrift_test/idl/api.thrift diff --git a/internal/mocks/thrift/gen.sh b/internal/mocks/thrift/gen.sh index dd4a4915a0..7e3385f1c2 100755 --- a/internal/mocks/thrift/gen.sh +++ b/internal/mocks/thrift/gen.sh @@ -2,4 +2,8 @@ kitex -thrift no_default_serdes -module github.com/cloudwego/kitex -gen-path .. ./test.thrift +kitex -thrift no_default_serdes -module github.com/cloudwego/kitex -gen-path .. ./stream.thrift + rm -rf ./mock # not in use, rm it + +rm -rf ./testservice # not in use, rm it \ No newline at end of file diff --git a/internal/mocks/thrift/k-stream.go b/internal/mocks/thrift/k-stream.go new file mode 100644 index 0000000000..ebcae431ad --- /dev/null +++ b/internal/mocks/thrift/k-stream.go @@ -0,0 +1,1900 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Code generated by Kitex v0.10.3. DO NOT EDIT. + +package thrift + +import ( + "bytes" + "fmt" + "reflect" + "strings" + + "github.com/apache/thrift/lib/go/thrift" + + "github.com/cloudwego/kitex/pkg/protocol/bthrift" +) + +// unused protection +var ( + _ = fmt.Formatter(nil) + _ = (*bytes.Buffer)(nil) + _ = (*strings.Builder)(nil) + _ = reflect.Type(nil) + _ = thrift.TProtocol(nil) + _ = bthrift.BinaryWriter(nil) +) + +func (p *Request) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + var issetMessage bool = false + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRING { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + issetMessage = true + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + if !issetMessage { + fieldId = 1 + goto RequiredFieldNotSetError + } + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Request[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +RequiredFieldNotSetError: + return offset, thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("required field %s is not set", fieldIDToName_Request[fieldId])) +} + +func (p *Request) FastReadField1(buf []byte) (int, error) { + offset := 0 + + var _field string + if v, l, err := bthrift.Binary.ReadString(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + + _field = v + + } + p.Message = _field + return offset, nil +} + +// for compatibility +func (p *Request) FastWrite(buf []byte) int { + return 0 +} + +func (p *Request) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "Request") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *Request) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("Request") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *Request) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "message", thrift.STRING, 1) + offset += bthrift.Binary.WriteStringNocopy(buf[offset:], binaryWriter, p.Message) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *Request) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("message", thrift.STRING, 1) + l += bthrift.Binary.StringLengthNocopy(p.Message) + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *Response) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + var issetMessage bool = false + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRING { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + issetMessage = true + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + if !issetMessage { + fieldId = 1 + goto RequiredFieldNotSetError + } + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Response[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +RequiredFieldNotSetError: + return offset, thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("required field %s is not set", fieldIDToName_Response[fieldId])) +} + +func (p *Response) FastReadField1(buf []byte) (int, error) { + offset := 0 + + var _field string + if v, l, err := bthrift.Binary.ReadString(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + + _field = v + + } + p.Message = _field + return offset, nil +} + +// for compatibility +func (p *Response) FastWrite(buf []byte) int { + return 0 +} + +func (p *Response) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "Response") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *Response) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("Response") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *Response) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "message", thrift.STRING, 1) + offset += bthrift.Binary.WriteStringNocopy(buf[offset:], binaryWriter, p.Message) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *Response) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("message", thrift.STRING, 1) + l += bthrift.Binary.StringLengthNocopy(p.Message) + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "Echo_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("Echo_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "Echo_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("Echo_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoClientArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoClientArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoClientArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoClientArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoClientArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoClient_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoClientArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoClient_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoClientArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoClientArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoClientResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoClientResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoClientResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoClientResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoClientResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoClient_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoClientResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoClient_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoClientResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoClientResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoServerArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoServerArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoServerArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoServerArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoServerArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoServer_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoServerArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoServer_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoServerArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoServerArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoServerResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoServerResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoServerResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoServerResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoServerResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoServer_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoServerResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoServer_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoServerResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoServerResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoUnaryArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoUnaryArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoUnaryArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoUnaryArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoUnaryArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoUnary_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoUnaryArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoUnary_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoUnaryArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoUnaryArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoUnaryResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoUnaryResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoUnaryResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoUnaryResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoUnaryResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoUnary_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoUnaryResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoUnary_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoUnaryResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoUnaryResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoBizExceptionArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoBizExceptionArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoBizExceptionArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoBizExceptionArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoBizExceptionArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoBizException_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoBizExceptionArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoBizException_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoBizExceptionArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoBizExceptionArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoBizExceptionResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoBizExceptionResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoBizExceptionResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoBizExceptionResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoBizExceptionResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoBizException_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoBizExceptionResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoBizException_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoBizExceptionResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoBizExceptionResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoPingPongArgs) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 1: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField1(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoPingPongArgs[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoPingPongArgs) FastReadField1(buf []byte) (int, error) { + offset := 0 + _field := NewRequest() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Req = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoPingPongArgs) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoPingPongArgs) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoPingPong_args") + if p != nil { + offset += p.fastWriteField1(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoPingPongArgs) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoPingPong_args") + if p != nil { + l += p.field1Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoPingPongArgs) fastWriteField1(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "req", thrift.STRUCT, 1) + offset += p.Req.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoPingPongArgs) field1Length() int { + l := 0 + l += bthrift.Binary.FieldBeginLength("req", thrift.STRUCT, 1) + l += p.Req.BLength() + l += bthrift.Binary.FieldEndLength() + return l +} + +func (p *TestServiceEchoPingPongResult) FastRead(buf []byte) (int, error) { + var err error + var offset int + var l int + var fieldTypeId thrift.TType + var fieldId int16 + _, l, err = bthrift.Binary.ReadStructBegin(buf) + offset += l + if err != nil { + goto ReadStructBeginError + } + + for { + _, fieldTypeId, fieldId, l, err = bthrift.Binary.ReadFieldBegin(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldBeginError + } + if fieldTypeId == thrift.STOP { + break + } + switch fieldId { + case 0: + if fieldTypeId == thrift.STRUCT { + l, err = p.FastReadField0(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldError + } + } else { + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + default: + l, err = bthrift.Binary.Skip(buf[offset:], fieldTypeId) + offset += l + if err != nil { + goto SkipFieldError + } + } + + l, err = bthrift.Binary.ReadFieldEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadFieldEndError + } + } + l, err = bthrift.Binary.ReadStructEnd(buf[offset:]) + offset += l + if err != nil { + goto ReadStructEndError + } + + return offset, nil +ReadStructBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err) +ReadFieldBeginError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) +ReadFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TestServiceEchoPingPongResult[fieldId]), err) +SkipFieldError: + return offset, thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) +ReadFieldEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read field end error", p), err) +ReadStructEndError: + return offset, thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) +} + +func (p *TestServiceEchoPingPongResult) FastReadField0(buf []byte) (int, error) { + offset := 0 + _field := NewResponse() + if l, err := _field.FastRead(buf[offset:]); err != nil { + return offset, err + } else { + offset += l + } + p.Success = _field + return offset, nil +} + +// for compatibility +func (p *TestServiceEchoPingPongResult) FastWrite(buf []byte) int { + return 0 +} + +func (p *TestServiceEchoPingPongResult) FastWriteNocopy(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + offset += bthrift.Binary.WriteStructBegin(buf[offset:], "EchoPingPong_result") + if p != nil { + offset += p.fastWriteField0(buf[offset:], binaryWriter) + } + offset += bthrift.Binary.WriteFieldStop(buf[offset:]) + offset += bthrift.Binary.WriteStructEnd(buf[offset:]) + return offset +} + +func (p *TestServiceEchoPingPongResult) BLength() int { + l := 0 + l += bthrift.Binary.StructBeginLength("EchoPingPong_result") + if p != nil { + l += p.field0Length() + } + l += bthrift.Binary.FieldStopLength() + l += bthrift.Binary.StructEndLength() + return l +} + +func (p *TestServiceEchoPingPongResult) fastWriteField0(buf []byte, binaryWriter bthrift.BinaryWriter) int { + offset := 0 + if p.IsSetSuccess() { + offset += bthrift.Binary.WriteFieldBegin(buf[offset:], "success", thrift.STRUCT, 0) + offset += p.Success.FastWriteNocopy(buf[offset:], binaryWriter) + offset += bthrift.Binary.WriteFieldEnd(buf[offset:]) + } + return offset +} + +func (p *TestServiceEchoPingPongResult) field0Length() int { + l := 0 + if p.IsSetSuccess() { + l += bthrift.Binary.FieldBeginLength("success", thrift.STRUCT, 0) + l += p.Success.BLength() + l += bthrift.Binary.FieldEndLength() + } + return l +} + +func (p *TestServiceEchoArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoResult) GetResult() interface{} { + return p.Success +} + +func (p *TestServiceEchoClientArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoClientResult) GetResult() interface{} { + return p.Success +} + +func (p *TestServiceEchoServerArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoServerResult) GetResult() interface{} { + return p.Success +} + +func (p *TestServiceEchoUnaryArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoUnaryResult) GetResult() interface{} { + return p.Success +} + +func (p *TestServiceEchoBizExceptionArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoBizExceptionResult) GetResult() interface{} { + return p.Success +} + +func (p *TestServiceEchoPingPongArgs) GetFirstArgument() interface{} { + return p.Req +} + +func (p *TestServiceEchoPingPongResult) GetResult() interface{} { + return p.Success +} diff --git a/internal/mocks/thrift/stream.go b/internal/mocks/thrift/stream.go new file mode 100644 index 0000000000..7af7d0c7cb --- /dev/null +++ b/internal/mocks/thrift/stream.go @@ -0,0 +1,864 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Code generated by thriftgo (0.3.13). DO NOT EDIT. + +package thrift + +import ( + "context" + "fmt" + "github.com/cloudwego/kitex/pkg/streaming" + "strings" +) + +type Request struct { + Message string `thrift:"message,1,required" frugal:"1,required,string" json:"message"` +} + +func NewRequest() *Request { + return &Request{} +} + +func (p *Request) InitDefault() { +} + +func (p *Request) GetMessage() (v string) { + return p.Message +} +func (p *Request) SetMessage(val string) { + p.Message = val +} + +func (p *Request) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Request(%+v)", *p) +} + +func (p *Request) DeepEqual(ano *Request) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Message) { + return false + } + return true +} + +func (p *Request) Field1DeepEqual(src string) bool { + + if strings.Compare(p.Message, src) != 0 { + return false + } + return true +} + +var fieldIDToName_Request = map[int16]string{ + 1: "message", +} + +type Response struct { + Message string `thrift:"message,1,required" frugal:"1,required,string" json:"message"` +} + +func NewResponse() *Response { + return &Response{} +} + +func (p *Response) InitDefault() { +} + +func (p *Response) GetMessage() (v string) { + return p.Message +} +func (p *Response) SetMessage(val string) { + p.Message = val +} + +func (p *Response) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("Response(%+v)", *p) +} + +func (p *Response) DeepEqual(ano *Response) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Message) { + return false + } + return true +} + +func (p *Response) Field1DeepEqual(src string) bool { + + if strings.Compare(p.Message, src) != 0 { + return false + } + return true +} + +var fieldIDToName_Response = map[int16]string{ + 1: "message", +} + +type TestService interface { + Echo(stream TestService_EchoServer) (err error) + + EchoClient(stream TestService_EchoClientServer) (err error) + + EchoServer(req *Request, stream TestService_EchoServerServer) (err error) + + EchoUnary(ctx context.Context, req *Request) (r *Response, err error) + + EchoBizException(stream TestService_EchoBizExceptionServer) (err error) + + EchoPingPong(ctx context.Context, req *Request) (r *Response, err error) +} + +type TestServiceEchoArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoArgs() *TestServiceEchoArgs { + return &TestServiceEchoArgs{} +} + +func (p *TestServiceEchoArgs) InitDefault() { +} + +var TestServiceEchoArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoArgs(%+v)", *p) +} + +func (p *TestServiceEchoArgs) DeepEqual(ano *TestServiceEchoArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoResult() *TestServiceEchoResult { + return &TestServiceEchoResult{} +} + +func (p *TestServiceEchoResult) InitDefault() { +} + +var TestServiceEchoResult_Success_DEFAULT *Response + +func (p *TestServiceEchoResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoResult(%+v)", *p) +} + +func (p *TestServiceEchoResult) DeepEqual(ano *TestServiceEchoResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoResult = map[int16]string{ + 0: "success", +} + +type TestService_EchoServer interface { + streaming.Stream + + Recv() (*Request, error) + + Send(*Response) error +} + +type TestServiceEchoClientArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoClientArgs() *TestServiceEchoClientArgs { + return &TestServiceEchoClientArgs{} +} + +func (p *TestServiceEchoClientArgs) InitDefault() { +} + +var TestServiceEchoClientArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoClientArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoClientArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoClientArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoClientArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoClientArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoClientArgs(%+v)", *p) +} + +func (p *TestServiceEchoClientArgs) DeepEqual(ano *TestServiceEchoClientArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoClientArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoClientArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoClientResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoClientResult() *TestServiceEchoClientResult { + return &TestServiceEchoClientResult{} +} + +func (p *TestServiceEchoClientResult) InitDefault() { +} + +var TestServiceEchoClientResult_Success_DEFAULT *Response + +func (p *TestServiceEchoClientResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoClientResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoClientResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoClientResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoClientResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoClientResult(%+v)", *p) +} + +func (p *TestServiceEchoClientResult) DeepEqual(ano *TestServiceEchoClientResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoClientResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoClientResult = map[int16]string{ + 0: "success", +} + +type TestService_EchoClientServer interface { + streaming.Stream + + Recv() (*Request, error) + + SendAndClose(*Response) error +} + +type TestServiceEchoServerArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoServerArgs() *TestServiceEchoServerArgs { + return &TestServiceEchoServerArgs{} +} + +func (p *TestServiceEchoServerArgs) InitDefault() { +} + +var TestServiceEchoServerArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoServerArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoServerArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoServerArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoServerArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoServerArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoServerArgs(%+v)", *p) +} + +func (p *TestServiceEchoServerArgs) DeepEqual(ano *TestServiceEchoServerArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoServerArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoServerArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoServerResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoServerResult() *TestServiceEchoServerResult { + return &TestServiceEchoServerResult{} +} + +func (p *TestServiceEchoServerResult) InitDefault() { +} + +var TestServiceEchoServerResult_Success_DEFAULT *Response + +func (p *TestServiceEchoServerResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoServerResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoServerResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoServerResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoServerResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoServerResult(%+v)", *p) +} + +func (p *TestServiceEchoServerResult) DeepEqual(ano *TestServiceEchoServerResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoServerResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoServerResult = map[int16]string{ + 0: "success", +} + +type TestService_EchoServerServer interface { + streaming.Stream + + Send(*Response) error +} + +type TestServiceEchoUnaryArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoUnaryArgs() *TestServiceEchoUnaryArgs { + return &TestServiceEchoUnaryArgs{} +} + +func (p *TestServiceEchoUnaryArgs) InitDefault() { +} + +var TestServiceEchoUnaryArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoUnaryArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoUnaryArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoUnaryArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoUnaryArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoUnaryArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoUnaryArgs(%+v)", *p) +} + +func (p *TestServiceEchoUnaryArgs) DeepEqual(ano *TestServiceEchoUnaryArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoUnaryArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoUnaryArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoUnaryResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoUnaryResult() *TestServiceEchoUnaryResult { + return &TestServiceEchoUnaryResult{} +} + +func (p *TestServiceEchoUnaryResult) InitDefault() { +} + +var TestServiceEchoUnaryResult_Success_DEFAULT *Response + +func (p *TestServiceEchoUnaryResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoUnaryResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoUnaryResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoUnaryResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoUnaryResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoUnaryResult(%+v)", *p) +} + +func (p *TestServiceEchoUnaryResult) DeepEqual(ano *TestServiceEchoUnaryResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoUnaryResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoUnaryResult = map[int16]string{ + 0: "success", +} + +type TestServiceEchoBizExceptionArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoBizExceptionArgs() *TestServiceEchoBizExceptionArgs { + return &TestServiceEchoBizExceptionArgs{} +} + +func (p *TestServiceEchoBizExceptionArgs) InitDefault() { +} + +var TestServiceEchoBizExceptionArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoBizExceptionArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoBizExceptionArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoBizExceptionArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoBizExceptionArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoBizExceptionArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoBizExceptionArgs(%+v)", *p) +} + +func (p *TestServiceEchoBizExceptionArgs) DeepEqual(ano *TestServiceEchoBizExceptionArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoBizExceptionArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoBizExceptionArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoBizExceptionResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoBizExceptionResult() *TestServiceEchoBizExceptionResult { + return &TestServiceEchoBizExceptionResult{} +} + +func (p *TestServiceEchoBizExceptionResult) InitDefault() { +} + +var TestServiceEchoBizExceptionResult_Success_DEFAULT *Response + +func (p *TestServiceEchoBizExceptionResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoBizExceptionResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoBizExceptionResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoBizExceptionResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoBizExceptionResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoBizExceptionResult(%+v)", *p) +} + +func (p *TestServiceEchoBizExceptionResult) DeepEqual(ano *TestServiceEchoBizExceptionResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoBizExceptionResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoBizExceptionResult = map[int16]string{ + 0: "success", +} + +type TestService_EchoBizExceptionServer interface { + streaming.Stream + + Recv() (*Request, error) + + SendAndClose(*Response) error +} + +type TestServiceEchoPingPongArgs struct { + Req *Request `thrift:"req,1" frugal:"1,default,Request" json:"req"` +} + +func NewTestServiceEchoPingPongArgs() *TestServiceEchoPingPongArgs { + return &TestServiceEchoPingPongArgs{} +} + +func (p *TestServiceEchoPingPongArgs) InitDefault() { +} + +var TestServiceEchoPingPongArgs_Req_DEFAULT *Request + +func (p *TestServiceEchoPingPongArgs) GetReq() (v *Request) { + if !p.IsSetReq() { + return TestServiceEchoPingPongArgs_Req_DEFAULT + } + return p.Req +} +func (p *TestServiceEchoPingPongArgs) SetReq(val *Request) { + p.Req = val +} + +func (p *TestServiceEchoPingPongArgs) IsSetReq() bool { + return p.Req != nil +} + +func (p *TestServiceEchoPingPongArgs) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoPingPongArgs(%+v)", *p) +} + +func (p *TestServiceEchoPingPongArgs) DeepEqual(ano *TestServiceEchoPingPongArgs) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field1DeepEqual(ano.Req) { + return false + } + return true +} + +func (p *TestServiceEchoPingPongArgs) Field1DeepEqual(src *Request) bool { + + if !p.Req.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoPingPongArgs = map[int16]string{ + 1: "req", +} + +type TestServiceEchoPingPongResult struct { + Success *Response `thrift:"success,0,optional" frugal:"0,optional,Response" json:"success,omitempty"` +} + +func NewTestServiceEchoPingPongResult() *TestServiceEchoPingPongResult { + return &TestServiceEchoPingPongResult{} +} + +func (p *TestServiceEchoPingPongResult) InitDefault() { +} + +var TestServiceEchoPingPongResult_Success_DEFAULT *Response + +func (p *TestServiceEchoPingPongResult) GetSuccess() (v *Response) { + if !p.IsSetSuccess() { + return TestServiceEchoPingPongResult_Success_DEFAULT + } + return p.Success +} +func (p *TestServiceEchoPingPongResult) SetSuccess(x interface{}) { + p.Success = x.(*Response) +} + +func (p *TestServiceEchoPingPongResult) IsSetSuccess() bool { + return p.Success != nil +} + +func (p *TestServiceEchoPingPongResult) String() string { + if p == nil { + return "" + } + return fmt.Sprintf("TestServiceEchoPingPongResult(%+v)", *p) +} + +func (p *TestServiceEchoPingPongResult) DeepEqual(ano *TestServiceEchoPingPongResult) bool { + if p == ano { + return true + } else if p == nil || ano == nil { + return false + } + if !p.Field0DeepEqual(ano.Success) { + return false + } + return true +} + +func (p *TestServiceEchoPingPongResult) Field0DeepEqual(src *Response) bool { + + if !p.Success.DeepEqual(src) { + return false + } + return true +} + +var fieldIDToName_TestServiceEchoPingPongResult = map[int16]string{ + 0: "success", +} diff --git a/internal/mocks/thrift/stream.thrift b/internal/mocks/thrift/stream.thrift new file mode 100644 index 0000000000..88461092c0 --- /dev/null +++ b/internal/mocks/thrift/stream.thrift @@ -0,0 +1,19 @@ +namespace go thrift + +struct Request { + 1: required string message, +} + +struct Response { + 1: required string message, +} + +service TestService { + Response Echo (1: Request req) (streaming.mode="bidirectional"), + Response EchoClient (1: Request req) (streaming.mode="client"), + Response EchoServer (1: Request req) (streaming.mode="server"), + Response EchoUnary (1: Request req) (streaming.mode="unary"), // not recommended + Response EchoBizException (1: Request req) (streaming.mode="client"), + + Response EchoPingPong (1: Request req), // KitexThrift, non-streaming +} \ No newline at end of file diff --git a/pkg/generic/grpcjsonthrift_test/generic_init.go b/pkg/generic/grpcjsonthrift_test/generic_init.go new file mode 100644 index 0000000000..5d2d44b751 --- /dev/null +++ b/pkg/generic/grpcjsonthrift_test/generic_init.go @@ -0,0 +1,420 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "strings" + "sync" + "time" + + "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/client/genericclient" + kt "github.com/cloudwego/kitex/internal/mocks/thrift" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/kerrors" + kitex "github.com/cloudwego/kitex/pkg/serviceinfo" + "github.com/cloudwego/kitex/pkg/streaming" + "github.com/cloudwego/kitex/server" + "github.com/cloudwego/kitex/transport" +) + +func newGenericStreamingClient(g generic.Generic, targetIPPort string) genericclient.Client { + cli, err := genericclient.NewStreamingClient("destService", g, + client.WithTransportProtocol(transport.GRPC), + client.WithHostPorts(targetIPPort), + ) + if err != nil { + panic(err) + } + return cli +} + +func newGenericClient(g generic.Generic, targetIPPort string) genericclient.Client { + cli, err := genericclient.NewClient("destService", g, client.WithHostPorts(targetIPPort)) + if err != nil { + panic(err) + } + return cli +} + +var _ kt.TestService = &StreamingTestImpl{} + +type StreamingTestImpl struct{} + +func (s *StreamingTestImpl) Echo(stream kt.TestService_EchoServer) (err error) { + fmt.Println("Echo called") + wg := &sync.WaitGroup{} + wg.Add(2) + + go func() { + defer func() { + if p := recover(); p != nil { + err = fmt.Errorf("panic: %v", p) + } + wg.Done() + }() + defer stream.Close() + for { + msg, recvErr := stream.Recv() + if recvErr == io.EOF { + return + } else if recvErr != nil { + err = recvErr + return + } + fmt.Printf("Echo: received message = %s\n", msg.Message) + time.Sleep(100 * time.Millisecond) + } + }() + + go func() { + defer func() { + if p := recover(); p != nil { + err = fmt.Errorf("panic: %v", p) + } + wg.Done() + }() + resp := &kt.Response{} + for i := 0; i < 3; i++ { + resp.Message = fmt.Sprintf("%dth response", i) + if sendErr := stream.Send(resp); sendErr != nil { + err = sendErr + return + } + fmt.Printf("Echo: sent message = %s\n", resp) + time.Sleep(100 * time.Millisecond) + } + }() + wg.Wait() + return +} + +func (s *StreamingTestImpl) EchoClient(stream kt.TestService_EchoClientServer) (err error) { + fmt.Println("EchoClient called") + var msgs []string + for { + req, err := stream.Recv() + if err != nil { + if err == io.EOF { + break + } + return err + } + fmt.Printf("Recv: %s\n", req.Message) + msgs = append(msgs, req.Message) + time.Sleep(100 * time.Millisecond) + } + return stream.SendAndClose(&kt.Response{Message: "all message: " + strings.Join(msgs, ", ")}) +} + +func (s *StreamingTestImpl) EchoServer(req *kt.Request, stream kt.TestService_EchoServerServer) (err error) { + fmt.Println("EchoServer called") + resp := &kt.Response{} + for i := 0; i < 3; i++ { + resp.Message = fmt.Sprintf("%v -> %dth response", req.Message, i) + err := stream.Send(resp) + if err != nil { + return err + } + time.Sleep(100 * time.Millisecond) + } + return +} + +func (s *StreamingTestImpl) EchoUnary(ctx context.Context, req *kt.Request) (resp *kt.Response, err error) { + fmt.Println("EchoUnary called") + resp = &kt.Response{} + resp.Message = "hello " + req.Message + return +} + +func (s *StreamingTestImpl) EchoPingPong(ctx context.Context, req *kt.Request) (resp *kt.Response, err error) { + fmt.Println("EchoPingPong called") + resp = &kt.Response{} + resp.Message = "hello " + req.Message + return +} + +func (s *StreamingTestImpl) EchoBizException(stream kt.TestService_EchoBizExceptionServer) error { + fmt.Println("EchoBizException called") + for { + req, err := stream.Recv() + if err != nil { + if err == io.EOF { + break + } + return err + } + fmt.Printf("Recv: %s\n", req.Message) + time.Sleep(100 * time.Millisecond) + } + return kerrors.NewBizStatusError(int32(404), "not found") +} + +// normal server +func newMockServer(handler kt.TestService, addr net.Addr, opts ...server.Option) server.Server { + var options []server.Option + + opts = append(opts, server.WithServiceAddr(addr)) + options = append(options, opts...) + options = append(options, server.WithCompatibleMiddlewareForUnary()) + + svr := server.NewServer(options...) + if err := svr.RegisterService(serviceInfo(), handler); err != nil { + panic(err) + } + go func() { + err := svr.Run() + if err != nil { + panic(err) + } + }() + return svr +} + +var serviceMethods = map[string]kitex.MethodInfo{ + "Echo": kitex.NewMethodInfo( + echoHandler, + newTestServiceEchoArgs, + newTestServiceEchoResult, + false, + kitex.WithStreamingMode(kitex.StreamingBidirectional), + ), + "EchoClient": kitex.NewMethodInfo( + echoClientHandler, + newTestServiceEchoClientArgs, + newTestServiceEchoClientResult, + false, + kitex.WithStreamingMode(kitex.StreamingClient), + ), + "EchoServer": kitex.NewMethodInfo( + echoServerHandler, + newTestServiceEchoServerArgs, + newTestServiceEchoServerResult, + false, + kitex.WithStreamingMode(kitex.StreamingServer), + ), + "EchoUnary": kitex.NewMethodInfo( + echoUnaryHandler, + newTestServiceEchoUnaryArgs, + newTestServiceEchoUnaryResult, + false, + kitex.WithStreamingMode(kitex.StreamingUnary), + ), + "EchoBizException": kitex.NewMethodInfo( + echoBizExceptionHandler, + newTestServiceEchoBizExceptionArgs, + newTestServiceEchoBizExceptionResult, + false, + kitex.WithStreamingMode(kitex.StreamingClient), + ), + "EchoPingPong": kitex.NewMethodInfo( + echoPingPongHandler, + newTestServiceEchoPingPongArgs, + newTestServiceEchoPingPongResult, + false, + kitex.WithStreamingMode(kitex.StreamingNone), + ), +} + +func serviceInfo() *kitex.ServiceInfo { + serviceName := "TestService" + handlerType := (*kt.TestService)(nil) + methods := map[string]kitex.MethodInfo{} + for name, m := range serviceMethods { + methods[name] = m + } + extra := map[string]interface{}{ + "PackageName": "thrift", + } + extra["streaming"] = true + + svcInfo := &kitex.ServiceInfo{ + ServiceName: serviceName, + HandlerType: handlerType, + Methods: methods, + PayloadCodec: kitex.Thrift, + KiteXGenVersion: "v0.11.0", + Extra: extra, + } + return svcInfo +} + +func echoHandler(ctx context.Context, handler, arg, result interface{}) error { + st, ok := arg.(*streaming.Args) + if !ok { + return errors.New("TestService.Echo is a thrift streaming method, please call with Kitex StreamClient") + } + stream := &testServiceEchoServer{st.Stream} + return handler.(kt.TestService).Echo(stream) +} + +type testServiceEchoServer struct { + streaming.Stream +} + +func (x *testServiceEchoServer) Send(m *kt.Response) error { + return x.Stream.SendMsg(m) +} + +func (x *testServiceEchoServer) Recv() (*kt.Request, error) { + m := new(kt.Request) + return m, x.Stream.RecvMsg(m) +} + +func newTestServiceEchoArgs() interface{} { + return kt.NewTestServiceEchoArgs() +} + +func newTestServiceEchoResult() interface{} { + return kt.NewTestServiceEchoResult() +} + +func echoClientHandler(ctx context.Context, handler, arg, result interface{}) error { + st, ok := arg.(*streaming.Args) + if !ok { + return errors.New("TestService.EchoClient is a thrift streaming method, please call with Kitex StreamClient") + } + stream := &testServiceEchoClientServer{st.Stream} + return handler.(kt.TestService).EchoClient(stream) +} + +type testServiceEchoClientServer struct { + streaming.Stream +} + +func (x *testServiceEchoClientServer) SendAndClose(m *kt.Response) error { + return x.Stream.SendMsg(m) +} + +func (x *testServiceEchoClientServer) Recv() (*kt.Request, error) { + m := new(kt.Request) + return m, x.Stream.RecvMsg(m) +} + +func newTestServiceEchoClientArgs() interface{} { + return kt.NewTestServiceEchoClientArgs() +} + +func newTestServiceEchoClientResult() interface{} { + return kt.NewTestServiceEchoClientResult() +} + +func echoServerHandler(ctx context.Context, handler, arg, result interface{}) error { + st, ok := arg.(*streaming.Args) + if !ok { + return errors.New("TestService.EchoServer is a thrift streaming method, please call with Kitex StreamClient") + } + stream := &testServiceEchoServerServer{st.Stream} + req := new(kt.Request) + if err := st.Stream.RecvMsg(req); err != nil { + return err + } + return handler.(kt.TestService).EchoServer(req, stream) +} + +type testServiceEchoServerServer struct { + streaming.Stream +} + +func (x *testServiceEchoServerServer) Send(m *kt.Response) error { + return x.Stream.SendMsg(m) +} + +func newTestServiceEchoServerArgs() interface{} { + return kt.NewTestServiceEchoServerArgs() +} + +func newTestServiceEchoServerResult() interface{} { + return kt.NewTestServiceEchoServerResult() +} + +func echoUnaryHandler(ctx context.Context, handler, arg, result interface{}) error { + if streaming.GetStream(ctx) == nil { + return errors.New("TestService.EchoUnary is a thrift streaming unary method, please call with Kitex StreamClient or remove the annotation streaming.mode") + } + realArg := arg.(*kt.TestServiceEchoUnaryArgs) + realResult := result.(*kt.TestServiceEchoUnaryResult) + success, err := handler.(kt.TestService).EchoUnary(ctx, realArg.Req) + if err != nil { + return err + } + realResult.Success = success + return nil +} + +func newTestServiceEchoUnaryArgs() interface{} { + return kt.NewTestServiceEchoUnaryArgs() +} + +func newTestServiceEchoUnaryResult() interface{} { + return kt.NewTestServiceEchoUnaryResult() +} + +func echoBizExceptionHandler(ctx context.Context, handler, arg, result interface{}) error { + st, ok := arg.(*streaming.Args) + if !ok { + return errors.New("TestService.EchoBizException is a thrift streaming method, please call with Kitex StreamClient") + } + stream := &testServiceEchoBizExceptionServer{st.Stream} + return handler.(kt.TestService).EchoBizException(stream) +} + +type testServiceEchoBizExceptionServer struct { + streaming.Stream +} + +func (x *testServiceEchoBizExceptionServer) SendAndClose(m *kt.Response) error { + return x.Stream.SendMsg(m) +} + +func (x *testServiceEchoBizExceptionServer) Recv() (*kt.Request, error) { + m := new(kt.Request) + return m, x.Stream.RecvMsg(m) +} + +func newTestServiceEchoBizExceptionArgs() interface{} { + return kt.NewTestServiceEchoBizExceptionArgs() +} + +func newTestServiceEchoBizExceptionResult() interface{} { + return kt.NewTestServiceEchoBizExceptionResult() +} + +func echoPingPongHandler(ctx context.Context, handler, arg, result interface{}) error { + realArg := kt.UnpackApacheCodec(arg).(*kt.TestServiceEchoPingPongArgs) + realResult := kt.UnpackApacheCodec(result).(*kt.TestServiceEchoPingPongResult) + success, err := handler.(kt.TestService).EchoPingPong(ctx, realArg.Req) + if err != nil { + return err + } + realResult.Success = success + return nil +} + +func newTestServiceEchoPingPongArgs() interface{} { + return kt.ToApacheCodec(kt.NewTestServiceEchoPingPongArgs()) +} + +func newTestServiceEchoPingPongResult() interface{} { + return kt.ToApacheCodec(kt.NewTestServiceEchoPingPongResult()) +} diff --git a/pkg/generic/grpcjsonthrift_test/generic_test.go b/pkg/generic/grpcjsonthrift_test/generic_test.go new file mode 100644 index 0000000000..ca9e2808fe --- /dev/null +++ b/pkg/generic/grpcjsonthrift_test/generic_test.go @@ -0,0 +1,269 @@ +/* + * Copyright 2024 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test + +import ( + "context" + "fmt" + "io" + "net" + "reflect" + "strings" + "sync" + "testing" + "time" + + "github.com/tidwall/gjson" + + "github.com/cloudwego/kitex/client/genericclient" + kt "github.com/cloudwego/kitex/internal/mocks/thrift" + "github.com/cloudwego/kitex/internal/test" + "github.com/cloudwego/kitex/pkg/generic" + "github.com/cloudwego/kitex/pkg/kerrors" + "github.com/cloudwego/kitex/server" +) + +var idl = "./idl/api.thrift" + +func TestClientStreaming(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initStreamingClient(t, addr, idl, false) + testClientStreaming(t, ctx, cli) + + // with dynamicgo + cli = initStreamingClient(t, addr, idl, true) + testClientStreaming(t, ctx, cli) +} + +func TestServerStreaming(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initStreamingClient(t, addr, idl, false) + testServerStreaming(t, ctx, cli) + + // with dynamicgo + cli = initStreamingClient(t, addr, idl, true) + testServerStreaming(t, ctx, cli) +} + +func TestBidirectionalStreaming(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initStreamingClient(t, addr, idl, false) + testBidirectionalStreaming(t, ctx, cli) + + // with dynamicgo + cli = initStreamingClient(t, addr, idl, true) + testBidirectionalStreaming(t, ctx, cli) +} + +func TestUnary(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initStreamingClient(t, addr, idl, false) + testUnary(t, ctx, cli) + + // with dynamicgo + cli = initStreamingClient(t, addr, idl, true) + testUnary(t, ctx, cli) +} + +func TestBizException(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initStreamingClient(t, addr, idl, false) + streamCli, err := genericclient.NewClientStreaming(ctx, cli, "EchoBizException") + test.Assert(t, err == nil) + for i := 0; i < 3; i++ { + req := fmt.Sprintf(`{"message": "grpc client streaming generic %dth request"}`, i) + err = streamCli.Send(req) + test.Assert(t, err == nil, err) + time.Sleep(100 * time.Millisecond) + } + resp, err := streamCli.CloseAndRecv() + test.Assert(t, err != nil) + bizStatusErr, ok := kerrors.FromBizStatusError(err) + test.Assert(t, ok) + test.Assert(t, bizStatusErr.BizStatusCode() == 404) + test.Assert(t, bizStatusErr.BizMessage() == "not found") + test.Assert(t, resp == nil) +} + +func TestNoneStreaming(t *testing.T) { + ctx := context.Background() + addr := test.GetLocalAddress() + + svr := initMockTestServer(new(StreamingTestImpl), addr) + defer svr.Stop() + + cli := initGenericClient(t, addr, idl, false) + testNoneStreaming(t, ctx, cli) + + // with dynamicgo + cli = initGenericClient(t, addr, idl, true) + testNoneStreaming(t, ctx, cli) +} + +func initStreamingClient(t *testing.T, addr, idl string, enableDynamicgo bool) genericclient.Client { + g, err := getJsonThriftGeneric(idl, enableDynamicgo) + test.Assert(t, err == nil) + return newGenericStreamingClient(g, addr) +} + +func initGenericClient(t *testing.T, addr, idl string, enableDynamicgo bool) genericclient.Client { + g, err := getJsonThriftGeneric(idl, enableDynamicgo) + test.Assert(t, err == nil) + return newGenericClient(g, addr) +} + +func getJsonThriftGeneric(idl string, enableDynamicgo bool) (generic.Generic, error) { + var p generic.DescriptorProvider + var err error + if enableDynamicgo { + p, err = generic.NewThriftFileProviderWithDynamicGo(idl) + if err != nil { + return nil, err + } + } else { + p, err = generic.NewThriftFileProvider(idl) + if err != nil { + return nil, err + } + } + g, err := generic.JSONThriftGeneric(p) + if err != nil { + return nil, err + } + return g, nil +} + +func initMockTestServer(handler kt.TestService, address string) server.Server { + addr, _ := net.ResolveTCPAddr("tcp", address) + return newMockServer(handler, addr) +} + +func testClientStreaming(t *testing.T, ctx context.Context, cli genericclient.Client) { + streamCli, err := genericclient.NewClientStreaming(ctx, cli, "EchoClient") + test.Assert(t, err == nil) + for i := 0; i < 3; i++ { + req := fmt.Sprintf(`{"message": "grpc client streaming generic %dth request"}`, i) + err = streamCli.Send(req) + test.Assert(t, err == nil, err) + time.Sleep(100 * time.Millisecond) + } + resp, err := streamCli.CloseAndRecv() + test.Assert(t, err == nil, err) + strResp, ok := resp.(string) + test.Assert(t, ok) + fmt.Printf("clientStreaming message received: %v\n", strResp) + test.Assert(t, reflect.DeepEqual(gjson.Get(strResp, "message").String(), + "all message: grpc client streaming generic 0th request, grpc client streaming generic 1th request, grpc client streaming generic 2th request")) +} + +func testServerStreaming(t *testing.T, ctx context.Context, cli genericclient.Client) { + streamCli, err := genericclient.NewServerStreaming(ctx, cli, "EchoServer", `{"message": "grpc server streaming generic request"}`) + test.Assert(t, err == nil, err) + for { + resp, err := streamCli.Recv() + if err != nil { + test.Assert(t, err == io.EOF) + fmt.Println("serverStreaming message receive done") + break + } else { + strResp, ok := resp.(string) + test.Assert(t, ok) + fmt.Printf("serverStreaming message received: %s\n", strResp) + test.Assert(t, strings.Contains(gjson.Get(strResp, "message").String(), "grpc server streaming generic request ->")) + } + time.Sleep(100 * time.Millisecond) + } +} + +func testBidirectionalStreaming(t *testing.T, ctx context.Context, cli genericclient.Client) { + streamCli, err := genericclient.NewBidirectionalStreaming(ctx, cli, "Echo") + test.Assert(t, err == nil) + + wg := &sync.WaitGroup{} + wg.Add(2) + + go func() { + defer wg.Done() + defer streamCli.Close() + for i := 0; i < 3; i++ { + req := fmt.Sprintf(`{"message": "grpc bidirectional streaming generic %dth request"}`, i) + err = streamCli.Send(req) + test.Assert(t, err == nil) + fmt.Printf("Echo send: req = %s\n", req) + } + }() + + go func() { + defer wg.Done() + for { + resp, err := streamCli.Recv() + if err != nil { + test.Assert(t, err == io.EOF) + fmt.Println("bidirectionalStreaming message receive done") + break + } else { + strResp, ok := resp.(string) + test.Assert(t, ok) + fmt.Printf("bidirectionalStreaming message received: %s\n", strResp) + test.Assert(t, strings.Contains(gjson.Get(strResp, "message").String(), "th response")) + } + time.Sleep(100 * time.Millisecond) + } + }() + wg.Wait() +} + +func testUnary(t *testing.T, ctx context.Context, cli genericclient.Client) { + resp, err := cli.GenericCall(ctx, "EchoUnary", `{"message": "unary request"}`) + test.Assert(t, err == nil) + strResp, ok := resp.(string) + test.Assert(t, ok) + test.Assert(t, reflect.DeepEqual(gjson.Get(strResp, "message").String(), "hello unary request")) +} + +func testNoneStreaming(t *testing.T, ctx context.Context, cli genericclient.Client) { + resp, err := cli.GenericCall(ctx, "EchoPingPong", `{"message": "ping pong request"}`) + test.Assert(t, err == nil, err) + strResp, ok := resp.(string) + test.Assert(t, ok) + test.Assert(t, reflect.DeepEqual(gjson.Get(strResp, "message").String(), "hello ping pong request")) +} diff --git a/pkg/generic/grpcjsonthrift_test/idl/api.thrift b/pkg/generic/grpcjsonthrift_test/idl/api.thrift new file mode 100644 index 0000000000..88461092c0 --- /dev/null +++ b/pkg/generic/grpcjsonthrift_test/idl/api.thrift @@ -0,0 +1,19 @@ +namespace go thrift + +struct Request { + 1: required string message, +} + +struct Response { + 1: required string message, +} + +service TestService { + Response Echo (1: Request req) (streaming.mode="bidirectional"), + Response EchoClient (1: Request req) (streaming.mode="client"), + Response EchoServer (1: Request req) (streaming.mode="server"), + Response EchoUnary (1: Request req) (streaming.mode="unary"), // not recommended + Response EchoBizException (1: Request req) (streaming.mode="client"), + + Response EchoPingPong (1: Request req), // KitexThrift, non-streaming +} \ No newline at end of file From 881573a3edd3462f1bc9b258a94110e258dd0274 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 13:36:39 +0800 Subject: [PATCH 10/20] feat: thrift binary writer --- internal/generic/thrift/http.go | 8 ++--- internal/generic/thrift/http_fallback.go | 5 +-- .../generic/thrift/http_go116plus_amd64.go | 16 ++++------ internal/generic/thrift/http_pb.go | 7 ++-- internal/generic/thrift/json.go | 12 +++---- internal/generic/thrift/json_fallback.go | 5 +-- .../generic/thrift/json_go116plus_amd64.go | 32 +++++++++---------- internal/generic/thrift/struct.go | 7 ++-- internal/generic/thrift/thrift.go | 3 +- pkg/generic/generic_service.go | 19 +++++------ pkg/generic/generic_service_test.go | 13 ++++---- pkg/remote/codec/thrift/thrift.go | 6 ++-- 12 files changed, 65 insertions(+), 68 deletions(-) diff --git a/internal/generic/thrift/http.go b/internal/generic/thrift/http.go index fd31bfcbce..ce786d4870 100644 --- a/internal/generic/thrift/http.go +++ b/internal/generic/thrift/http.go @@ -80,7 +80,7 @@ func (w *WriteHTTPRequest) SetDynamicGo(convOpts, convOptsWithThriftBase *conv.O } // originalWrite ... -func (w *WriteHTTPRequest) originalWrite(ctx context.Context, out io.Writer, msg interface{}, requestBase *base.Base) error { +func (w *WriteHTTPRequest) originalWrite(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, requestBase *base.Base) error { req := msg.(*descriptor.HTTPRequest) if req.Body == nil && len(req.RawBody) != 0 { if err := customJson.Unmarshal(req.RawBody, &req.Body); err != nil { @@ -94,11 +94,11 @@ func (w *WriteHTTPRequest) originalWrite(ctx context.Context, out io.Writer, msg if !fn.HasRequestBase { requestBase = nil } - binaryWriter := thrift.NewBinaryWriter() - if err = wrapStructWriter(ctx, req, binaryWriter, fn.Request, &writerOption{requestBase: requestBase, binaryWithBase64: w.binaryWithBase64}); err != nil { + + if err = wrapStructWriter(ctx, req, bw, fn.Request, &writerOption{requestBase: requestBase, binaryWithBase64: w.binaryWithBase64}); err != nil { return err } - _, err = out.Write(binaryWriter.Bytes()) + _, err = out.Write(bw.Bytes()) return err } diff --git a/internal/generic/thrift/http_fallback.go b/internal/generic/thrift/http_fallback.go index 4fa510bbed..b3935f93e1 100644 --- a/internal/generic/thrift/http_fallback.go +++ b/internal/generic/thrift/http_fallback.go @@ -23,10 +23,11 @@ import ( "context" "io" + "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" ) // Write ... -func (w *WriteHTTPRequest) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { - return w.originalWrite(ctx, out, msg, requestBase) +func (w *WriteHTTPRequest) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { + return w.originalWrite(ctx, out, bw, msg, requestBase) } diff --git a/internal/generic/thrift/http_go116plus_amd64.go b/internal/generic/thrift/http_go116plus_amd64.go index c825890d84..305471e38f 100644 --- a/internal/generic/thrift/http_go116plus_amd64.go +++ b/internal/generic/thrift/http_go116plus_amd64.go @@ -36,10 +36,10 @@ import ( ) // Write ... -func (w *WriteHTTPRequest) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (w *WriteHTTPRequest) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { // fallback logic if !w.dynamicgoEnabled { - return w.originalWrite(ctx, out, msg, requestBase) + return w.originalWrite(ctx, out, bw, msg, requestBase) } // dynamicgo logic @@ -63,29 +63,27 @@ func (w *WriteHTTPRequest) Write(ctx context.Context, out io.Writer, msg interfa cv = j2t.NewBinaryConv(w.convOpts) } - binaryWriter := thrift.NewBinaryWriter() - ctx = context.WithValue(ctx, conv.CtxKeyHTTPRequest, req) body := req.GetBody() dbuf := mcache.Malloc(len(body))[0:0] defer mcache.Free(dbuf) for _, field := range dynamicgoTypeDsc.Struct().Fields() { - binaryWriter.WriteFieldBegin(thrift.TType(field.Type().Type()), int16(field.ID())) + bw.WriteFieldBegin(thrift.TType(field.Type().Type()), int16(field.ID())) // json []byte to thrift []byte if err := cv.DoInto(ctx, field.Type(), body, &dbuf); err != nil { return err } } - if _, err := out.Write(binaryWriter.Bytes()); err != nil { + if _, err := out.Write(bw.Bytes()); err != nil { return err } if _, err := out.Write(dbuf); err != nil { return err } - binaryWriter.Reset() - binaryWriter.WriteFieldStop() - _, err := out.Write(binaryWriter.Bytes()) + bw.Reset() + bw.WriteFieldStop() + _, err := out.Write(bw.Bytes()) return err } diff --git a/internal/generic/thrift/http_pb.go b/internal/generic/thrift/http_pb.go index 8e3e4c221c..409d87f8d7 100644 --- a/internal/generic/thrift/http_pb.go +++ b/internal/generic/thrift/http_pb.go @@ -55,7 +55,7 @@ func NewWriteHTTPPbRequest(svc *descriptor.ServiceDescriptor, pbSvc *desc.Servic } // Write ... -func (w *WriteHTTPPbRequest) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (w *WriteHTTPPbRequest) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { req := msg.(*descriptor.HTTPRequest) fn, err := w.svc.Router.Lookup(req) if err != nil { @@ -77,11 +77,10 @@ func (w *WriteHTTPPbRequest) Write(ctx context.Context, out io.Writer, msg inter } req.GeneralBody = pbMsg - binaryWriter := thrift.NewBinaryWriter() - if err = wrapStructWriter(ctx, req, binaryWriter, fn.Request, &writerOption{requestBase: requestBase}); err != nil { + if err = wrapStructWriter(ctx, req, bw, fn.Request, &writerOption{requestBase: requestBase}); err != nil { return err } - _, err = out.Write(binaryWriter.Bytes()) + _, err = out.Write(bw.Bytes()) return err } diff --git a/internal/generic/thrift/json.go b/internal/generic/thrift/json.go index d4eb7bf082..a1539c876d 100644 --- a/internal/generic/thrift/json.go +++ b/internal/generic/thrift/json.go @@ -83,7 +83,7 @@ func (m *WriteJSON) SetDynamicGo(convOpts, convOptsWithThriftBase *conv.Options) m.dynamicgoEnabled = true } -func (m *WriteJSON) originalWrite(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (m *WriteJSON) originalWrite(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { fnDsc, err := m.svcDsc.LookupFunctionByMethod(method) if err != nil { return fmt.Errorf("missing method: %s in service: %s", method, m.svcDsc.Name) @@ -98,14 +98,12 @@ func (m *WriteJSON) originalWrite(ctx context.Context, out io.Writer, msg interf requestBase = nil } - binaryWriter := thrift.NewBinaryWriter() - // msg is void or nil if _, ok := msg.(descriptor.Void); ok || msg == nil { - if err = wrapStructWriter(ctx, msg, binaryWriter, typeDsc, &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary}); err != nil { + if err = wrapStructWriter(ctx, msg, bw, typeDsc, &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary}); err != nil { return err } - _, err = out.Write(binaryWriter.Bytes()) + _, err = out.Write(bw.Bytes()) return err } @@ -125,10 +123,10 @@ func (m *WriteJSON) originalWrite(ctx context.Context, out io.Writer, msg interf Index: 0, } } - if err = wrapJSONWriter(ctx, &body, binaryWriter, typeDsc, &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary}); err != nil { + if err = wrapJSONWriter(ctx, &body, bw, typeDsc, &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary}); err != nil { return err } - _, err = out.Write(binaryWriter.Bytes()) + _, err = out.Write(bw.Bytes()) return err } diff --git a/internal/generic/thrift/json_fallback.go b/internal/generic/thrift/json_fallback.go index e1500fa853..7eac14253a 100644 --- a/internal/generic/thrift/json_fallback.go +++ b/internal/generic/thrift/json_fallback.go @@ -21,12 +21,13 @@ package thrift import ( "context" + "github.com/cloudwego/gopkg/protocol/thrift" "io" "github.com/cloudwego/gopkg/protocol/thrift/base" ) // Write write json string to out thrift.TProtocol -func (m *WriteJSON) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { - return m.originalWrite(ctx, out, msg, method, isClient, requestBase) +func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { + return m.originalWrite(ctx, out, bw, msg, method, isClient, requestBase) } diff --git a/internal/generic/thrift/json_go116plus_amd64.go b/internal/generic/thrift/json_go116plus_amd64.go index d321ea8afc..65914105b2 100644 --- a/internal/generic/thrift/json_go116plus_amd64.go +++ b/internal/generic/thrift/json_go116plus_amd64.go @@ -39,10 +39,10 @@ import ( ) // Write write json string to out thrift.TProtocol -func (m *WriteJSON) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { // fallback logic if !m.dynamicgoEnabled { - return m.originalWrite(ctx, out, msg, method, isClient, requestBase) + return m.originalWrite(ctx, out, bw, msg, method, isClient, requestBase) } // dynamicgo logic @@ -68,15 +68,13 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, msg interface{}, m cv = j2t.NewBinaryConv(m.convOpts) } - binaryWriter := thrift.NewBinaryWriter() - // msg is void or nil if _, ok := msg.(descriptor.Void); ok || msg == nil { - if err := m.writeFields(ctx, out, dynamicgoTypeDsc, nil, nil, isClient); err != nil { + if err := m.writeFields(ctx, out, bw, dynamicgoTypeDsc, nil, nil, isClient); err != nil { return err } - binaryWriter.WriteFieldStop() - _, err := out.Write(binaryWriter.Bytes()) + bw.WriteFieldStop() + _, err := out.Write(bw.Bytes()) return err } @@ -87,22 +85,20 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, msg interface{}, m } transBuff := utils.StringToSliceByte(s) - if err := m.writeFields(ctx, out, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { + if err := m.writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { return err } - binaryWriter.WriteFieldStop() - _, err := out.Write(binaryWriter.Bytes()) + bw.WriteFieldStop() + _, err := out.Write(bw.Bytes()) return err } type MsgType int -func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient bool) error { +func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient bool) error { dbuf := mcache.Malloc(len(transBuff))[0:0] defer mcache.Free(dbuf) - binaryWriter := thrift.NewBinaryWriter() - for _, field := range dynamicgoTypeDsc.Struct().Fields() { // Exception field if !isClient && field.ID() != 0 { @@ -111,11 +107,12 @@ func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, dynamicgoTyp continue } - binaryWriter.WriteFieldBegin(thrift.TType(field.Type().Type()), int16(field.ID())) + bw.WriteFieldBegin(thrift.TType(field.Type().Type()), int16(field.ID())) // if the field type is void, just write void and return if field.Type().Type() == dthrift.VOID { - binaryWriter.WriteFieldStop() - _, err := out.Write(binaryWriter.Bytes()) + bw.WriteFieldStop() + _, err := out.Write(bw.Bytes()) + bw.Reset() return err } else { // encode using dynamicgo @@ -125,9 +122,10 @@ func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, dynamicgoTyp } } } - if _, err := out.Write(binaryWriter.Bytes()); err != nil { + if _, err := out.Write(bw.Bytes()); err != nil { return err } + bw.Reset() _, err := out.Write(dbuf) return err } diff --git a/internal/generic/thrift/struct.go b/internal/generic/thrift/struct.go index eaea4bfe08..059870adc1 100644 --- a/internal/generic/thrift/struct.go +++ b/internal/generic/thrift/struct.go @@ -59,7 +59,7 @@ func (m *WriteStruct) SetBinaryWithBase64(enable bool) { } // Write ... -func (m *WriteStruct) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (m *WriteStruct) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { fnDsc, err := m.svcDsc.LookupFunctionByMethod(method) if err != nil { return err @@ -73,11 +73,10 @@ func (m *WriteStruct) Write(ctx context.Context, out io.Writer, msg interface{}, if !hasRequestBase { requestBase = nil } - binaryWriter := thrift.NewBinaryWriter() - if err = wrapStructWriter(ctx, msg, binaryWriter, ty, &writerOption{requestBase: requestBase, binaryWithBase64: m.binaryWithBase64}); err != nil { + if err = wrapStructWriter(ctx, msg, bw, ty, &writerOption{requestBase: requestBase, binaryWithBase64: m.binaryWithBase64}); err != nil { return err } - _, err = out.Write(binaryWriter.Bytes()) + _, err = out.Write(bw.Bytes()) return err } diff --git a/internal/generic/thrift/thrift.go b/internal/generic/thrift/thrift.go index 862691642c..5d49429f49 100644 --- a/internal/generic/thrift/thrift.go +++ b/internal/generic/thrift/thrift.go @@ -21,6 +21,7 @@ import ( "context" "io" + "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" ) @@ -35,5 +36,5 @@ type MessageReader interface { // MessageWriter write to thrift.TProtocol type MessageWriter interface { - Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error + Write(ctx context.Context, out io.Writer, w *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error } diff --git a/pkg/generic/generic_service.go b/pkg/generic/generic_service.go index dd6535550a..7b90899615 100644 --- a/pkg/generic/generic_service.go +++ b/pkg/generic/generic_service.go @@ -21,10 +21,11 @@ import ( "fmt" "io" + "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" "github.com/cloudwego/kitex/internal/generic/proto" - "github.com/cloudwego/kitex/internal/generic/thrift" + gthrift "github.com/cloudwego/kitex/internal/generic/thrift" codecProto "github.com/cloudwego/kitex/pkg/remote/codec/protobuf" "github.com/cloudwego/kitex/pkg/serviceinfo" ) @@ -143,12 +144,12 @@ func (g *Args) GetOrSetBase() interface{} { } // Write ... -func (g *Args) Write(ctx context.Context, method string, out io.Writer) error { +func (g *Args) Write(ctx context.Context, method string, bw *thrift.BinaryWriter, out io.Writer) error { if err, ok := g.inner.(error); ok { return err } - if w, ok := g.inner.(thrift.MessageWriter); ok { - return w.Write(ctx, out, g.Request, method, true, g.base) + if w, ok := g.inner.(gthrift.MessageWriter); ok { + return w.Write(ctx, out, bw, g.Request, method, true, g.base) } return fmt.Errorf("unexpected Args writer type: %T", g.inner) } @@ -168,7 +169,7 @@ func (g *Args) Read(ctx context.Context, method string, dataLen int, in io.Reade if err, ok := g.inner.(error); ok { return err } - if rw, ok := g.inner.(thrift.MessageReader); ok { + if rw, ok := g.inner.(gthrift.MessageReader); ok { g.Method = method var err error g.Request, err = rw.Read(ctx, method, false, dataLen, in) @@ -213,12 +214,12 @@ func (r *Result) SetCodec(inner interface{}) { } // Write ... -func (r *Result) Write(ctx context.Context, method string, out io.Writer) error { +func (r *Result) Write(ctx context.Context, method string, bw *thrift.BinaryWriter, out io.Writer) error { if err, ok := r.inner.(error); ok { return err } - if w, ok := r.inner.(thrift.MessageWriter); ok { - return w.Write(ctx, out, r.Success, method, false, nil) + if w, ok := r.inner.(gthrift.MessageWriter); ok { + return w.Write(ctx, out, bw, r.Success, method, false, nil) } return fmt.Errorf("unexpected Result writer type: %T", r.inner) } @@ -238,7 +239,7 @@ func (r *Result) Read(ctx context.Context, method string, dataLen int, in io.Rea if err, ok := r.inner.(error); ok { return err } - if w, ok := r.inner.(thrift.MessageReader); ok { + if w, ok := r.inner.(gthrift.MessageReader); ok { var err error r.Success, err = w.Read(ctx, method, true, dataLen, in) return err diff --git a/pkg/generic/generic_service_test.go b/pkg/generic/generic_service_test.go index cc9bdb69d6..cc77ed05c2 100644 --- a/pkg/generic/generic_service_test.go +++ b/pkg/generic/generic_service_test.go @@ -22,6 +22,7 @@ import ( "strings" "testing" + "github.com/cloudwego/gopkg/protocol/thrift" gbase "github.com/cloudwego/gopkg/protocol/thrift/base" "github.com/golang/mock/gomock" @@ -54,14 +55,14 @@ func TestGenericService(t *testing.T) { test.Assert(t, base != nil) a.SetCodec(struct{}{}) // write not ok - err := a.Write(ctx, method, buffer) + err := a.Write(ctx, method, thrift.NewBinaryWriter(), buffer) test.Assert(t, err.Error() == "unexpected Args writer type: struct {}") // Write expect - argWriteInner.EXPECT().Write(ctx, buffer, a.Request, a.GetOrSetBase()).Return(nil) + argWriteInner.EXPECT().Write(ctx, buffer, thrift.NewBinaryWriter(), a.Request, a.GetOrSetBase()).Return(nil) a.SetCodec(argWriteInner) // write ok - err = a.Write(ctx, method, buffer) + err = a.Write(ctx, method, thrift.NewBinaryWriter(), buffer) test.Assert(t, err == nil, err) // read not ok err = a.Read(ctx, method, 0, buffer) @@ -77,13 +78,13 @@ func TestGenericService(t *testing.T) { test.Assert(t, ok == true) // write not ok - err = r.Write(ctx, method, buffer) + err = r.Write(ctx, method, thrift.NewBinaryWriter(), buffer) test.Assert(t, err.Error() == "unexpected Result writer type: ") // Write expect - resultWriteInner.EXPECT().Write(ctx, buffer, r.Success, (*gbase.Base)(nil)).Return(nil).AnyTimes() + resultWriteInner.EXPECT().Write(ctx, buffer, thrift.NewBinaryWriter(), r.Success, (*gbase.Base)(nil)).Return(nil).AnyTimes() r.SetCodec(resultWriteInner) // write ok - err = r.Write(ctx, method, buffer) + err = r.Write(ctx, method, thrift.NewBinaryWriter(), buffer) test.Assert(t, err == nil) // read not ok err = r.Read(ctx, method, 0, buffer) diff --git a/pkg/remote/codec/thrift/thrift.go b/pkg/remote/codec/thrift/thrift.go index e7a9fed13f..d0231d3ec9 100644 --- a/pkg/remote/codec/thrift/thrift.go +++ b/pkg/remote/codec/thrift/thrift.go @@ -193,7 +193,7 @@ func encodeGenericThrift(out remote.ByteBuffer, ctx context.Context, method stri if _, err := out.Write(binaryWriter.Bytes()); err != nil { return perrors.NewProtocolErrorWithErrMsg(err, fmt.Sprintf("thrift marshal, Write failed: %s", err.Error())) } - if err := msg.Write(ctx, method, out); err != nil { + if err := msg.Write(ctx, method, thrift.NewBinaryWriter(), out); err != nil { return perrors.NewProtocolErrorWithErrMsg(err, fmt.Sprintf("thrift marshal, Write failed: %s", err.Error())) } return nil @@ -291,11 +291,11 @@ func (c thriftCodec) Name() string { } type genericWriter interface { // used by pkg/generic - Write(ctx context.Context, method string, w io.Writer) error + Write(ctx context.Context, method string, w *thrift.BinaryWriter, out io.Writer) error } type genericReader interface { // used by pkg/generic - Read(ctx context.Context, method string, dataLen int, r io.Reader) error + Read(ctx context.Context, method string, dataLen int, in io.Reader) error } // ThriftMsgFastCodec ... From f5879ef7622ba8045173efff8d9541ed2c90229f Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 29 Jul 2024 16:36:55 +0800 Subject: [PATCH 11/20] feat: support json thrift generic streaming writer reader --- internal/generic/thrift/json.go | 90 +++++++++++++++++-- .../generic/thrift/json_go116plus_amd64.go | 29 ++++-- .../grpcjsonthrift_test/generic_test.go | 6 +- pkg/remote/codec/grpc/grpc.go | 32 ++++++- pkg/remote/codec/thrift/thrift_test.go | 9 +- 5 files changed, 145 insertions(+), 21 deletions(-) diff --git a/internal/generic/thrift/json.go b/internal/generic/thrift/json.go index a1539c876d..9e85b2db63 100644 --- a/internal/generic/thrift/json.go +++ b/internal/generic/thrift/json.go @@ -23,6 +23,7 @@ import ( "strconv" "github.com/bytedance/gopkg/lang/dirtmake" + "github.com/bytedance/sonic" "github.com/cloudwego/dynamicgo/conv" "github.com/cloudwego/dynamicgo/conv/t2j" dthrift "github.com/cloudwego/dynamicgo/thrift" @@ -34,6 +35,7 @@ import ( "github.com/cloudwego/kitex/pkg/generic/descriptor" "github.com/cloudwego/kitex/pkg/remote" "github.com/cloudwego/kitex/pkg/remote/codec/perrors" + "github.com/cloudwego/kitex/pkg/serviceinfo" "github.com/cloudwego/kitex/pkg/utils" ) @@ -123,9 +125,20 @@ func (m *WriteJSON) originalWrite(ctx context.Context, out io.Writer, bw *thrift Index: 0, } } + + opt := &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary} + if isStreaming(fnDsc.StreamingMode) { + // unwrap one struct layer + typeDsc = typeDsc.Struct.FieldsByID[int32(getStreamingFieldID(isClient, true))].Type + return writeStreamingContent(ctx, &body, typeDsc, opt, bw) + } + if err = wrapJSONWriter(ctx, &body, bw, typeDsc, &writerOption{requestBase: requestBase, binaryWithBase64: m.base64Binary}); err != nil { return err } + if _, isGRPC := out.(remote.FrameWrite); isGRPC { + return nil + } _, err = out.Write(bw.Bytes()) return err } @@ -185,23 +198,42 @@ func (m *ReadJSON) Read(ctx context.Context, method string, isClient bool, dataL tyDsc = fnDsc.Request() } + _, isGRPC := buffer.(remote.FrameWrite) + var resp interface{} + var err error if tyDsc.Struct().Fields()[0].Type().Type() == dthrift.VOID { - if _, err := buffer.ReadBinary(voidWholeLen); err != nil { + if isGRPC { + _, err = buffer.Next(voidWholeLen) + } else { + _, err = buffer.ReadBinary(voidWholeLen) + } + if err != nil { return nil, err } resp = descriptor.Void{} } else { - transBuff, err := buffer.ReadBinary(dataLen) + var transBuff []byte + if isGRPC { + transBuff, err = buffer.Next(dataLen) + } else { + transBuff, err = buffer.ReadBinary(dataLen) + } if err != nil { return nil, err } + isStream := isStreaming(m.svc.Functions[method].StreamingMode) + if isStream { + // unwrap one struct layer + tyDsc = tyDsc.Struct().FieldById(dthrift.FieldID(getStreamingFieldID(isClient, false))).Type() + } + // json size is usually 2 times larger than equivalent thrift data buf := dirtmake.Bytes(0, len(transBuff)*2) // thrift []byte to json []byte var t2jBinaryConv t2j.BinaryConv - if isClient { + if isClient && !isStream { t2jBinaryConv = t2j.NewBinaryConv(m.convOptsWithException) } else { t2jBinaryConv = t2j.NewBinaryConv(m.convOpts) @@ -209,9 +241,11 @@ func (m *ReadJSON) Read(ctx context.Context, method string, isClient bool, dataL if err := t2jBinaryConv.DoInto(ctx, tyDsc, transBuff, &buf); err != nil { return nil, err } - buf = removePrefixAndSuffix(buf) + if !isStream { + buf = removePrefixAndSuffix(buf) + } resp = utils.SliceByteToString(buf) - if tyDsc.Struct().Fields()[0].Type().Type() == dthrift.STRING { + if !isStream && tyDsc.Struct().Fields()[0].Type().Type() == dthrift.STRING { strresp := resp.(string) resp, err = strconv.Unquote(strresp) if err != nil { @@ -223,7 +257,7 @@ func (m *ReadJSON) Read(ctx context.Context, method string, isClient bool, dataL return resp, nil } -func (m *ReadJSON) originalRead(ctx context.Context, method string, isClient bool, in *thrift.BinaryReader) (interface{}, error) { +func (m *ReadJSON) originalRead(ctx context.Context, method string, isClient bool, br *thrift.BinaryReader) (interface{}, error) { fnDsc, err := m.svc.LookupFunctionByMethod(method) if err != nil { return nil, err @@ -232,7 +266,14 @@ func (m *ReadJSON) originalRead(ctx context.Context, method string, isClient boo if !isClient { fDsc = fnDsc.Request } - resp, err := skipStructReader(ctx, in, fDsc, &readerOption{forJSON: true, throwException: true, binaryWithBase64: m.binaryWithBase64}) + + if isStreaming(fnDsc.StreamingMode) { + // unwrap one struct layer + fDsc = fDsc.Struct.FieldsByID[int32(getStreamingFieldID(isClient, false))].Type + return readStreamingContent(ctx, fDsc, &readerOption{forJSON: true, binaryWithBase64: m.binaryWithBase64}, br) + } + + resp, err := skipStructReader(ctx, br, fDsc, &readerOption{forJSON: true, throwException: true, binaryWithBase64: m.binaryWithBase64}) if err != nil { return nil, err } @@ -263,3 +304,38 @@ func removePrefixAndSuffix(buf []byte) []byte { } return buf } + +func isStreaming(streamingMode serviceinfo.StreamingMode) bool { + return streamingMode != serviceinfo.StreamingUnary && streamingMode != serviceinfo.StreamingNone +} + +func getStreamingFieldID(isClient, isWrite bool) int { + var streamingFieldID int + if (isWrite && isClient) || (!isWrite && !isClient) { + streamingFieldID = 1 + } + return streamingFieldID +} + +func writeStreamingContent(ctx context.Context, body *gjson.Result, typeDsc *descriptor.TypeDescriptor, opt *writerOption, bw *thrift.BinaryWriter) error { + val, writer, err := nextJSONWriter(body, typeDsc, opt) + if err != nil { + return fmt.Errorf("nextWriter of field[%s] error %w", typeDsc.Name, err) + } + if err = writer(ctx, val, bw, typeDsc, opt); err != nil { + return fmt.Errorf("writer of field[%s] error %w", typeDsc.Name, err) + } + return nil +} + +func readStreamingContent(ctx context.Context, typeDesc *descriptor.TypeDescriptor, opt *readerOption, br *thrift.BinaryReader) (v interface{}, err error) { + resp, err := readStruct(ctx, br, typeDesc, opt) + if err != nil { + return nil, err + } + respNode, err := sonic.Marshal(resp) + if err != nil { + return nil, perrors.NewProtocolErrorWithType(perrors.InvalidData, fmt.Sprintf("streaming response marshal failed. err:%#v", err)) + } + return string(respNode), nil +} diff --git a/internal/generic/thrift/json_go116plus_amd64.go b/internal/generic/thrift/json_go116plus_amd64.go index 65914105b2..b0e84d91aa 100644 --- a/internal/generic/thrift/json_go116plus_amd64.go +++ b/internal/generic/thrift/json_go116plus_amd64.go @@ -70,7 +70,7 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW // msg is void or nil if _, ok := msg.(descriptor.Void); ok || msg == nil { - if err := m.writeFields(ctx, out, bw, dynamicgoTypeDsc, nil, nil, isClient); err != nil { + if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, nil, nil, isClient); err != nil { return err } bw.WriteFieldStop() @@ -85,17 +85,23 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW } transBuff := utils.StringToSliceByte(s) - if err := m.writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { + if isStreaming(m.svcDsc.Functions[method].StreamingMode) { + // unwrap one struct layer + dynamicgoTypeDsc = dynamicgoTypeDsc.Struct().FieldById(dthrift.FieldID(getStreamingFieldID(isClient, true))).Type() + return writeStreamingContentWithDynamicgo(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff) + } else { + if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { + return err + } + bw.WriteFieldStop() + _, err := out.Write(bw.Bytes()) return err } - bw.WriteFieldStop() - _, err := out.Write(bw.Bytes()) - return err } type MsgType int -func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient bool) error { +func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient bool) error { dbuf := mcache.Malloc(len(transBuff))[0:0] defer mcache.Free(dbuf) @@ -129,3 +135,14 @@ func (m *WriteJSON) writeFields(ctx context.Context, out io.Writer, bw *thrift.B _, err := out.Write(dbuf) return err } + +func writeStreamingContentWithDynamicgo(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte) error { + dbuf := mcache.Malloc(len(transBuff))[0:0] + defer mcache.Free(dbuf) + + if err := cv.DoInto(ctx, dynamicgoTypeDsc, transBuff, &dbuf); err != nil { + return err + } + _, err := out.Write(dbuf) + return err +} diff --git a/pkg/generic/grpcjsonthrift_test/generic_test.go b/pkg/generic/grpcjsonthrift_test/generic_test.go index ca9e2808fe..b2ce5053a6 100644 --- a/pkg/generic/grpcjsonthrift_test/generic_test.go +++ b/pkg/generic/grpcjsonthrift_test/generic_test.go @@ -201,7 +201,7 @@ func testServerStreaming(t *testing.T, ctx context.Context, cli genericclient.Cl for { resp, err := streamCli.Recv() if err != nil { - test.Assert(t, err == io.EOF) + test.Assert(t, err == io.EOF, err) fmt.Println("serverStreaming message receive done") break } else { @@ -237,7 +237,7 @@ func testBidirectionalStreaming(t *testing.T, ctx context.Context, cli genericcl for { resp, err := streamCli.Recv() if err != nil { - test.Assert(t, err == io.EOF) + test.Assert(t, err == io.EOF, err) fmt.Println("bidirectionalStreaming message receive done") break } else { @@ -254,7 +254,7 @@ func testBidirectionalStreaming(t *testing.T, ctx context.Context, cli genericcl func testUnary(t *testing.T, ctx context.Context, cli genericclient.Client) { resp, err := cli.GenericCall(ctx, "EchoUnary", `{"message": "unary request"}`) - test.Assert(t, err == nil) + test.Assert(t, err == nil, err) strResp, ok := resp.(string) test.Assert(t, ok) test.Assert(t, reflect.DeepEqual(gjson.Get(strResp, "message").String(), "hello unary request")) diff --git a/pkg/remote/codec/grpc/grpc.go b/pkg/remote/codec/grpc/grpc.go index 5cbc94fc2a..1bbb7272b5 100644 --- a/pkg/remote/codec/grpc/grpc.go +++ b/pkg/remote/codec/grpc/grpc.go @@ -21,8 +21,10 @@ import ( "encoding/binary" "errors" "fmt" + "io" "github.com/cloudwego/fastpb" + gpkgthrift "github.com/cloudwego/gopkg/protocol/thrift" "google.golang.org/protobuf/proto" "github.com/cloudwego/kitex/internal/utils/safemcache" @@ -100,7 +102,20 @@ func (c *grpcCodec) Encode(ctx context.Context, message remote.Message, out remo switch message.ProtocolInfo().CodecType { case serviceinfo.Thrift: - payload, err = thrift.MarshalThriftData(ctx, c.ThriftCodec, message.Data()) + switch msg := message.Data().(type) { + case genericWriter: + methodName := message.RPCInfo().Invocation().MethodName() + if methodName == "" { + return errors.New("empty methodName in grpc generic streaming Encode") + } + bw := gpkgthrift.NewBinaryWriter() + if err := msg.Write(ctx, methodName, bw, out); err != nil { + return perrors.NewProtocolErrorWithErrMsg(err, fmt.Sprintf("generic thrift streaming marshal, Write failed: %s", err.Error())) + } + payload = bw.Bytes() + default: + payload, err = thrift.MarshalThriftData(ctx, c.ThriftCodec, message.Data()) + } case serviceinfo.Protobuf: switch t := message.Data().(type) { case fastpb.Writer: @@ -187,6 +202,13 @@ func (c *grpcCodec) Decode(ctx context.Context, message remote.Message, in remot data := message.Data() switch message.ProtocolInfo().CodecType { case serviceinfo.Thrift: + if t, ok := data.(genericReader); ok { + methodName := message.RPCInfo().Invocation().MethodName() + if methodName == "" { + return errors.New("empty methodName in grpc Decode") + } + return t.Read(ctx, methodName, len(d), remote.NewReaderBuffer(d)) + } return thrift.UnmarshalThriftData(ctx, c.ThriftCodec, "", d, message.Data()) case serviceinfo.Protobuf: if t, ok := data.(fastpb.Reader); ok { @@ -224,3 +246,11 @@ func (c *grpcCodec) Decode(ctx context.Context, message remote.Message, in remot func (c *grpcCodec) Name() string { return "grpc" } + +type genericWriter interface { // used by pkg/generic + Write(ctx context.Context, method string, bw *gpkgthrift.BinaryWriter, out io.Writer) error +} + +type genericReader interface { // used by pkg/generic + Read(ctx context.Context, method string, dataLen int, in io.Reader) error +} diff --git a/pkg/remote/codec/thrift/thrift_test.go b/pkg/remote/codec/thrift/thrift_test.go index 12308545fa..05e8780d75 100644 --- a/pkg/remote/codec/thrift/thrift_test.go +++ b/pkg/remote/codec/thrift/thrift_test.go @@ -19,6 +19,7 @@ package thrift import ( "context" "errors" + "github.com/cloudwego/gopkg/protocol/thrift" "io" "testing" @@ -65,7 +66,7 @@ func init() { type mockWithContext struct { ReadFunc func(ctx context.Context, method string, dataLen int, oprot io.Reader) error - WriteFunc func(ctx context.Context, method string, oprot io.Writer) error + WriteFunc func(ctx context.Context, method string, writer *thrift.BinaryWriter, oprot io.Writer) error } func (m *mockWithContext) Read(ctx context.Context, method string, dataLen int, oprot io.Reader) error { @@ -75,9 +76,9 @@ func (m *mockWithContext) Read(ctx context.Context, method string, dataLen int, return nil } -func (m *mockWithContext) Write(ctx context.Context, method string, oprot io.Writer) error { +func (m *mockWithContext) Write(ctx context.Context, method string, writer *thrift.BinaryWriter, oprot io.Writer) error { if m.WriteFunc != nil { - return m.WriteFunc(ctx, method, oprot) + return m.WriteFunc(ctx, method, writer, oprot) } return nil } @@ -87,7 +88,7 @@ func TestWithContext(t *testing.T) { t.Run(tb.Name, func(t *testing.T) { ctx := context.Background() - req := &mockWithContext{WriteFunc: func(ctx context.Context, method string, oprot io.Writer) error { + req := &mockWithContext{WriteFunc: func(ctx context.Context, method string, writer *thrift.BinaryWriter, oprot io.Writer) error { return nil }} ink := rpcinfo.NewInvocation("", "mock") From 945e904f8e9bf0a572bf2dc2b8ab5fd5205df401 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Tue, 30 Jul 2024 17:05:36 +0800 Subject: [PATCH 12/20] fix: bug --- pkg/generic/thrift/base.go | 22 ++++++++++------------ pkg/remote/codec/thrift/thrift_test.go | 1 - 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pkg/generic/thrift/base.go b/pkg/generic/thrift/base.go index 07fd7ac002..12144bdb0c 100644 --- a/pkg/generic/thrift/base.go +++ b/pkg/generic/thrift/base.go @@ -20,8 +20,6 @@ import ( "fmt" "github.com/cloudwego/gopkg/protocol/thrift" - - "github.com/cloudwego/kitex/pkg/protocol/bthrift" ) type TrafficEnv struct { @@ -101,11 +99,11 @@ func (p *TrafficEnv) Read(iprot *thrift.BinaryReader) (err error) { return nil ReadFieldBeginError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) ReadFieldError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TrafficEnv[fieldId]), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TrafficEnv[fieldId]), err) SkipFieldError: - return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) + return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) } func (p *TrafficEnv) ReadField1(iprot *thrift.BinaryReader) error { @@ -333,11 +331,11 @@ func (p *Base) Read(iprot *thrift.BinaryReader) (err error) { return nil ReadFieldBeginError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) ReadFieldError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Base[fieldId]), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Base[fieldId]), err) SkipFieldError: - return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) + return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) } func (p *Base) ReadField1(iprot *thrift.BinaryReader) error { @@ -442,7 +440,7 @@ func (p *Base) Write(oprot *thrift.BinaryWriter) (err error) { oprot.WriteFieldStop() return nil WriteFieldError: - return bthrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err) + return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err) } func (p *Base) writeField1(oprot *thrift.BinaryWriter) (err error) { @@ -605,11 +603,11 @@ func (p *BaseResp) Read(iprot *thrift.BinaryReader) (err error) { return nil ReadFieldBeginError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) ReadFieldError: - return bthrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_BaseResp[fieldId]), err) + return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_BaseResp[fieldId]), err) SkipFieldError: - return bthrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) + return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) } func (p *BaseResp) ReadField1(iprot *thrift.BinaryReader) error { diff --git a/pkg/remote/codec/thrift/thrift_test.go b/pkg/remote/codec/thrift/thrift_test.go index 05e8780d75..1961651d7d 100644 --- a/pkg/remote/codec/thrift/thrift_test.go +++ b/pkg/remote/codec/thrift/thrift_test.go @@ -19,7 +19,6 @@ package thrift import ( "context" "errors" - "github.com/cloudwego/gopkg/protocol/thrift" "io" "testing" From 07cef5a00d32bc4c560a5e0581dd20a00466848d Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Wed, 31 Jul 2024 11:30:40 +0800 Subject: [PATCH 13/20] chore: no need base.go --- pkg/generic/thrift/base.go | 693 ------------------------------------- 1 file changed, 693 deletions(-) delete mode 100644 pkg/generic/thrift/base.go diff --git a/pkg/generic/thrift/base.go b/pkg/generic/thrift/base.go deleted file mode 100644 index 12144bdb0c..0000000000 --- a/pkg/generic/thrift/base.go +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright 2021 CloudWeGo Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package thrift - -import ( - "fmt" - - "github.com/cloudwego/gopkg/protocol/thrift" -) - -type TrafficEnv struct { - Open bool `thrift:"Open,1" json:"Open"` - - Env string `thrift:"Env,2" json:"Env"` -} - -func NewTrafficEnv() *TrafficEnv { - return &TrafficEnv{ - Open: false, - Env: "", - } -} - -func (p *TrafficEnv) GetOpen() bool { - return p.Open -} - -func (p *TrafficEnv) GetEnv() string { - return p.Env -} - -func (p *TrafficEnv) SetOpen(val bool) { - p.Open = val -} - -func (p *TrafficEnv) SetEnv(val string) { - p.Env = val -} - -var fieldIDToName_TrafficEnv = map[int16]string{ - 1: "Open", - 2: "Env", -} - -func (p *TrafficEnv) Read(iprot *thrift.BinaryReader) (err error) { - var fieldTypeId thrift.TType - var fieldId int16 - - for { - fieldTypeId, fieldId, err = iprot.ReadFieldBegin() - if err != nil { - goto ReadFieldBeginError - } - if fieldTypeId == thrift.STOP { - break - } - - switch fieldId { - case 1: - if fieldTypeId == thrift.BOOL { - if err = p.ReadField1(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 2: - if fieldTypeId == thrift.STRING { - if err = p.ReadField2(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - default: - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - } - - return nil -ReadFieldBeginError: - return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) -ReadFieldError: - return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TrafficEnv[fieldId]), err) -SkipFieldError: - return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) -} - -func (p *TrafficEnv) ReadField1(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadBool(); err != nil { - return err - } else { - p.Open = v - } - return nil -} - -func (p *TrafficEnv) ReadField2(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.Env = v - } - return nil -} - -func (p *TrafficEnv) Write(oprot *thrift.BinaryWriter) (err error) { - if p != nil { - p.writeField1(oprot) - p.writeField2(oprot) - } - oprot.WriteFieldStop() - return nil -} - -func (p *TrafficEnv) writeField1(oprot *thrift.BinaryWriter) { - oprot.WriteFieldBegin(thrift.BOOL, 1) - oprot.WriteBool(p.Open) -} - -func (p *TrafficEnv) writeField2(oprot *thrift.BinaryWriter) { - oprot.WriteFieldBegin(thrift.STRING, 2) - oprot.WriteString(p.Env) -} - -func (p *TrafficEnv) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("TrafficEnv(%+v)", *p) -} - -type Base struct { - LogID string `thrift:"LogID,1" json:"LogID"` - - Caller string `thrift:"Caller,2" json:"Caller"` - - Addr string `thrift:"Addr,3" json:"Addr"` - - Client string `thrift:"Client,4" json:"Client"` - - TrafficEnv *TrafficEnv `thrift:"TrafficEnv,5" json:"TrafficEnv,omitempty"` - - Extra map[string]string `thrift:"Extra,6" json:"Extra,omitempty"` -} - -func NewBase() *Base { - return &Base{ - LogID: "", - Caller: "", - Addr: "", - Client: "", - } -} - -func (p *Base) GetLogID() string { - return p.LogID -} - -func (p *Base) GetCaller() string { - return p.Caller -} - -func (p *Base) GetAddr() string { - return p.Addr -} - -func (p *Base) GetClient() string { - return p.Client -} - -var Base_TrafficEnv_DEFAULT *TrafficEnv - -func (p *Base) GetTrafficEnv() *TrafficEnv { - if !p.IsSetTrafficEnv() { - return Base_TrafficEnv_DEFAULT - } - return p.TrafficEnv -} - -var Base_Extra_DEFAULT map[string]string - -func (p *Base) GetExtra() map[string]string { - if !p.IsSetExtra() { - return Base_Extra_DEFAULT - } - return p.Extra -} - -func (p *Base) SetLogID(val string) { - p.LogID = val -} - -func (p *Base) SetCaller(val string) { - p.Caller = val -} - -func (p *Base) SetAddr(val string) { - p.Addr = val -} - -func (p *Base) SetClient(val string) { - p.Client = val -} - -func (p *Base) SetTrafficEnv(val *TrafficEnv) { - p.TrafficEnv = val -} - -func (p *Base) SetExtra(val map[string]string) { - p.Extra = val -} - -var fieldIDToName_Base = map[int16]string{ - 1: "LogID", - 2: "Caller", - 3: "Addr", - 4: "Client", - 5: "TrafficEnv", - 6: "Extra", -} - -func (p *Base) IsSetTrafficEnv() bool { - return p.TrafficEnv != nil -} - -func (p *Base) IsSetExtra() bool { - return p.Extra != nil -} - -func (p *Base) Read(iprot *thrift.BinaryReader) (err error) { - var fieldTypeId thrift.TType - var fieldId int16 - - for { - fieldTypeId, fieldId, err = iprot.ReadFieldBegin() - if err != nil { - goto ReadFieldBeginError - } - if fieldTypeId == thrift.STOP { - break - } - - switch fieldId { - case 1: - if fieldTypeId == thrift.STRING { - if err = p.ReadField1(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 2: - if fieldTypeId == thrift.STRING { - if err = p.ReadField2(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 3: - if fieldTypeId == thrift.STRING { - if err = p.ReadField3(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 4: - if fieldTypeId == thrift.STRING { - if err = p.ReadField4(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 5: - if fieldTypeId == thrift.STRUCT { - if err = p.ReadField5(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 6: - if fieldTypeId == thrift.MAP { - if err = p.ReadField6(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - default: - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - } - - return nil -ReadFieldBeginError: - return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) -ReadFieldError: - return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Base[fieldId]), err) -SkipFieldError: - return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) -} - -func (p *Base) ReadField1(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.LogID = v - } - return nil -} - -func (p *Base) ReadField2(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.Caller = v - } - return nil -} - -func (p *Base) ReadField3(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.Addr = v - } - return nil -} - -func (p *Base) ReadField4(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.Client = v - } - return nil -} - -func (p *Base) ReadField5(iprot *thrift.BinaryReader) error { - p.TrafficEnv = NewTrafficEnv() - if err := p.TrafficEnv.Read(iprot); err != nil { - return err - } - return nil -} - -func (p *Base) ReadField6(iprot *thrift.BinaryReader) error { - _, _, size, err := iprot.ReadMapBegin() - if err != nil { - return err - } - p.Extra = make(map[string]string, size) - for i := 0; i < size; i++ { - var _key string - if v, err := iprot.ReadString(); err != nil { - return err - } else { - _key = v - } - - var _val string - if v, err := iprot.ReadString(); err != nil { - return err - } else { - _val = v - } - - p.Extra[_key] = _val - } - return nil -} - -func (p *Base) Write(oprot *thrift.BinaryWriter) (err error) { - var fieldId int16 - if p != nil { - if err = p.writeField1(oprot); err != nil { - fieldId = 1 - goto WriteFieldError - } - if err = p.writeField2(oprot); err != nil { - fieldId = 2 - goto WriteFieldError - } - if err = p.writeField3(oprot); err != nil { - fieldId = 3 - goto WriteFieldError - } - if err = p.writeField4(oprot); err != nil { - fieldId = 4 - goto WriteFieldError - } - if err = p.writeField5(oprot); err != nil { - fieldId = 5 - goto WriteFieldError - } - if err = p.writeField6(oprot); err != nil { - fieldId = 6 - goto WriteFieldError - } - - } - oprot.WriteFieldStop() - return nil -WriteFieldError: - return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err) -} - -func (p *Base) writeField1(oprot *thrift.BinaryWriter) (err error) { - oprot.WriteFieldBegin(thrift.STRING, 1) - oprot.WriteString(p.LogID) - return nil -} - -func (p *Base) writeField2(oprot *thrift.BinaryWriter) (err error) { - oprot.WriteFieldBegin(thrift.STRING, 2) - oprot.WriteString(p.Caller) - return nil -} - -func (p *Base) writeField3(oprot *thrift.BinaryWriter) (err error) { - oprot.WriteFieldBegin(thrift.STRING, 3) - oprot.WriteString(p.Addr) - return nil -} - -func (p *Base) writeField4(oprot *thrift.BinaryWriter) (err error) { - oprot.WriteFieldBegin(thrift.STRING, 4) - oprot.WriteString(p.Client) - return nil -} - -func (p *Base) writeField5(oprot *thrift.BinaryWriter) (err error) { - if p.IsSetTrafficEnv() { - oprot.WriteFieldBegin(thrift.STRUCT, 5) - if err = p.TrafficEnv.Write(oprot); err != nil { - return err - } - } - return nil -} - -func (p *Base) writeField6(oprot *thrift.BinaryWriter) (err error) { - if p.IsSetExtra() { - oprot.WriteFieldBegin(thrift.MAP, 6) - oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)) - for k, v := range p.Extra { - oprot.WriteString(k) - oprot.WriteString(v) - } - } - return nil -} - -func (p *Base) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("Base(%+v)", *p) -} - -type BaseResp struct { - StatusMessage string `thrift:"StatusMessage,1" json:"StatusMessage"` - - StatusCode int32 `thrift:"StatusCode,2" json:"StatusCode"` - - Extra map[string]string `thrift:"Extra,3" json:"Extra,omitempty"` -} - -func NewBaseResp() *BaseResp { - return &BaseResp{ - StatusMessage: "", - StatusCode: 0, - } -} - -func (p *BaseResp) GetStatusMessage() string { - return p.StatusMessage -} - -func (p *BaseResp) GetStatusCode() int32 { - return p.StatusCode -} - -var BaseResp_Extra_DEFAULT map[string]string - -func (p *BaseResp) GetExtra() map[string]string { - if !p.IsSetExtra() { - return BaseResp_Extra_DEFAULT - } - return p.Extra -} - -func (p *BaseResp) SetStatusMessage(val string) { - p.StatusMessage = val -} - -func (p *BaseResp) SetStatusCode(val int32) { - p.StatusCode = val -} - -func (p *BaseResp) SetExtra(val map[string]string) { - p.Extra = val -} - -var fieldIDToName_BaseResp = map[int16]string{ - 1: "StatusMessage", - 2: "StatusCode", - 3: "Extra", -} - -func (p *BaseResp) IsSetExtra() bool { - return p.Extra != nil -} - -func (p *BaseResp) Read(iprot *thrift.BinaryReader) (err error) { - var fieldTypeId thrift.TType - var fieldId int16 - - for { - fieldTypeId, fieldId, err = iprot.ReadFieldBegin() - if err != nil { - goto ReadFieldBeginError - } - if fieldTypeId == thrift.STOP { - break - } - - switch fieldId { - case 1: - if fieldTypeId == thrift.STRING { - if err = p.ReadField1(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 2: - if fieldTypeId == thrift.I32 { - if err = p.ReadField2(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - case 3: - if fieldTypeId == thrift.MAP { - if err = p.ReadField3(iprot); err != nil { - goto ReadFieldError - } - } else { - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - default: - if err = iprot.Skip(fieldTypeId); err != nil { - goto SkipFieldError - } - } - } - - return nil -ReadFieldBeginError: - return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err) -ReadFieldError: - return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_BaseResp[fieldId]), err) -SkipFieldError: - return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err) -} - -func (p *BaseResp) ReadField1(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadString(); err != nil { - return err - } else { - p.StatusMessage = v - } - return nil -} - -func (p *BaseResp) ReadField2(iprot *thrift.BinaryReader) error { - if v, err := iprot.ReadI32(); err != nil { - return err - } else { - p.StatusCode = v - } - return nil -} - -func (p *BaseResp) ReadField3(iprot *thrift.BinaryReader) error { - _, _, size, err := iprot.ReadMapBegin() - if err != nil { - return err - } - p.Extra = make(map[string]string, size) - for i := 0; i < size; i++ { - var _key string - if v, err := iprot.ReadString(); err != nil { - return err - } else { - _key = v - } - - var _val string - if v, err := iprot.ReadString(); err != nil { - return err - } else { - _val = v - } - - p.Extra[_key] = _val - } - return nil -} - -func (p *BaseResp) Write(oprot *thrift.BinaryWriter) (err error) { - if p != nil { - p.writeField1(oprot) - p.writeField2(oprot) - p.writeField3(oprot) - } - oprot.WriteFieldStop() - return nil -} - -func (p *BaseResp) writeField1(oprot *thrift.BinaryWriter) { - oprot.WriteFieldBegin(thrift.STRING, 1) - oprot.WriteString(p.StatusMessage) -} - -func (p *BaseResp) writeField2(oprot *thrift.BinaryWriter) { - oprot.WriteFieldBegin(thrift.I32, 2) - oprot.WriteI32(p.StatusCode) -} - -func (p *BaseResp) writeField3(oprot *thrift.BinaryWriter) { - if p.IsSetExtra() { - oprot.WriteFieldBegin(thrift.MAP, 3) - oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)) - for k, v := range p.Extra { - oprot.WriteString(k) - oprot.WriteString(v) - } - } -} - -func (p *BaseResp) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("BaseResp(%+v)", *p) -} From 5d38a8490454a49fd4fda332d4e188cf0ac67b22 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Wed, 31 Jul 2024 11:41:05 +0800 Subject: [PATCH 14/20] fix: http2 write --- internal/generic/thrift/json_go116plus_amd64.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/generic/thrift/json_go116plus_amd64.go b/internal/generic/thrift/json_go116plus_amd64.go index b0e84d91aa..42d337432d 100644 --- a/internal/generic/thrift/json_go116plus_amd64.go +++ b/internal/generic/thrift/json_go116plus_amd64.go @@ -88,7 +88,7 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW if isStreaming(m.svcDsc.Functions[method].StreamingMode) { // unwrap one struct layer dynamicgoTypeDsc = dynamicgoTypeDsc.Struct().FieldById(dthrift.FieldID(getStreamingFieldID(isClient, true))).Type() - return writeStreamingContentWithDynamicgo(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff) + return writeStreamingContentWithDynamicgo(ctx, bw, dynamicgoTypeDsc, &cv, transBuff) } else { if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { return err @@ -136,13 +136,15 @@ func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dy return err } -func writeStreamingContentWithDynamicgo(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte) error { +func writeStreamingContentWithDynamicgo(ctx context.Context, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte) error { dbuf := mcache.Malloc(len(transBuff))[0:0] defer mcache.Free(dbuf) if err := cv.DoInto(ctx, dynamicgoTypeDsc, transBuff, &dbuf); err != nil { return err } - _, err := out.Write(dbuf) - return err + for _, b := range dbuf { + bw.WriteByte(int8(b)) + } + return nil } From 83e15caee7c39e7538bec4d453a5be80f218d86e Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Wed, 31 Jul 2024 11:53:47 +0800 Subject: [PATCH 15/20] fix: http2 write --- .../generic/thrift/json_go116plus_amd64.go | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/generic/thrift/json_go116plus_amd64.go b/internal/generic/thrift/json_go116plus_amd64.go index 42d337432d..ff4d647ae3 100644 --- a/internal/generic/thrift/json_go116plus_amd64.go +++ b/internal/generic/thrift/json_go116plus_amd64.go @@ -22,6 +22,7 @@ package thrift import ( "context" "fmt" + "github.com/cloudwego/kitex/pkg/remote" "io" "unsafe" @@ -68,12 +69,17 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW cv = j2t.NewBinaryConv(m.convOpts) } + _, isGRPC := out.(remote.FrameWrite) + // msg is void or nil if _, ok := msg.(descriptor.Void); ok || msg == nil { - if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, nil, nil, isClient); err != nil { + if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, nil, nil, isClient, isGRPC); err != nil { return err } bw.WriteFieldStop() + if isGRPC { + return nil + } _, err := out.Write(bw.Bytes()) return err } @@ -90,10 +96,13 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW dynamicgoTypeDsc = dynamicgoTypeDsc.Struct().FieldById(dthrift.FieldID(getStreamingFieldID(isClient, true))).Type() return writeStreamingContentWithDynamicgo(ctx, bw, dynamicgoTypeDsc, &cv, transBuff) } else { - if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient); err != nil { + if err := writeFields(ctx, out, bw, dynamicgoTypeDsc, &cv, transBuff, isClient, isGRPC); err != nil { return err } bw.WriteFieldStop() + if isGRPC { + return nil + } _, err := out.Write(bw.Bytes()) return err } @@ -101,7 +110,7 @@ func (m *WriteJSON) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryW type MsgType int -func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient bool) error { +func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dynamicgoTypeDsc *dthrift.TypeDescriptor, cv *j2t.BinaryConv, transBuff []byte, isClient, isGRPC bool) error { dbuf := mcache.Malloc(len(transBuff))[0:0] defer mcache.Free(dbuf) @@ -117,6 +126,9 @@ func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dy // if the field type is void, just write void and return if field.Type().Type() == dthrift.VOID { bw.WriteFieldStop() + if isGRPC { + return nil + } _, err := out.Write(bw.Bytes()) bw.Reset() return err @@ -128,6 +140,12 @@ func writeFields(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, dy } } } + if isGRPC { + for _, b := range dbuf { + bw.WriteByte(int8(b)) + } + return nil + } if _, err := out.Write(bw.Bytes()); err != nil { return err } From fb95beb97871ecd3f9a607d356727a5f20b31f41 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Wed, 31 Jul 2024 11:57:05 +0800 Subject: [PATCH 16/20] fix: lint --- internal/generic/thrift/json_go116plus_amd64.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/generic/thrift/json_go116plus_amd64.go b/internal/generic/thrift/json_go116plus_amd64.go index ff4d647ae3..155d019385 100644 --- a/internal/generic/thrift/json_go116plus_amd64.go +++ b/internal/generic/thrift/json_go116plus_amd64.go @@ -22,7 +22,6 @@ package thrift import ( "context" "fmt" - "github.com/cloudwego/kitex/pkg/remote" "io" "unsafe" @@ -35,6 +34,7 @@ import ( "github.com/cloudwego/gopkg/protocol/thrift/base" "github.com/cloudwego/kitex/pkg/generic/descriptor" + "github.com/cloudwego/kitex/pkg/remote" "github.com/cloudwego/kitex/pkg/remote/codec/perrors" "github.com/cloudwego/kitex/pkg/utils" ) From ffe667b2441098a2b4bfa1194ed2a6fcb9a7063c Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Tue, 6 Aug 2024 15:13:06 +0800 Subject: [PATCH 17/20] fix: revert rebase --- internal/mocks/generic/thrift.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/mocks/generic/thrift.go b/internal/mocks/generic/thrift.go index ae32354f04..ec369eadc6 100644 --- a/internal/mocks/generic/thrift.go +++ b/internal/mocks/generic/thrift.go @@ -27,6 +27,8 @@ import ( reflect "reflect" "github.com/cloudwego/gopkg/protocol/thrift/base" + "github.com/cloudwego/gopkg/protocol/thrift" + gomock "github.com/golang/mock/gomock" ) @@ -92,15 +94,15 @@ func (m *MockMessageWriter) EXPECT() *MockMessageWriterMockRecorder { } // Write mocks base method. -func (m *MockMessageWriter) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (m *MockMessageWriter) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Write", ctx, out, msg, requestBase) + ret := m.ctrl.Call(m, "Write", ctx, out, bw, msg, requestBase) ret0, _ := ret[0].(error) return ret0 } // Write indicates an expected call of Write. -func (mr *MockMessageWriterMockRecorder) Write(ctx, out, msg, requestBase interface{}) *gomock.Call { +func (mr *MockMessageWriterMockRecorder) Write(ctx, out, bw, msg, requestBase interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockMessageWriter)(nil).Write), ctx, out, msg, requestBase) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockMessageWriter)(nil).Write), ctx, out, bw, msg, requestBase) } From 1a40333a8ffa577798b31ec5ae9bfcf1ccb934fe Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Wed, 7 Aug 2024 18:02:53 +0800 Subject: [PATCH 18/20] fix: test --- pkg/generic/grpcjsonthrift_test/generic_init.go | 10 +++++----- pkg/remote/codec/thrift/thrift_data.go | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/generic/grpcjsonthrift_test/generic_init.go b/pkg/generic/grpcjsonthrift_test/generic_init.go index 5d2d44b751..f0a29b10b0 100644 --- a/pkg/generic/grpcjsonthrift_test/generic_init.go +++ b/pkg/generic/grpcjsonthrift_test/generic_init.go @@ -49,7 +49,7 @@ func newGenericStreamingClient(g generic.Generic, targetIPPort string) genericcl } func newGenericClient(g generic.Generic, targetIPPort string) genericclient.Client { - cli, err := genericclient.NewClient("destService", g, client.WithHostPorts(targetIPPort)) + cli, err := genericclient.NewClient("destService", g, client.WithHostPorts(targetIPPort), client.WithTransportProtocol(transport.TTHeader)) if err != nil { panic(err) } @@ -401,8 +401,8 @@ func newTestServiceEchoBizExceptionResult() interface{} { } func echoPingPongHandler(ctx context.Context, handler, arg, result interface{}) error { - realArg := kt.UnpackApacheCodec(arg).(*kt.TestServiceEchoPingPongArgs) - realResult := kt.UnpackApacheCodec(result).(*kt.TestServiceEchoPingPongResult) + realArg := arg.(*kt.TestServiceEchoPingPongArgs) + realResult := result.(*kt.TestServiceEchoPingPongResult) success, err := handler.(kt.TestService).EchoPingPong(ctx, realArg.Req) if err != nil { return err @@ -412,9 +412,9 @@ func echoPingPongHandler(ctx context.Context, handler, arg, result interface{}) } func newTestServiceEchoPingPongArgs() interface{} { - return kt.ToApacheCodec(kt.NewTestServiceEchoPingPongArgs()) + return kt.NewTestServiceEchoPingPongArgs() } func newTestServiceEchoPingPongResult() interface{} { - return kt.ToApacheCodec(kt.NewTestServiceEchoPingPongResult()) + return kt.NewTestServiceEchoPingPongResult() } diff --git a/pkg/remote/codec/thrift/thrift_data.go b/pkg/remote/codec/thrift/thrift_data.go index 4ff0ca9d9c..29a97ce702 100644 --- a/pkg/remote/codec/thrift/thrift_data.go +++ b/pkg/remote/codec/thrift/thrift_data.go @@ -155,7 +155,6 @@ func (c thriftCodec) fastUnmarshal(trans remote.ByteBuffer, data interface{}, da } // unmarshalThriftData only decodes the data (after methodName, msgType and seqId) -// method is only used for generic calls func (c thriftCodec) unmarshalThriftData(trans remote.ByteBuffer, data interface{}, dataLen int) error { // decode with hyper unmarshal if c.IsSet(FrugalRead) && c.hyperMessageUnmarshalAvailable(data, dataLen) { From 52445b764d38f6120f29eb7ae9408481e936fd11 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 26 Aug 2024 18:11:20 +0800 Subject: [PATCH 19/20] fix: write interface --- internal/generic/thrift/binary.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/generic/thrift/binary.go b/internal/generic/thrift/binary.go index d4aa2e3b2b..2e042795cd 100644 --- a/internal/generic/thrift/binary.go +++ b/internal/generic/thrift/binary.go @@ -18,6 +18,7 @@ package thrift import ( "context" + "github.com/cloudwego/gopkg/protocol/thrift" "io" "github.com/cloudwego/gopkg/protocol/thrift/base" @@ -30,6 +31,6 @@ func NewWriteBinary() *WriteBinary { return &WriteBinary{} } -func (w *WriteBinary) Write(ctx context.Context, out io.Writer, msg interface{}, method string, isClient bool, requestBase *base.Base) error { +func (w *WriteBinary) Write(ctx context.Context, out io.Writer, bw *thrift.BinaryWriter, msg interface{}, method string, isClient bool, requestBase *base.Base) error { return nil } From 0518592f6d9499246f546f8a48a71adb149d1558 Mon Sep 17 00:00:00 2001 From: Marina-Sakai Date: Mon, 26 Aug 2024 18:15:22 +0800 Subject: [PATCH 20/20] fix: import --- internal/generic/thrift/binary.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/generic/thrift/binary.go b/internal/generic/thrift/binary.go index 2e042795cd..eb7ec66708 100644 --- a/internal/generic/thrift/binary.go +++ b/internal/generic/thrift/binary.go @@ -18,9 +18,9 @@ package thrift import ( "context" - "github.com/cloudwego/gopkg/protocol/thrift" "io" + "github.com/cloudwego/gopkg/protocol/thrift" "github.com/cloudwego/gopkg/protocol/thrift/base" )