-
Notifications
You must be signed in to change notification settings - Fork 0
/
func.go
84 lines (73 loc) · 2.05 KB
/
func.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package rpcmap
import (
"reflect"
)
// Function definition object
type FuncDef struct {
argno int
hasRv bool
argsType reflect.Type
meth reflect.Value
data map[string]interface{}
}
func makeFuncDef(f interface{}) *FuncDef {
t := reflect.TypeOf(f)
if !methTypeCheck(t, 0) {
panic("Invalid function signature for RpcMap.Func")
}
fd := &FuncDef{
meth: reflect.ValueOf(f),
argno: t.NumIn(),
hasRv: 2 == t.NumOut(),
data: make(map[string]interface{}),
}
if t.NumIn() == 0 {
fd.argsType = typeOfEmptyStruct
} else {
fd.argsType = t.In(t.NumIn() - 1)
}
return fd
}
// Call a function. If function signature has no return value, returned interface is nil.
// If function does not accept context, ctx parameter will be ignored, you can pass nil.
func (fd* FuncDef) Call(ctx interface{}, in interface{}) (interface{}, error) {
var in_args []reflect.Value
switch fd.argno {
case 0:
in_args = []reflect.Value{}
case 1:
in_args = []reflect.Value{ reflect.ValueOf(in) }
case 2:
in_args = []reflect.Value{ reflect.ValueOf(ctx), reflect.ValueOf(in) }
}
rvs := fd.meth.Call(in_args)
if fd.hasRv {
rerr,_ := rvs[1].Interface().(error)
return rvs[0].Interface(), rerr
} else {
rerr,_ := rvs[0].Interface().(error)
return nil, rerr
}
return nil, nil
}
// Create input argument for function based on it's prototype. If function takes pointer, it will create
// original type.
func (fd* FuncDef) MakeArg() interface{} {
return makeArg(fd.argsType)
}
// Returns number of function arguments
func (fd* FuncDef) InArgs() int {
return fd.argno
}
// Returns true if functions has a result
func (fd* FuncDef) HasOutArg() bool {
return fd.hasRv
}
// Set function meta-data value
func (fd* FuncDef) Set(key string, v interface{}) {
fd.data[key] = v
}
// Get function meta-data value
func (fd* FuncDef) Get(key string) interface{} {
return fd.data[key]
}