--- /dev/null
+/*
+MIT License
+
+Copyright (c) 2023 Mattia Cabrini
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package utility
+
+import (
+ "reflect"
+)
+
+type Method struct {
+ to reflect.Method
+ numIn int
+
+ F GenericFunc
+}
+
+func newMethod(to reflect.Method, callable GenericFunc) (m *Method) {
+ m = &Method{
+ to: to,
+ numIn: to.Type.NumIn() - 1,
+ F: callable,
+ }
+
+ return
+}
+
+func (m *Method) NumIn() int {
+ return m.numIn
+}
+
+func (m *Method) ParamKind(i int) reflect.Kind {
+ return m.to.Type.In(i + 1).Kind()
+}
type GenericFunc func(...interface{}) ([]interface{}, error)
-func checkMethodArgs(methodVO reflect.Method, args []reflect.Value) error {
- if m, a := methodVO.Type.NumIn(), len(args); m != a+1 {
+func checkMethodArgs(methodTO reflect.Method, args []reflect.Value) error {
+ if m, a := methodTO.Type.NumIn(), len(args); m != a+1 {
return fmt.Errorf("expected %d arguments, got %d", m, a)
}
for i, arg := range args {
- argTypeExpected := methodVO.Type.In(i + 1)
+ argTypeExpected := methodTO.Type.In(i + 1)
if i == 0 {
continue // skip the object itself
}
}
-func GetMethod(obj interface{}, name string, suffix string) GenericFunc {
+func GetMethod(obj interface{}, name string, suffix string) *Method {
to := reflect.TypeOf(obj)
vo := reflect.ValueOf(obj)
if b {
methodVO := vo.MethodByName(name + suffix)
-
- return newGenericFunc(obj, methodTO, methodVO)
+ callable := newGenericFunc(obj, methodTO, methodVO)
+ return newMethod(methodTO, callable)
}
return nil
package utility
-import "testing"
+import (
+ "reflect"
+ "testing"
+)
type testType struct {
A int `con:"true" con2:"true"`
func TestMethodOk0(t *testing.T) {
obj := testType{0, 1}
- f := GetMethod(&obj, "GetAB", "")
+ m := GetMethod(&obj, "GetAB", "")
- if f == nil {
+ if m == nil {
t.Fail()
return
}
- results, err := f(0, 1)
+ results, err := m.F(0, 1)
if err != nil {
t.Error(err)
if results[1].(int) != 2 {
t.Error(1)
}
+
+ if m.ParamKind(0) != reflect.Int {
+ t.Error(2)
+ }
+ if m.ParamKind(1) != reflect.Int {
+ t.Error(3)
+ }
+ if m.NumIn() != 2 {
+ t.Error(4)
+ }
}
func TestMethodOk1(t *testing.T) {
obj := testType{0, 1}
- f := GetMethod(&obj, "GetAB", "interface")
+ m := GetMethod(&obj, "GetAB", "interface")
- if f == nil {
+ if m == nil {
t.Fail()
return
}
- results, err := f(0, 1)
+ results, err := m.F(0, 1)
if err != nil {
t.Error(err)
func TestMethodOk2(t *testing.T) {
obj := testType{0, 1}
- f := GetMethod(&obj, "GetAB", "struct")
+ m := GetMethod(&obj, "GetAB", "struct")
- if f == nil {
+ if m == nil {
t.Fail()
return
}
- results, err := f(0, obj)
+ results, err := m.F(0, obj)
if err != nil {
t.Error(err)
func TestMethodArgCountKo(t *testing.T) {
obj := testType{0, 1}
- f := GetMethod(&obj, "Get", "AB")
+ m := GetMethod(&obj, "Get", "AB")
- if f == nil {
+ if m == nil {
t.Fail()
return
}
- _, err := f(0)
+ _, err := m.F(0)
if err == nil {
t.Fail()
func TestMethodArgTypeKo(t *testing.T) {
obj := testType{0, 1}
- f := GetMethod(&obj, "Get", "AB")
+ m := GetMethod(&obj, "Get", "AB")
- if f == nil {
+ if m == nil {
t.Fail()
return
}
- _, err := f(0, "1")
+ _, err := m.F(0, "1")
if err == nil {
t.Fail()