forked from mtfelian/golang-socketio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandler.go
69 lines (57 loc) · 1.61 KB
/
handler.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
package gosocketio
import (
"errors"
"reflect"
)
// handler is an event handler representation
type handler struct {
function reflect.Value
args reflect.Type
hasArgs bool
out bool
}
var (
ErrorHandlerIsNotFunc = errors.New("f is not a function")
ErrorHandlerHasNot2Args = errors.New("f should have 1 or 2 arguments")
ErrorHandlerWrongResult = errors.New("f should return no more than one value")
)
// newHandler parses function f (event handler) using reflection, and stores it's representation
func newHandler(f interface{}) (*handler, error) {
fVal := reflect.ValueOf(f)
if fVal.Kind() != reflect.Func {
return nil, ErrorHandlerIsNotFunc
}
fType := fVal.Type()
if fType.NumOut() > 1 {
return nil, ErrorHandlerWrongResult
}
curCaller := &handler{
function: fVal,
out: fType.NumOut() == 1,
}
switch fType.NumIn() {
case 1:
curCaller.args = nil
curCaller.hasArgs = false
case 2:
curCaller.args = fType.In(1)
curCaller.hasArgs = true
default:
return nil, ErrorHandlerHasNot2Args
}
return curCaller, nil
}
// arguments returns function parameter as it is present in it using reflection
func (h *handler) arguments() interface{} { return reflect.New(h.args).Interface() }
// call func with given arguments from its representation using reflection
func (h *handler) call(c *Channel, arguments interface{}) []reflect.Value {
// nil is untyped, so use the default empty value of correct type
if arguments == nil {
arguments = h.arguments()
}
a := []reflect.Value{reflect.ValueOf(c), reflect.ValueOf(arguments).Elem()}
if !h.hasArgs {
a = a[0:1]
}
return h.function.Call(a)
}