@@ -213,18 +213,62 @@ impl Step {
213213 if is_regex_or_expr {
214214 if let Some ( elem_ty) = find_first_slice ( & func. sig ) {
215215 let addon_parsing = Some ( quote ! {
216- let __cucumber_matches = __cucumber_ctx
216+ let mut __cucumber_matches = :: std:: vec:: Vec :: with_capacity(
217+ __cucumber_ctx. matches. len( ) . saturating_sub( 1 ) ,
218+ ) ;
219+ let mut __cucumber_iter = __cucumber_ctx
217220 . matches
218221 . iter( )
219222 . skip( 1 )
220- . enumerate( )
221- . map( |( i, s) | {
223+ . enumerate( ) ;
224+ while let Some ( ( i, ( cap_name, s) ) ) =
225+ __cucumber_iter. next( )
226+ {
227+ // Special handling of `cucumber-expressions`
228+ // `parameter` with multiple capturing groups.
229+ let prefix = cap_name
230+ . as_ref( )
231+ . filter( |n| n. starts_with( "__" ) )
232+ . map( |n| {
233+ let num_len = n
234+ . chars( )
235+ . skip( 2 )
236+ . take_while( |& c| c != '_' )
237+ . map( char :: len_utf8)
238+ . sum:: <usize >( ) ;
239+ let len = num_len + b"__" . len( ) ;
240+ n. split_at( len) . 0
241+ } ) ;
242+
243+ let to_take = __cucumber_iter
244+ . clone( )
245+ . take_while( |( _, ( n, _) ) | {
246+ prefix
247+ . zip( n. as_ref( ) )
248+ . filter( |( prefix, n) | n. starts_with( prefix) )
249+ . is_some( )
250+ } )
251+ . count( ) ;
252+
253+ let s = :: std:: iter:: once( s. as_str( ) )
254+ . chain(
255+ __cucumber_iter
256+ . by_ref( )
257+ . take( to_take)
258+ . map( |( _, ( _, s) ) | s. as_str( ) ) ,
259+ )
260+ . fold( None , |acc, s| {
261+ acc. or_else( || ( !s. is_empty( ) ) . then( || s) )
262+ } )
263+ . unwrap_or_default( ) ;
264+
265+ __cucumber_matches. push(
222266 s. parse:: <#elem_ty>( ) . unwrap_or_else( |e| panic!(
223267 "Failed to parse element at {} '{}': {}" ,
224268 i, s, e,
225269 ) )
226- } )
227- . collect :: < Vec <_>> ( ) ;
270+ ) ;
271+ }
228272 } ) ;
229273 let func_args = func
230274 . sig
@@ -319,11 +363,49 @@ impl Step {
319363 ) ;
320364
321365 quote ! {
322- let #ident = __cucumber_iter
323- . next( )
324- . expect( #not_found_err)
325- . parse:: <#ty>( )
326- . expect( #parsing_err) ;
366+ let #ident = {
367+ let ( cap_name, s) = __cucumber_iter
368+ . next( )
369+ . expect( #not_found_err) ;
370+ // Special handling of `cucumber-expressions` `parameter`
371+ // with multiple capturing groups.
372+ let prefix = cap_name
373+ . as_ref( )
374+ . filter( |n| n. starts_with( "__" ) )
375+ . map( |n| {
376+ let num_len = n
377+ . chars( )
378+ . skip( 2 )
379+ . take_while( |& c| c != '_' )
380+ . map( char :: len_utf8)
381+ . sum:: <usize >( ) ;
382+ let len = num_len + b"__" . len( ) ;
383+ n. split_at( len) . 0
384+ } ) ;
385+
386+ let to_take = __cucumber_iter
387+ . clone( )
388+ . take_while( |( n, _) | {
389+ prefix. zip( n. as_ref( ) )
390+ . filter( |( prefix, n) | n. starts_with( prefix) )
391+ . is_some( )
392+ } )
393+ . count( ) ;
394+
395+ :: std:: iter:: once( s. as_str( ) )
396+ . chain(
397+ __cucumber_iter
398+ . by_ref( )
399+ . take( to_take)
400+ . map( |( _, s) | s. as_str( ) ) ,
401+ )
402+ . fold(
403+ None ,
404+ |acc, s| acc. or_else( || ( !s. is_empty( ) ) . then( || s) ) ,
405+ )
406+ . unwrap_or_default( )
407+ } ;
408+ let #ident = #ident. parse:: <#ty>( ) . expect( #parsing_err) ;
327409 }
328410 } ;
329411
@@ -533,7 +615,7 @@ impl<'p> Parameters<'p> {
533615 self . 0
534616 . iter ( )
535617 . map ( |par| {
536- let name = par. param . 0 . fragment ( ) ;
618+ let name = par. param . input . fragment ( ) ;
537619 let ty = & par. ty ;
538620
539621 if DEFAULT_PARAMETERS . contains ( name) {
@@ -619,7 +701,7 @@ impl<'p> Parameters<'p> {
619701 . 0
620702 . iter ( )
621703 . filter_map ( |par| {
622- let name = par. param . 0 . fragment ( ) ;
704+ let name = par. param . input . fragment ( ) ;
623705 ( !DEFAULT_PARAMETERS . contains ( name) ) . then ( || ( * name, & par. ty ) )
624706 } )
625707 . unzip ( ) ;
0 commit comments