@@ -65,28 +65,12 @@ func (p *parser) popValue(typ reflect.Type) (reflect.Value, error) {
6565 case reflect .TypeFor [map [string ]bool ]():
6666 val , err := p .popSet ()
6767 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 ()
7070 if err != nil {
7171 return reflect .Zero (typ ), err
7272 }
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
9074 }
9175
9276 panic (fmt .Errorf ("unhandled case in switch: %v" , typ ))
@@ -129,25 +113,78 @@ func (p *parser) popIntOrBool() (IntOrBool, error) {
129113 return IntOrBool (i ), nil
130114}
131115
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 ) {
133149 if p .allowYAMLLists {
134150 val , rest , err := tryFindYAMLListAtStart (p .line )
135151 if err != nil && ! errors .Is (err , errNotYAMLList ) {
136152 return nil , err
137153 }
138154 if err == nil {
139- p .line = rest
140- return parseYAMLList (val )
155+ p .line = strings . TrimSpace ( rest )
156+ return parseYAMLList [ T ] (val )
141157 }
142-
143- // err is errNotYAMLList, parse it as a regular list.
144158 }
159+
145160 val , rest , _ := strings .Cut (p .line , " " )
146- p .line = rest
161+ p .line = strings . TrimSpace ( rest )
147162 if val == "" {
148- return []string {}, nil
163+ return []T {}, nil
149164 }
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+ })
151188}
152189
153190func tryFindYAMLListAtStart (s string ) (list , rest string , err error ) {
@@ -210,11 +247,12 @@ loop:
210247 return s [:iter .idx ], s [iter .idx :], nil
211248}
212249
213- func parseYAMLList (list string ) ([]string , error ) {
214- var val []string
250+ func parseYAMLList [ T any ] (list string ) ([]T , error ) {
251+ var val []T
215252 if err := yaml .Unmarshal ([]byte (list ), & val ); err != nil {
216253 return nil , err
217254 }
255+
218256 return val , nil
219257}
220258
0 commit comments