form - processors.go
1 package form
2
3 import (
4 "math"
5 "reflect"
6 "regexp"
7 "strconv"
8 )
9
10 type processor interface {
11 process(reflect.Value, []string) error
12 }
13
14 type inum struct {
15 min, max int64
16 bits int
17 }
18
19 func newInum(tags reflect.StructTag, bits int) inum {
20 i := inum{
21 min: math.MinInt64,
22 max: math.MaxInt64,
23 bits: bits,
24 }
25 if m := tags.Get("min"); m != "" {
26 im, err := strconv.ParseInt(m, 10, bits)
27 if err == nil {
28 i.min = im
29 }
30 }
31 if m := tags.Get("max"); m != "" {
32 im, err := strconv.ParseInt(m, 10, bits)
33 if err == nil {
34 i.max = im
35 }
36 }
37 return i
38 }
39
40 func (i inum) process(v reflect.Value, data []string) error {
41 num, err := strconv.ParseInt(data[0], 10, i.bits)
42 if err != nil {
43 return err
44 }
45 if num < i.min || num > i.max {
46 return ErrNotInRange
47 }
48 v.SetInt(num)
49 return nil
50 }
51
52 type unum struct {
53 min, max uint64
54 bits int
55 }
56
57 func newUnum(tags reflect.StructTag, bits int) unum {
58 u := unum{
59 max: math.MaxUint64,
60 bits: bits,
61 }
62 if m := tags.Get("min"); m != "" {
63 um, err := strconv.ParseUint(m, 10, bits)
64 if err == nil {
65 u.min = um
66 }
67 }
68 if m := tags.Get("max"); m != "" {
69 um, err := strconv.ParseUint(m, 10, bits)
70 if err == nil {
71 u.max = um
72 }
73 }
74 return u
75 }
76
77 func (u unum) process(v reflect.Value, data []string) error {
78 num, err := strconv.ParseUint(data[0], 10, u.bits)
79 if err != nil {
80 return err
81 }
82 if num < u.min || num > u.max {
83 return ErrNotInRange
84 }
85 v.SetUint(num)
86 return nil
87 }
88
89 type float struct {
90 min, max float64
91 bits int
92 }
93
94 func newFloat(tags reflect.StructTag, bits int) float {
95 f := float{
96 min: -math.MaxFloat64,
97 max: math.MaxFloat64,
98 bits: bits,
99 }
100 if m := tags.Get("min"); m != "" {
101 um, err := strconv.ParseFloat(m, bits)
102 if err == nil {
103 f.min = um
104 }
105 }
106 if m := tags.Get("max"); m != "" {
107 um, err := strconv.ParseFloat(m, bits)
108 if err == nil {
109 f.max = um
110 }
111 }
112 return f
113 }
114
115 func (f float) process(v reflect.Value, data []string) error {
116 num, err := strconv.ParseFloat(data[0], f.bits)
117 if err != nil {
118 return err
119 }
120 if num < f.min || num > f.max {
121 return ErrNotInRange
122 }
123 v.SetFloat(num)
124 return nil
125 }
126
127 type str struct {
128 regex *regexp.Regexp
129 }
130
131 func newString(tags reflect.StructTag) str {
132 if r := tags.Get("regex"); r != "" {
133 if re, err := regexp.Compile(r); err == nil {
134 return str{
135 regex: re,
136 }
137 }
138 }
139 return str{}
140 }
141
142 func (s str) process(v reflect.Value, data []string) error {
143 if s.regex != nil {
144 if !s.regex.MatchString(data[0]) {
145 return ErrNoMatch
146 }
147 }
148 v.SetString(data[0])
149 return nil
150 }
151
152 type boolean struct{}
153
154 func matchString(a string, b []byte) bool {
155 if len(a) != len(b) {
156 return false
157 }
158 for n, c := range b {
159 if a[n]|32 != c {
160 return false
161 }
162 }
163 return true
164 }
165
166 var (
167 trues = [...][]byte{
168 {'1'},
169 {'y'},
170 {'t'},
171 {'o', 'n'},
172 {'y', 'e', 's'},
173 {'t', 'r', 'u', 'e'},
174 }
175 falses = [...][]byte{
176 {'0'},
177 {'n'},
178 {'g'},
179 {'o', 'f', 'f'},
180 {'n', 'o'},
181 {'f', 'a', 'l', 's', 'e'},
182 }
183 )
184
185 func (boolean) process(v reflect.Value, data []string) error {
186 for _, b := range trues {
187 if matchString(data[0], b) {
188 v.SetBool(true)
189 return nil
190 }
191 }
192 for _, b := range falses {
193 if matchString(data[0], b) {
194 v.SetBool(false)
195 return nil
196 }
197 }
198 return ErrInvalidBoolean
199 }
200
201 type slice struct {
202 processor
203 typ reflect.Type
204 }
205
206 func (s slice) process(v reflect.Value, data []string) error {
207 if v.Cap() >= len(data) {
208 v.SetLen(len(data))
209 } else {
210 v.Set(reflect.MakeSlice(s.typ, len(data), len(data)))
211 }
212 var errs Errors
213 for n := range data {
214 if err := s.processor.process(v.Index(n), data[n:]); err != nil {
215 if errs == nil {
216 errs = make(Errors, len(data))
217 }
218 errs[n] = err
219 }
220 }
221 if len(errs) > 0 {
222 return errs
223 }
224 return nil
225 }
226
227 type pointer struct {
228 processor
229 typ reflect.Type
230 }
231
232 func (p pointer) process(v reflect.Value, data []string) error {
233 pv := reflect.New(p.typ)
234 if err := p.processor.process(pv.Elem(), data); err != nil {
235 return err
236 }
237 v.Set(pv)
238 return nil
239 }
240
241 type formParser interface {
242 ParseForm([]string) error
243 }
244
245 type inter bool
246
247 func (i inter) process(v reflect.Value, data []string) error {
248 if i {
249 v = v.Addr()
250 }
251 return v.Interface().(formParser).ParseForm(data)
252 }