From 7f440d616fb16b648b36b1b5cc95bed5414bbb8f Mon Sep 17 00:00:00 2001 From: andot Date: Sun, 18 Feb 2024 11:53:25 +0800 Subject: [PATCH] add StructType & ListType support for default codec --- rpc/core/client_codec.go | 6 +++++- rpc/core/codec_option.go | 26 +++++++++++++++++++++++++- rpc/core/service_codec.go | 6 +++++- rpc/mock/mock_test.go | 39 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/rpc/core/client_codec.go b/rpc/core/client_codec.go index bc27b56..328170e 100644 --- a/rpc/core/client_codec.go +++ b/rpc/core/client_codec.go @@ -6,7 +6,7 @@ | | | rpc/core/client_codec.go | | | -| LastModified: Feb 27, 2022 | +| LastModified: Feb 18, 2024 | | Author: Ma Bingyao | | | \*________________________________________________________*/ @@ -29,6 +29,8 @@ type clientCodec struct { io.LongType io.RealType io.MapType + io.StructType + io.ListType } // Encode request. @@ -60,6 +62,8 @@ func (c clientCodec) Decode(response []byte, context *ClientContext) (result []i decoder.LongType = c.LongType decoder.RealType = c.RealType decoder.MapType = c.MapType + decoder.StructType = c.StructType + decoder.ListType = c.ListType tag := decoder.NextByte() if tag == io.TagHeader { var h map[string]interface{} diff --git a/rpc/core/codec_option.go b/rpc/core/codec_option.go index c4ddc45..08817be 100644 --- a/rpc/core/codec_option.go +++ b/rpc/core/codec_option.go @@ -6,7 +6,7 @@ | | | rpc/core/codec_option.go | | | -| LastModified: Jun 16, 2021 | +| LastModified: Feb 18, 2024 | | Author: Ma Bingyao | | | \*________________________________________________________*/ @@ -74,3 +74,27 @@ func WithMapType(mapType io.MapType) CodecOption { } } } + +// WithStructType returns a structType Option for clientCodec & serviceCodec. +func WithStructType(structType io.StructType) CodecOption { + return func(c interface{}) { + switch c := c.(type) { + case *serviceCodec: + c.StructType = structType + case *clientCodec: + c.StructType = structType + } + } +} + +// WithListType returns a listType Option for clientCodec & serviceCodec. +func WithListType(listType io.ListType) CodecOption { + return func(c interface{}) { + switch c := c.(type) { + case *serviceCodec: + c.ListType = listType + case *clientCodec: + c.ListType = listType + } + } +} diff --git a/rpc/core/service_codec.go b/rpc/core/service_codec.go index 4bc8cc7..cf46798 100644 --- a/rpc/core/service_codec.go +++ b/rpc/core/service_codec.go @@ -6,7 +6,7 @@ | | | rpc/core/service_codec.go | | | -| LastModified: Feb 27, 2022 | +| LastModified: Feb 18, 2024 | | Author: Ma Bingyao | | | \*________________________________________________________*/ @@ -32,6 +32,8 @@ type serviceCodec struct { io.LongType io.RealType io.MapType + io.StructType + io.ListType } // Encode response. @@ -75,6 +77,8 @@ func (c serviceCodec) Decode(request []byte, context *ServiceContext) (name stri decoder.LongType = c.LongType decoder.RealType = c.RealType decoder.MapType = c.MapType + decoder.StructType = c.StructType + decoder.ListType = c.ListType tag := decoder.NextByte() if tag == io.TagHeader { var h map[string]interface{} diff --git a/rpc/mock/mock_test.go b/rpc/mock/mock_test.go index 4d20c3d..688f8db 100644 --- a/rpc/mock/mock_test.go +++ b/rpc/mock/mock_test.go @@ -6,7 +6,7 @@ | | | rpc/mock/mock_test.go | | | -| LastModified: May 7, 2021 | +| LastModified: Feb 18, 2024 | | Author: Ma Bingyao | | | \*________________________________________________________*/ @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/hprose/hprose-golang/v3/io" "github.com/hprose/hprose-golang/v3/rpc/core" . "github.com/hprose/hprose-golang/v3/rpc/mock" "github.com/hprose/hprose-golang/v3/rpc/plugins/circuitbreaker" @@ -59,6 +60,9 @@ func TestHelloWorld(t *testing.T) { result, err := proxy.Hello("world") assert.Equal(t, "hello world", result) assert.NoError(t, err) + results, err := client.Invoke("hello", []interface{}{"world"}) + assert.Equal(t, "hello world", results[0]) + assert.NoError(t, err) server.Close() } @@ -1323,3 +1327,36 @@ func TestClientAbort(t *testing.T) { assert.Greater(t, n, int32(0)) server.Close() } + +func TestReturnStructSlice(t *testing.T) { + type User struct { + Name string + Age int + } + io.RegisterName("User", (*User)(nil)) + service := core.NewService() + service.AddFunction(func() []User { + return []User{{"Tom", 18}, {"Jerry", 20}} + }, "users") + server := Server{Address: "testReturnStructSlice"} + err := service.Bind(server) + assert.NoError(t, err) + client := core.NewClient("mock://testReturnStructSlice") + client.Codec = core.NewClientCodec( + core.WithStructType(io.StructTypeStructObject), + core.WithListType(io.ListTypeSlice), + ) + var proxy struct { + Users func() ([]User, error) + } + client.UseService(&proxy) + result, err := proxy.Users() + if assert.NoError(t, err) { + assert.Equal(t, []User{{"Tom", 18}, {"Jerry", 20}}, result) + } + results, err := client.Invoke("users", nil) + if assert.NoError(t, err) { + assert.Equal(t, []User{{"Tom", 18}, {"Jerry", 20}}, results[0]) + } + server.Close() +}