forked from go-sanitize/sanitize
-
Notifications
You must be signed in to change notification settings - Fork 0
/
int.go
131 lines (113 loc) · 2.63 KB
/
int.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
package sanitize
import (
"fmt"
"reflect"
)
// sanitizeIntField sanitizes a int field. Requires the whole
// reflect.Value for the struct because it needs access to both the Value and
// Type of the struct.
func sanitizeIntField(s Sanitizer, structValue reflect.Value, idx int) error {
fieldValue := structValue.Field(idx)
tags := s.fieldTags(structValue.Type().Field(idx).Tag)
if fieldValue.Kind() == reflect.Ptr && !fieldValue.IsNil() {
fieldValue = fieldValue.Elem()
}
isSlice := fieldValue.Kind() == reflect.Slice
var fields []reflect.Value
if !isSlice {
fields = []reflect.Value{fieldValue}
} else {
for i := 0; i < fieldValue.Len(); i++ {
fields = append(fields, fieldValue.Index(i))
}
}
var err error
// Minimum value
_, hasMin := tags["min"]
min := int(0)
if hasMin {
min, err = parseInt(tags["min"])
if err != nil {
return err
}
}
// Maximum value
_, hasMax := tags["max"]
max := int(0)
if hasMax {
max, err = parseInt(tags["max"])
if err != nil {
return err
}
}
// Checking if minimum is not higher than maximum
if hasMax && hasMin && max < min {
return fmt.Errorf(
"max less than min on int field '%s' during struct sanitization",
fieldValue.Type().Name(),
)
}
// Checking if minimum and maximum are above 0
if (hasMin && min < 0) || (hasMax && max < 0) {
return fmt.Errorf(
"min and max on int field '%s' can not be below 0",
fieldValue.Type().Name(),
)
}
// Default value
_, hasDef := tags["def"]
def := int(0)
if hasDef {
def, err = parseInt(tags["def"])
if err != nil {
return err
}
// Making sure default is not smaller than min or higher than max
if hasMax && def > max {
return fmt.Errorf(
"incompatible def and max tag components, def (%+v) is "+
"higher than max (%+v)",
def,
max,
)
}
if hasMin && def < min {
return fmt.Errorf(
"incompatible def and min tag components, def (%+v) is "+
"lower than min (%+v)",
def,
min,
)
}
}
for _, field := range fields {
isPtr := field.Kind() == reflect.Ptr
// Pointer, nil, and we have a default: set it
if isPtr && field.IsNil() && hasDef {
field.Set(reflect.ValueOf(&def))
return nil
}
// Pointer, nil, and no default
if isPtr && field.IsNil() && !hasDef {
return nil
}
// Not nil pointer. Dereference then continue as normal
if isPtr && !field.IsNil() {
field = field.Elem()
}
// Apply min and max transforms
if hasMin {
oldNum := field.Int()
if min > int(oldNum) {
field.SetInt(int64(min))
}
}
if hasMax {
oldNum := field.Int()
if max < int(oldNum) {
field.SetInt(int64(max))
}
}
}
return nil
}