From 446f922fc7d8105df8a24e8127f31358636546ba Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Sun, 11 Aug 2024 23:23:54 +0900 Subject: [PATCH 1/2] wip --- mux.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/mux.go b/mux.go index 7230308..7675161 100644 --- a/mux.go +++ b/mux.go @@ -2,6 +2,7 @@ package dew import ( "context" + "fmt" "reflect" "sync" ) @@ -168,6 +169,38 @@ func (mx *mux) updateHandler(m middlewareType) { // Register adds the handler to the mux for the given command type. func (mx *mux) Register(handler any) { hdlTyp := reflect.TypeOf(handler) + + // if it's not a pointer, convert it to a pointer so we can get + // access to all the methods of the struct. + if hdlTyp.Kind() != reflect.Ptr { + newVal := reflect.New(reflect.PointerTo(hdlTyp)) + ptrToHandler := reflect.ValueOf(&handler) + if ptrToHandler.Elem().Type().AssignableTo(newVal.Elem().Type()) { + newVal.Elem().Set(ptrToHandler.Elem()) + } else { + // If direct assignment is not possible, we need to create an intermediate value + intermediateVal := reflect.New(hdlTyp) + intermediateVal.Elem().Set(reflect.ValueOf(handler)) + newVal.Elem().Set(intermediateVal) + } + handler = newVal.Interface() + hdlTyp = reflect.TypeOf(handler) + + if hdlTyp.Kind() == reflect.Ptr && hdlTyp.Elem().Kind() == reflect.Ptr { + // We have a pointer to a pointer, let's get to the single pointer + newVal := reflect.ValueOf(handler).Elem() + handler = newVal.Interface() + hdlTyp = reflect.TypeOf(handler) + } + + } + + kind := hdlTyp.Kind() + println(fmt.Sprintf("Register: %v %s", kind, hdlTyp.String())) + + numMethod := hdlTyp.NumMethod() + println(fmt.Sprintf("numMethod: %v", numMethod)) + for i := 0; i < hdlTyp.NumMethod(); i++ { mtdTyp := hdlTyp.Method(i) if isHandlerMethod(mtdTyp) { @@ -187,6 +220,7 @@ func (mx *mux) setupHandler() { mx.updateHandler(mQuery) } if mx.mHandlers[mDispatch] == nil { + println("setupHandler") mx.updateHandler(mDispatch) } if mx.parent != nil { @@ -195,6 +229,7 @@ func (mx *mux) setupHandler() { } func (mx *mux) addHandler(t reflect.Type, h any) { + println(fmt.Sprintf("addHandler: %v", t)) mx.entries.Store(t, &handler{handler: h, mux: mx}) } From f2852c3842f69a7253bbf91941fcc88f76e43d46 Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Sun, 11 Aug 2024 23:31:44 +0900 Subject: [PATCH 2/2] Support value type for Regiser parameter --- mux.go | 56 +++++++++++++++-------------------------------------- mux_test.go | 13 +++++++++++++ 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/mux.go b/mux.go index 7675161..900475e 100644 --- a/mux.go +++ b/mux.go @@ -167,48 +167,24 @@ func (mx *mux) updateHandler(m middlewareType) { } // Register adds the handler to the mux for the given command type. -func (mx *mux) Register(handler any) { - hdlTyp := reflect.TypeOf(handler) - - // if it's not a pointer, convert it to a pointer so we can get - // access to all the methods of the struct. - if hdlTyp.Kind() != reflect.Ptr { - newVal := reflect.New(reflect.PointerTo(hdlTyp)) - ptrToHandler := reflect.ValueOf(&handler) - if ptrToHandler.Elem().Type().AssignableTo(newVal.Elem().Type()) { - newVal.Elem().Set(ptrToHandler.Elem()) - } else { - // If direct assignment is not possible, we need to create an intermediate value - intermediateVal := reflect.New(hdlTyp) - intermediateVal.Elem().Set(reflect.ValueOf(handler)) - newVal.Elem().Set(intermediateVal) - } - handler = newVal.Interface() - hdlTyp = reflect.TypeOf(handler) - - if hdlTyp.Kind() == reflect.Ptr && hdlTyp.Elem().Kind() == reflect.Ptr { - // We have a pointer to a pointer, let's get to the single pointer - newVal := reflect.ValueOf(handler).Elem() - handler = newVal.Interface() - hdlTyp = reflect.TypeOf(handler) - } - +func (mx *mux) Register(handler interface{}) { + val := reflect.ValueOf(handler) + typ := val.Type() + + // Convert to pointer if not already + if typ.Kind() != reflect.Ptr { + val = reflect.New(typ) + val.Elem().Set(reflect.ValueOf(handler)) + typ = val.Type() } - kind := hdlTyp.Kind() - println(fmt.Sprintf("Register: %v %s", kind, hdlTyp.String())) - - numMethod := hdlTyp.NumMethod() - println(fmt.Sprintf("numMethod: %v", numMethod)) - - for i := 0; i < hdlTyp.NumMethod(); i++ { - mtdTyp := hdlTyp.Method(i) - if isHandlerMethod(mtdTyp) { - cmdTyp := mtdTyp.Type.In(2).Elem() - if cmdTyp.Implements(reflect.TypeOf((*Action)(nil)).Elem()) { - mx.addHandler(cmdTyp, reflect.ValueOf(handler).Method(i).Interface()) - } else if cmdTyp.Implements(reflect.TypeOf((*QueryAction)(nil)).Elem()) { - mx.addHandler(cmdTyp, reflect.ValueOf(handler).Method(i).Interface()) + for i := 0; i < typ.NumMethod(); i++ { + method := typ.Method(i) + if isHandlerMethod(method) { + cmdType := method.Type.In(2).Elem() + if cmdType.Implements(reflect.TypeOf((*Action)(nil)).Elem()) || + cmdType.Implements(reflect.TypeOf((*QueryAction)(nil)).Elem()) { + mx.addHandler(cmdType, val.Method(i).Interface()) } } } diff --git a/mux_test.go b/mux_test.go index d609b8b..73bfa3b 100644 --- a/mux_test.go +++ b/mux_test.go @@ -29,6 +29,19 @@ func TestMux_BasicCommand(t *testing.T) { } } +func TestMux_ValueTypeHandler(t *testing.T) { + var userHandler userHandler + + mux := dew.New() + mux.Register(userHandler) + + createUser := &createUser{Name: "john"} + testRunDispatch(t, dew.NewAction(mux, createUser)) + if createUser.Result != "user created" { + t.Fatalf("unexpected result: %s", createUser.Result) + } +} + func TestMux_HandlerNotFound(t *testing.T) { defer func() { if r := recover(); r == nil {