From 0d497ca0df4d66f5e40b1bcac632c6e0b24c8603 Mon Sep 17 00:00:00 2001 From: Gorbunov Kirill Andreevich Date: Tue, 27 Feb 2024 21:05:42 +0300 Subject: [PATCH 1/3] #97 add As for Broker. --- broker/wrap.go | 34 +++++++++++++++++++ broker/wrap_test.go | 83 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 broker/wrap.go create mode 100644 broker/wrap_test.go diff --git a/broker/wrap.go b/broker/wrap.go new file mode 100644 index 00000000..331b1d63 --- /dev/null +++ b/broker/wrap.go @@ -0,0 +1,34 @@ +package broker + +import ( + "reflect" +) + +func As(b Broker, target any) bool { + if b == nil { + return false + } + if target == nil { + return false + } + val := reflect.ValueOf(target) + typ := val.Type() + if typ.Kind() != reflect.Ptr || val.IsNil() { + return false + } + targetType := typ.Elem() + if targetType.Kind() != reflect.Interface && !targetType.Implements(brokerType) { + return false + } + return as(b, val, targetType) +} + +func as(b Broker, targetVal reflect.Value, targetType reflect.Type) bool { + if reflect.TypeOf(b).AssignableTo(targetType) { + targetVal.Elem().Set(reflect.ValueOf(b)) + return true + } + return false +} + +var brokerType = reflect.TypeOf((*Broker)(nil)).Elem() diff --git a/broker/wrap_test.go b/broker/wrap_test.go new file mode 100644 index 00000000..671ea1b3 --- /dev/null +++ b/broker/wrap_test.go @@ -0,0 +1,83 @@ +package broker + +import ( + "context" + "fmt" + "reflect" + "testing" + + "go.unistack.org/micro/v4/options" +) + +type bro struct { + name string +} + +func (p *bro) Name() string { return p.name } +func (p *bro) Init(opts ...options.Option) error { return nil } + +// Options returns broker options +func (p *bro) Options() Options { return Options{} } + +// Address return configured address +func (p *bro) Address() string { return "" } + +// Connect connects to broker +func (p *bro) Connect(ctx context.Context) error { return nil } + +// Disconnect disconnect from broker +func (p *bro) Disconnect(ctx context.Context) error { return nil } + +// Publish message, msg can be single broker.Message or []broker.Message +func (p *bro) Publish(ctx context.Context, msg interface{}, opts ...options.Option) error { return nil } + +// Subscribe subscribes to topic message via handler +func (p *bro) Subscribe(ctx context.Context, topic string, handler interface{}, opts ...options.Option) (Subscriber, error) { + return nil, nil +} + +// String type of broker +func (p *bro) String() string { return p.name } + +func TestAs(t *testing.T) { + var b *bro + broTarget := &bro{name: "kafka"} + + testCases := []struct { + b Broker + target any + match bool + want any + }{ + { + broTarget, + &b, + true, + broTarget, + }, + { + nil, + &b, + false, + nil, + }, + } + for i, tc := range testCases { + name := fmt.Sprintf("%d:As(Errorf(..., %v), %v)", i, tc.b, tc.target) + // Clear the target pointer, in case it was set in a previous test. + rtarget := reflect.ValueOf(tc.target) + rtarget.Elem().Set(reflect.Zero(reflect.TypeOf(tc.target).Elem())) + t.Run(name, func(t *testing.T) { + match := As(tc.b, tc.target) + if match != tc.match { + t.Fatalf("match: got %v; want %v", match, tc.match) + } + if !match { + return + } + if got := rtarget.Elem().Interface(); got != tc.want { + t.Fatalf("got %#v, want %#v", got, tc.want) + } + }) + } +} From c09674ae92e12753689e909ea205f62eecb6d5c4 Mon Sep 17 00:00:00 2001 From: Gorbunov Kirill Andreevich Date: Tue, 27 Feb 2024 22:11:39 +0300 Subject: [PATCH 2/3] #97 add As for all interface. --- broker/wrap.go | 34 ----------- micro.go | 77 +++++++++++++++++++++++++ broker/wrap_test.go => micro_test.go | 84 +++++++++++++++++----------- 3 files changed, 129 insertions(+), 66 deletions(-) delete mode 100644 broker/wrap.go create mode 100644 micro.go rename broker/wrap_test.go => micro_test.go (74%) diff --git a/broker/wrap.go b/broker/wrap.go deleted file mode 100644 index 331b1d63..00000000 --- a/broker/wrap.go +++ /dev/null @@ -1,34 +0,0 @@ -package broker - -import ( - "reflect" -) - -func As(b Broker, target any) bool { - if b == nil { - return false - } - if target == nil { - return false - } - val := reflect.ValueOf(target) - typ := val.Type() - if typ.Kind() != reflect.Ptr || val.IsNil() { - return false - } - targetType := typ.Elem() - if targetType.Kind() != reflect.Interface && !targetType.Implements(brokerType) { - return false - } - return as(b, val, targetType) -} - -func as(b Broker, targetVal reflect.Value, targetType reflect.Type) bool { - if reflect.TypeOf(b).AssignableTo(targetType) { - targetVal.Elem().Set(reflect.ValueOf(b)) - return true - } - return false -} - -var brokerType = reflect.TypeOf((*Broker)(nil)).Elem() diff --git a/micro.go b/micro.go new file mode 100644 index 00000000..c167e1b4 --- /dev/null +++ b/micro.go @@ -0,0 +1,77 @@ +package micro + +import ( + "reflect" + + "go.unistack.org/micro/v4/broker" + "go.unistack.org/micro/v4/client" + "go.unistack.org/micro/v4/codec" + "go.unistack.org/micro/v4/flow" + "go.unistack.org/micro/v4/fsm" + "go.unistack.org/micro/v4/logger" + "go.unistack.org/micro/v4/meter" + "go.unistack.org/micro/v4/register" + "go.unistack.org/micro/v4/resolver" + "go.unistack.org/micro/v4/router" + "go.unistack.org/micro/v4/selector" + "go.unistack.org/micro/v4/server" + "go.unistack.org/micro/v4/store" + "go.unistack.org/micro/v4/sync" + "go.unistack.org/micro/v4/tracer" +) + +func As(b any, target any) bool { + if b == nil { + return false + } + if target == nil { + return false + } + val := reflect.ValueOf(target) + typ := val.Type() + if typ.Kind() != reflect.Ptr || val.IsNil() { + return false + } + targetType := typ.Elem() + if targetType.Kind() != reflect.Interface && + !(targetType.Implements(brokerType) || + targetType.Implements(loggerType) || + targetType.Implements(clientType) || + targetType.Implements(serverType) || + targetType.Implements(codecType) || + targetType.Implements(flowType) || + targetType.Implements(fsmType) || + targetType.Implements(meterType) || + targetType.Implements(registerType) || + targetType.Implements(resolverType) || + targetType.Implements(selectorType) || + targetType.Implements(storeType) || + targetType.Implements(syncType) || + targetType.Implements(tracerType) || + targetType.Implements(serviceType) || + targetType.Implements(routerType)) { + return false + } + if reflect.TypeOf(b).AssignableTo(targetType) { + val.Elem().Set(reflect.ValueOf(b)) + return true + } + return false +} + +var brokerType = reflect.TypeOf((*broker.Broker)(nil)).Elem() +var loggerType = reflect.TypeOf((*logger.Logger)(nil)).Elem() +var clientType = reflect.TypeOf((*client.Client)(nil)).Elem() +var serverType = reflect.TypeOf((*server.Server)(nil)).Elem() +var codecType = reflect.TypeOf((*codec.Codec)(nil)).Elem() +var flowType = reflect.TypeOf((*flow.Flow)(nil)).Elem() +var fsmType = reflect.TypeOf((*fsm.FSM)(nil)).Elem() +var meterType = reflect.TypeOf((*meter.Meter)(nil)).Elem() +var registerType = reflect.TypeOf((*register.Register)(nil)).Elem() +var resolverType = reflect.TypeOf((*resolver.Resolver)(nil)).Elem() +var routerType = reflect.TypeOf((*router.Router)(nil)).Elem() +var selectorType = reflect.TypeOf((*selector.Selector)(nil)).Elem() +var storeType = reflect.TypeOf((*store.Store)(nil)).Elem() +var syncType = reflect.TypeOf((*sync.Sync)(nil)).Elem() +var tracerType = reflect.TypeOf((*tracer.Tracer)(nil)).Elem() +var serviceType = reflect.TypeOf((*Service)(nil)).Elem() diff --git a/broker/wrap_test.go b/micro_test.go similarity index 74% rename from broker/wrap_test.go rename to micro_test.go index 671ea1b3..c9dc1bbb 100644 --- a/broker/wrap_test.go +++ b/micro_test.go @@ -1,4 +1,4 @@ -package broker +package micro import ( "context" @@ -6,45 +6,18 @@ import ( "reflect" "testing" + "go.unistack.org/micro/v4/broker" + "go.unistack.org/micro/v4/fsm" "go.unistack.org/micro/v4/options" ) -type bro struct { - name string -} - -func (p *bro) Name() string { return p.name } -func (p *bro) Init(opts ...options.Option) error { return nil } - -// Options returns broker options -func (p *bro) Options() Options { return Options{} } - -// Address return configured address -func (p *bro) Address() string { return "" } - -// Connect connects to broker -func (p *bro) Connect(ctx context.Context) error { return nil } - -// Disconnect disconnect from broker -func (p *bro) Disconnect(ctx context.Context) error { return nil } - -// Publish message, msg can be single broker.Message or []broker.Message -func (p *bro) Publish(ctx context.Context, msg interface{}, opts ...options.Option) error { return nil } - -// Subscribe subscribes to topic message via handler -func (p *bro) Subscribe(ctx context.Context, topic string, handler interface{}, opts ...options.Option) (Subscriber, error) { - return nil, nil -} - -// String type of broker -func (p *bro) String() string { return p.name } - func TestAs(t *testing.T) { var b *bro broTarget := &bro{name: "kafka"} + fsmTarget := &fsmT{name: "fsm"} testCases := []struct { - b Broker + b any target any match bool want any @@ -61,6 +34,12 @@ func TestAs(t *testing.T) { false, nil, }, + { + fsmTarget, + &b, + false, + nil, + }, } for i, tc := range testCases { name := fmt.Sprintf("%d:As(Errorf(..., %v), %v)", i, tc.b, tc.target) @@ -81,3 +60,44 @@ func TestAs(t *testing.T) { }) } } + +type bro struct { + name string +} + +func (p *bro) Name() string { return p.name } +func (p *bro) Init(opts ...options.Option) error { return nil } + +// Options returns broker options +func (p *bro) Options() broker.Options { return broker.Options{} } + +// Address return configured address +func (p *bro) Address() string { return "" } + +// Connect connects to broker +func (p *bro) Connect(ctx context.Context) error { return nil } + +// Disconnect disconnect from broker +func (p *bro) Disconnect(ctx context.Context) error { return nil } + +// Publish message, msg can be single broker.Message or []broker.Message +func (p *bro) Publish(ctx context.Context, msg interface{}, opts ...options.Option) error { return nil } + +// Subscribe subscribes to topic message via handler +func (p *bro) Subscribe(ctx context.Context, topic string, handler interface{}, opts ...options.Option) (broker.Subscriber, error) { + return nil, nil +} + +// String type of broker +func (p *bro) String() string { return p.name } + +type fsmT struct { + name string +} + +func (f *fsmT) Start(ctx context.Context, a interface{}, o ...Option) (interface{}, error) { + return nil, nil +} +func (f *fsmT) Current() string { return f.name } +func (f *fsmT) Reset() {} +func (f *fsmT) State(s string, sf fsm.StateFunc) {} From cdfeaa7e208c72374d63a911176b6a641ba2397d Mon Sep 17 00:00:00 2001 From: Gorbunov Kirill Andreevich Date: Tue, 27 Feb 2024 22:36:18 +0300 Subject: [PATCH 3/3] #97 add As for all interface. --- micro.go | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/micro.go b/micro.go index c167e1b4..c86955c8 100644 --- a/micro.go +++ b/micro.go @@ -33,24 +33,41 @@ func As(b any, target any) bool { return false } targetType := typ.Elem() - if targetType.Kind() != reflect.Interface && - !(targetType.Implements(brokerType) || - targetType.Implements(loggerType) || - targetType.Implements(clientType) || - targetType.Implements(serverType) || - targetType.Implements(codecType) || - targetType.Implements(flowType) || - targetType.Implements(fsmType) || - targetType.Implements(meterType) || - targetType.Implements(registerType) || - targetType.Implements(resolverType) || - targetType.Implements(selectorType) || - targetType.Implements(storeType) || - targetType.Implements(syncType) || - targetType.Implements(tracerType) || - targetType.Implements(serviceType) || - targetType.Implements(routerType)) { - return false + if targetType.Kind() != reflect.Interface { + switch { + case targetType.Implements(brokerType): + break + case targetType.Implements(loggerType): + break + case targetType.Implements(clientType): + break + case targetType.Implements(serverType): + break + case targetType.Implements(codecType): + break + case targetType.Implements(flowType): + break + case targetType.Implements(fsmType): + break + case targetType.Implements(meterType): + break + case targetType.Implements(registerType): + break + case targetType.Implements(resolverType): + break + case targetType.Implements(selectorType): + break + case targetType.Implements(storeType): + break + case targetType.Implements(syncType): + break + case targetType.Implements(serviceType): + break + case targetType.Implements(routerType): + break + default: + return false + } } if reflect.TypeOf(b).AssignableTo(targetType) { val.Elem().Set(reflect.ValueOf(b))