@@ -65,28 +65,12 @@ func (p *parser) popValue(typ reflect.Type) (reflect.Value, error) {
65
65
case reflect .TypeFor [map [string ]bool ]():
66
66
val , err := p .popSet ()
67
67
return reflect .ValueOf (val ), err
68
- case reflect .TypeFor [[]* regexp. Regexp ]():
69
- val , err := p .popList ()
68
+ case reflect .TypeFor [[]ByRegexOption ]():
69
+ val , err := p .popListRegexOption ()
70
70
if err != nil {
71
71
return reflect .Zero (typ ), err
72
72
}
73
-
74
- ret := make ([]* regexp.Regexp , len (val ))
75
- var errs []error
76
- for i , s := range val {
77
- regex , err := regexp .Compile (s )
78
- if err != nil {
79
- errs = append (errs , err )
80
- continue
81
- }
82
- ret [i ] = regex
83
- }
84
-
85
- if err := errors .Join (errs ... ); err != nil {
86
- return reflect .Zero (typ ), err
87
- }
88
-
89
- return reflect .ValueOf (ret ), nil
73
+ return reflect .ValueOf (val ), nil
90
74
}
91
75
92
76
panic (fmt .Errorf ("unhandled case in switch: %v" , typ ))
@@ -129,25 +113,78 @@ func (p *parser) popIntOrBool() (IntOrBool, error) {
129
113
return IntOrBool (i ), nil
130
114
}
131
115
132
- func (p * parser ) popList () ([]string , error ) {
116
+ func (ar * ByRegexOption ) UnmarshalYAML (node * yaml.Node ) error {
117
+ switch node .Tag {
118
+ case "!!str" :
119
+ pat , err := regexp .Compile (node .Value )
120
+ if err != nil {
121
+ return err
122
+ }
123
+ ar .Pattern = pat
124
+ ar .Template = nil
125
+ return nil
126
+ case "!!map" :
127
+ var m map [string ]string
128
+ if err := node .Decode (& m ); err != nil {
129
+ return err
130
+ }
131
+ if len (m ) != 1 {
132
+ return fmt .Errorf ("by_regex map item must have exactly one key-value pair, but got %d" , len (m ))
133
+ }
134
+ for pattern , template := range m {
135
+ pat , err := regexp .Compile (pattern )
136
+ if err != nil {
137
+ return fmt .Errorf ("invalid regex pattern %q: %w" , pattern , err )
138
+ }
139
+ ar .Pattern = pat
140
+ ar .Template = & template
141
+ return nil
142
+ }
143
+ }
144
+
145
+ return fmt .Errorf ("unexpected data type at %v" , node .Tag )
146
+ }
147
+
148
+ func popListValue [T any ](p * parser , parse func (string ) (T , error )) ([]T , error ) {
133
149
if p .allowYAMLLists {
134
150
val , rest , err := tryFindYAMLListAtStart (p .line )
135
151
if err != nil && ! errors .Is (err , errNotYAMLList ) {
136
152
return nil , err
137
153
}
138
154
if err == nil {
139
- p .line = rest
140
- return parseYAMLList (val )
155
+ p .line = strings . TrimSpace ( rest )
156
+ return parseYAMLList [ T ] (val )
141
157
}
142
-
143
- // err is errNotYAMLList, parse it as a regular list.
144
158
}
159
+
145
160
val , rest , _ := strings .Cut (p .line , " " )
146
- p .line = rest
161
+ p .line = strings . TrimSpace ( rest )
147
162
if val == "" {
148
- return []string {}, nil
163
+ return []T {}, nil
149
164
}
150
- return strings .Split (val , "," ), nil
165
+
166
+ var ret []T
167
+ var errs []error
168
+ for _ , item := range strings .Split (val , "," ) {
169
+ v , err := parse (item )
170
+ if err != nil {
171
+ errs = append (errs , err )
172
+ continue
173
+ }
174
+ ret = append (ret , v )
175
+ }
176
+ return ret , errors .Join (errs ... )
177
+ }
178
+
179
+ func (p * parser ) popList () ([]string , error ) {
180
+ return popListValue (p , func (s string ) (string , error ) { return s , nil })
181
+ }
182
+
183
+ func (p * parser ) popListRegexOption () ([]ByRegexOption , error ) {
184
+ return popListValue (p , func (s string ) (ByRegexOption , error ) {
185
+ pat , err := regexp .Compile (s )
186
+ return ByRegexOption {Pattern : pat }, err
187
+ })
151
188
}
152
189
153
190
func tryFindYAMLListAtStart (s string ) (list , rest string , err error ) {
@@ -210,11 +247,12 @@ loop:
210
247
return s [:iter .idx ], s [iter .idx :], nil
211
248
}
212
249
213
- func parseYAMLList (list string ) ([]string , error ) {
214
- var val []string
250
+ func parseYAMLList [ T any ] (list string ) ([]T , error ) {
251
+ var val []T
215
252
if err := yaml .Unmarshal ([]byte (list ), & val ); err != nil {
216
253
return nil , err
217
254
}
255
+
218
256
return val , nil
219
257
}
220
258
0 commit comments