-
Notifications
You must be signed in to change notification settings - Fork 164
/
handler.go
108 lines (99 loc) · 2.78 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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2016 CodisLabs. All Rights Reserved.
// Licensed under the MIT (MIT-LICENSE.txt) license.
package redis
import (
"reflect"
"strings"
"github.com/CodisLabs/redis-port/pkg/libs/errors"
"github.com/CodisLabs/redis-port/pkg/libs/log"
)
type HandlerFunc func(arg0 interface{}, args ...[]byte) (Resp, error)
type HandlerTable map[string]HandlerFunc
func NewHandlerTable(o interface{}) (map[string]HandlerFunc, error) {
if o == nil {
return nil, errors.Errorf("handler is nil")
}
t := make(map[string]HandlerFunc)
r := reflect.TypeOf(o)
for i := 0; i < r.NumMethod(); i++ {
m := r.Method(i)
if m.Name[0] < 'A' || m.Name[0] > 'Z' {
continue
}
n := strings.ToLower(m.Name)
if h, err := createHandlerFunc(o, &m.Func); err != nil {
return nil, err
} else if _, exists := t[n]; exists {
return nil, errors.Errorf("func.name = '%s' has already exists", m.Name)
} else {
t[n] = h
}
}
return t, nil
}
func MustHandlerTable(o interface{}) map[string]HandlerFunc {
t, err := NewHandlerTable(o)
if err != nil {
log.PanicError(err, "create redis handler map failed")
}
return t
}
func createHandlerFunc(o interface{}, f *reflect.Value) (HandlerFunc, error) {
t := f.Type()
arg0Type := reflect.TypeOf((*interface{})(nil)).Elem()
argsType := reflect.TypeOf([][]byte{})
if t.NumIn() != 3 || t.In(1) != arg0Type || t.In(2) != argsType {
return nil, errors.Errorf("register with invalid func type = '%s'", t)
}
ret0Type := reflect.TypeOf((*Resp)(nil)).Elem()
ret1Type := reflect.TypeOf((*error)(nil)).Elem()
if t.NumOut() != 2 || t.Out(0) != ret0Type || t.Out(1) != ret1Type {
return nil, errors.Errorf("register with invalid func type = '%s'", t)
}
return func(arg0 interface{}, args ...[]byte) (Resp, error) {
var arg0Value reflect.Value
if arg0 == nil {
arg0Value = reflect.ValueOf((*interface{})(nil))
} else {
arg0Value = reflect.ValueOf(arg0)
}
var input, output []reflect.Value
input = []reflect.Value{reflect.ValueOf(o), arg0Value, reflect.ValueOf(args)}
if t.IsVariadic() {
output = f.CallSlice(input)
} else {
output = f.Call(input)
}
var ret0 Resp
var ret1 error
if i := output[0].Interface(); i != nil {
ret0 = i.(Resp)
}
if i := output[1].Interface(); i != nil {
ret1 = i.(error)
}
return ret0, ret1
}, nil
}
func ParseArgs(resp Resp) (cmd string, args [][]byte, err error) {
a, err := AsArray(resp, nil)
if err != nil {
return "", nil, err
} else if len(a) == 0 {
return "", nil, errors.Errorf("empty array")
}
bs := make([][]byte, len(a))
for i := 0; i < len(a); i++ {
b, err := AsBulkBytes(a[i], nil)
if err != nil {
return "", nil, err
} else {
bs[i] = b
}
}
cmd = strings.ToLower(string(bs[0]))
if cmd == "" {
return "", nil, errors.Errorf("empty command")
}
return cmd, bs[1:], nil
}