-
Notifications
You must be signed in to change notification settings - Fork 1
/
handler_creator.go
163 lines (151 loc) · 5.01 KB
/
handler_creator.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright The Jet authors. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package handler
import (
"github.com/fengyuan-liang/jet-web-fasthttp/core/context"
"github.com/fengyuan-liang/jet-web-fasthttp/core/hook"
"github.com/fengyuan-liang/jet-web-fasthttp/pkg/xlog"
"reflect"
"syscall"
)
// ---------------------------------------------------------------------------
// CreatorFunc define func of HandlerCreator
type CreatorFunc = func(rcvr *reflect.Value, method *reflect.Method) (IHandler, error)
type HandlerCreator struct {
MethodPrefix string
Creator CreatorFunc
}
var unusedError *error
var unusedCtx *context.Ctx
var typeOfError = reflect.TypeOf(unusedError).Elem()
var typeOfCtx = reflect.TypeOf(unusedCtx).Elem()
type contextType int
type parametersType int
type returnValuesType int
const (
noCtx contextType = iota
defaultCtx
customCtx
)
const (
noParameter parametersType = iota
oneParameterAndFirstIsCtx // only one parameter and parameter are ctx
oneParameterAndFirstNotIsCtx // only one parameter and parameter not are ctx
twoParameterAndFirstIsCtx // two parameters and the first parameter is ctx
twoParameterAndSecondIsCtx // two parameters and the second parameter are ctx
)
const (
noReturnValue returnValuesType = iota
OneReturnValueAndIsError // only return value and is error
OneReturnValueAndNotError // only return value and not an error
twoReturnValueAndFirstIsError // two return value and the first is error
twoReturnValueAndSecondIsError // two return value and the second is error
)
var handlerCreatorLog = xlog.NewWith("handle_create_log")
// New common creator
// Method spec:
//
// (rcvr *XXXX) YYYY(ctx jet.Ctx, req ZZZZ) (err error)
// (rcvr *XXXX) YYYY(ctx jet.Ctx, req ZZZZ) (ret RRRR, err error)
// (rcvr *XXXX) YYYY(ctx jet.Ctx, req ZZZZ)
// (rcvr *XXXX) YYYY(ctx jet.Ctx, req ZZZZ) (ret RRRR, err error)
// (rcvr *XXXX) YYYY(ctx jet.Ctx, req ZZZZ) (err error)
// (rcvr *XXXX) YYYY(ctx jet.Ctx) (err error)
// (rcvr *XXXX) YYYY(ctx jet.Ctx) (ret RRRR, err error)
// (rcvr *XXXX) YYYY() (err error)
// (rcvr *XXXX) YYYY() (ret RRRR, err error)
func (p HandlerCreator) New(rcvr *reflect.Value, method *reflect.Method) (IHandler, error) {
var (
mtype = method.Type
methodNumIn = mtype.NumIn() - 1
methodNumOut = mtype.NumOut()
methodName = method.Name
ctxType = noCtx
parameterType = noParameter
returnValueType = noReturnValue
)
// only allow up to two parameters
if methodNumIn > 2 {
handlerCreatorLog.Errorf("too many parameters, Method [%s] exceeds the default limit", methodName)
return nil, syscall.EINVAL
}
// only allow up to two return values allowed
if methodNumOut > 2 {
handlerCreatorLog.Errorf("too many return values, Method [%s] exceeds the default limit", methodName)
return nil, syscall.EINVAL
}
switch methodNumIn {
case 1:
in := mtype.In(1)
if in.Kind() == reflect.Ptr {
if in.Implements(typeOfCtx) {
ctxType++
parameterType = oneParameterAndFirstIsCtx
} else {
parameterType = oneParameterAndFirstNotIsCtx
}
} else if in.Kind() == reflect.Struct || in.Kind() == reflect.Interface {
if in == typeOfCtx || in.Implements(typeOfCtx) {
parameterType = oneParameterAndFirstIsCtx
}
} else {
parameterType = oneParameterAndFirstNotIsCtx
}
case 2:
firstIn, secondIn := mtype.In(1), mtype.In(2)
if firstIn.Kind() == reflect.Ptr {
firstIn = firstIn.Elem()
}
if secondIn.Kind() == reflect.Ptr {
secondIn = secondIn.Elem()
}
if firstIn.Implements(typeOfCtx) {
ctxType++
parameterType = twoParameterAndFirstIsCtx
} else if secondIn.Implements(typeOfCtx) {
ctxType++
parameterType = twoParameterAndSecondIsCtx
}
}
// NumOut
switch methodNumOut {
case 1:
out := mtype.Out(0)
if out.Kind() == reflect.Ptr {
if out.Implements(typeOfError) {
returnValueType = OneReturnValueAndIsError
} else {
returnValueType = OneReturnValueAndNotError
}
} else if out == typeOfError {
returnValueType = OneReturnValueAndIsError
} else {
returnValueType = OneReturnValueAndNotError
}
case 2:
firstOut, secondOut := mtype.Out(0), mtype.Out(1)
if firstOut.Kind() == reflect.Ptr {
if firstOut.Implements(typeOfError) {
returnValueType = twoReturnValueAndFirstIsError
}
} else if firstOut == typeOfError {
returnValueType = twoReturnValueAndFirstIsError
}
if secondOut.Kind() == reflect.Ptr {
if firstOut.Implements(typeOfError) {
returnValueType = twoReturnValueAndSecondIsError
}
} else if secondOut == typeOfError {
returnValueType = twoReturnValueAndSecondIsError
}
}
return &handler{
rcvr: rcvr,
method: method,
ctxType: ctxType,
parametersType: parameterType,
returnValuesType: returnValueType,
hook: new(hook.Hook),
}, nil
}