-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathinput.go
82 lines (72 loc) · 1.8 KB
/
input.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 play
import (
"errors"
"reflect"
"strings"
"sync"
"github.com/leochen2038/play/codec/binders"
)
type Input struct {
binder binders.Binder
exValues sync.Map
}
func NewInput(binder binders.Binder) Input {
return Input{binder: binder}
}
func (input *Input) Binder() binders.Binder {
return input.binder
}
func (input *Input) SetBinder(binder binders.Binder) {
input.binder = binder
}
func (input *Input) SetValue(key string, val interface{}) {
input.exValues.Store(key, val)
}
func (input *Input) Value(key string) interface{} {
if exValue, ok := input.exValues.Load(key); ok {
return exValue
} else {
if input.binder != nil {
return input.binder.Get(key)
}
return nil
}
}
func (input *Input) Bind(v reflect.Value) (err error) {
if v.CanSet() {
var tField reflect.StructField
var vField reflect.Value
var fieldCount = v.Type().NumField()
for i := 0; i < fieldCount; i++ {
if vField, tField = v.Field(i), v.Type().Field(i); !vField.CanInterface() {
continue
}
key := tField.Tag.Get("key")
if key == "" {
key = tField.Name
}
for _, key := range strings.Split(key, ",") {
if exValue, ok := input.exValues.Load(key); ok {
if tField.Type.String() != reflect.TypeOf(exValue).String() {
return errors.New("input custom " + key + " type need " + tField.Type.String() + " but " + reflect.TypeOf(exValue).String() + " given")
}
vField.Set(reflect.ValueOf(exValue))
goto NEXT
}
}
if input.binder != nil {
if err = input.binder.Bind(vField, tField); err != nil {
return err
}
} else {
if defval := tField.Tag.Get("default"); defval != "" {
vField.Set(reflect.ValueOf(defval))
} else {
return errors.New("input: " + key + " <" + tField.Tag.Get("note") + "> is required")
}
}
NEXT:
}
}
return
}