forked from gocraft/meta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstring_slice.go
150 lines (124 loc) · 3.02 KB
/
string_slice.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
package meta
import (
"reflect"
"strings"
"unicode/utf8"
)
type StringSlice struct {
Val []string
Path string
}
type StringSliceOptions struct {
*StringOptions
*SliceOptions
}
func (i *StringSlice) ParseOptions(tag reflect.StructTag) interface{} {
var tempS String
opts := tempS.ParseOptions(tag)
// unlike String we want Blank to default to true so we can clean up input values like: a,b,c,,,d
stringOpts := opts.(*StringOptions)
stringOpts.Blank = true
if tag.Get("meta_blank") == "false" {
stringOpts.Blank = false
}
return &StringSliceOptions{
StringOptions: stringOpts,
SliceOptions: ParseSliceOptions(tag),
}
}
func (n *StringSlice) JSONValue(path string, i interface{}, options interface{}) Errorable {
n.Path = path
n.Val = nil
if i == nil {
return ErrBlank
}
var errorsInSlice ErrorSlice
switch value := i.(type) {
case string:
return n.FormValue(value, options)
case []interface{}:
if len(value) == 0 {
return ErrBlank
}
opts := options.(*StringSliceOptions)
stringOpts := opts.StringOptions
sliceOpts := opts.SliceOptions
if sliceOpts.MinLengthPresent && len(value) < sliceOpts.MinLength {
return ErrMinLength
}
if sliceOpts.MaxLengthPresent && len(value) > sliceOpts.MaxLength {
return ErrMaxLength
}
for _, v := range value {
var s String
if err := s.JSONValue("", v, stringOpts); err != nil {
errorsInSlice = append(errorsInSlice, err)
if err == ErrBlank && !opts.DiscardBlank {
n.Val = append(n.Val, s.Val)
}
} else {
if !opts.DiscardBlank || s.Val != "" {
errorsInSlice = append(errorsInSlice, nil)
n.Val = append(n.Val, s.Val)
}
}
}
if errorsInSlice.Len() > 0 {
return errorsInSlice
}
}
return nil
}
func (i *StringSlice) FormValue(value string, options interface{}) Errorable {
if !utf8.ValidString(value) {
return ErrUtf8
}
if value == "" {
return ErrBlank
}
var tempS String
opts := options.(*StringSliceOptions)
stringOpts := opts.StringOptions
sliceOpts := opts.SliceOptions
strs := strings.Split(value, ",")
if sliceOpts.MinLengthPresent && len(strs) < sliceOpts.MinLength {
return ErrMinLength
}
if sliceOpts.MaxLengthPresent && len(strs) > sliceOpts.MaxLength {
return ErrMaxLength
}
var errorsInSlice ErrorSlice
for _, s := range strs {
tempS.Val = ""
if err := tempS.FormValue(s, stringOpts); err != nil {
errorsInSlice = append(errorsInSlice, err)
if err == ErrBlank && !opts.DiscardBlank {
i.Val = append(i.Val, tempS.Val)
}
} else {
if !opts.DiscardBlank || tempS.Val != "" {
errorsInSlice = append(errorsInSlice, nil)
i.Val = append(i.Val, tempS.Val)
}
}
}
if errorsInSlice.Len() > 0 {
return errorsInSlice
}
return nil
}
func (s StringSlice) MarshalJSON() ([]byte, error) {
if len(s.Val) > 0 {
return MetaJson.Marshal(s.Val)
}
return nullString, nil
}
func (s *StringSlice) UnmarshalJSON(data []byte) error {
var value []string
err := MetaJson.Unmarshal(data, &value)
if err != nil {
return err
}
*s = StringSlice{Val: value}
return nil
}