@@ -481,148 +481,157 @@ impl<T> Node<T> {
481481 let mut path = full_path;
482482 let mut backtracking = false ;
483483 let mut params = Params :: new ( ) ;
484- let mut skipped_nodes = Vec :: new ( ) ;
484+ let mut skipped_nodes: Vec < Skipped < ' _ , ' _ , T > > = Vec :: new ( ) ;
485485
486486 ' walk: loop {
487+ // Initialize the backtracker.
487488 backtracker ! ( skipped_nodes, path, current, params, backtracking, ' walk) ;
488489
489- // The path is longer than this node's prefix, search deeper.
490- if path. len ( ) > current. prefix . len ( ) {
491- let ( prefix, rest) = path. split_at ( current. prefix . len ( ) ) ;
492-
493- // Found a matching prefix.
494- if * prefix == * current. prefix {
495- let first = rest[ 0 ] ;
496- let consumed = path;
497- path = rest;
498-
499- // If we are currently backtracking, avoid searching static children
500- // that we already searched.
501- if !backtracking {
502- // Find a child node that matches the next character in the path.
503- if let Some ( i) = current. indices . iter ( ) . position ( |& c| c == first) {
504- // Keep track of wildcard routes that we skip.
505- //
506- // We may end up needing to backtrack later in case we do not find a
507- // match.
508- if current. wild_child {
509- skipped_nodes. push ( Skipped {
510- path : consumed,
511- node : current,
512- params : params. len ( ) ,
513- } ) ;
514- }
515-
516- // Continue searching.
517- current = & current. children [ i] ;
518- continue ' walk;
519- }
490+ // Reached the end of the search.
491+ if path. len ( ) <= current. prefix . len ( ) {
492+ // Check for an exact match.
493+ if * path == * current. prefix {
494+ // Found the matching value.
495+ if let Some ( ref value) = current. value {
496+ // Remap the keys of any route parameters we accumulated during the search.
497+ params. for_each_key_mut ( |( i, key) | * key = & current. remapping [ i] ) ;
498+ return Ok ( ( value, params) ) ;
520499 }
500+ }
521501
522- // We didn't find a matching static child.
523- //
524- // If there are no wildcards, then there are no matching routes in the tree.
525- if !current. wild_child {
526- // Try backtracking in case we skipped a wildcard that may match.
527- try_backtrack ! ( ) ;
528- return Err ( MatchError :: NotFound ) ;
529- }
502+ // Try backtracking in case we skipped a wildcard that may match.
503+ try_backtrack ! ( ) ;
530504
531- // Continue searching in the wildcard, which are kept at the end of the list.
532- current = current. children . last ( ) . unwrap ( ) ;
533- match current. node_type {
534- // Match against a route parameter.
535- NodeType :: Param => {
536- // Check for more path segments.
537- match path. iter ( ) . position ( |& c| c == b'/' ) {
538- // Found another segment.
539- Some ( i) => {
540- let ( param, rest) = path. split_at ( i) ;
541-
542- // If there is a static child, continue the search.
543- if let [ child] = current. children . as_slice ( ) {
544- // Store the parameter value.
545- //
546- // Parameters are normalized so the key is irrelevant at this point.
547- params. push ( b"" , param) ;
548-
549- // Continue searching.
550- path = rest;
551- current = child;
552- backtracking = false ;
553- continue ' walk;
554- }
505+ // Otherwise, there are no matching routes in the tree.
506+ return Err ( MatchError :: NotFound ) ;
507+ }
555508
556- // Try backtracking in case we skipped a wildcard that may match .
557- try_backtrack ! ( ) ;
509+ // Otherwise, the path is longer than this node's prefix, search deeper .
510+ let ( prefix , rest ) = path . split_at ( current . prefix . len ( ) ) ;
558511
559- // Otherwise, there are no matching routes in the tree.
560- return Err ( MatchError :: NotFound ) ;
561- }
562- // This is the last path segment.
563- None => {
564- // Found the matching value.
565- if let Some ( ref value) = current. value {
566- // Store the parameter value.
567- params. push ( b"" , path) ;
512+ // The prefix does not match.
513+ if * prefix != * current. prefix {
514+ // Try backtracking in case we skipped a wildcard that may match.
515+ try_backtrack ! ( ) ;
568516
569- // Remap the keys of any route parameters we accumulated during the search.
570- params. for_each_key_mut ( |( i, key) | {
571- * key = & current. remapping [ i]
572- } ) ;
517+ // Otherwise, there are no matching routes in the tree.
518+ return Err ( MatchError :: NotFound ) ;
519+ }
520+
521+ let previous = path;
522+ path = rest;
573523
574- return Ok ( ( value, params) ) ;
575- }
524+ // If we are currently backtracking, avoid searching static children
525+ // that we already searched.
526+ if !backtracking {
527+ let next = path[ 0 ] ;
576528
529+ // Find a child node that matches the next character in the path.
530+ if let Some ( i) = current. indices . iter ( ) . position ( |& c| c == next) {
531+ // Keep track of wildcard routes that we skip.
532+ //
533+ // We may end up needing to backtrack later in case we do not find a
534+ // match.
535+ if current. wild_child {
536+ skipped_nodes. push ( Skipped {
537+ path : previous,
538+ node : current,
539+ params : params. len ( ) ,
540+ } ) ;
541+ }
542+
543+ // Continue searching.
544+ current = & current. children [ i] ;
545+ continue ' walk;
546+ }
547+ }
548+
549+ // We didn't find a matching static child.
550+ //
551+ // If there are no wildcards, then there are no matching routes in the tree.
552+ if !current. wild_child {
553+ // Try backtracking in case we skipped a wildcard that may match.
554+ try_backtrack ! ( ) ;
555+ return Err ( MatchError :: NotFound ) ;
556+ }
557+
558+ // Continue searching in the wildcard child, which is kept at the end of the list.
559+ current = current. children . last ( ) . unwrap ( ) ;
560+ match current. node_type {
561+ // Match against a route parameter.
562+ NodeType :: Param => {
563+ // Check for more path segments.
564+ let i = match path. iter ( ) . position ( |& c| c == b'/' ) {
565+ // Found another segment.
566+ Some ( i) => i,
567+ // This is the last path segment.
568+ None => {
569+ let value = match current. value {
570+ // Found the matching value.
571+ Some ( ref value) => value,
572+ None => {
577573 // Try backtracking in case we skipped a wildcard that may match.
578574 try_backtrack ! ( ) ;
579575
580576 // Otherwise, there are no matching routes in the tree.
581577 return Err ( MatchError :: NotFound ) ;
582578 }
583- }
584- }
585- NodeType :: CatchAll => {
586- // Catch-all segments are only allowed at the end of the route.
587- //
588- // This node must contain the value if there is a match.
589- return match current. value {
590- // Found the value.
591- Some ( ref value) => {
592- // Remap the keys of any route parameters we accumulated during the search.
593- params
594- . for_each_key_mut ( |( i, key) | * key = & current. remapping [ i] ) ;
595-
596- // Store the final catch-all parameter (`{*...}`).
597- let key = & current. prefix [ 2 ..current. prefix . len ( ) - 1 ] ;
598- params. push ( key, path) ;
599-
600- Ok ( ( value, params) )
601- }
602- // Otherwise, there are no matching routes in the tree.
603- None => Err ( MatchError :: NotFound ) ,
604579 } ;
580+
581+ // Store the parameter value.
582+ // Parameters are normalized so the key is irrelevant for now.
583+ params. push ( b"" , path) ;
584+
585+ // Remap the keys of any route parameters we accumulated during the search.
586+ params. for_each_key_mut ( |( i, key) | * key = & current. remapping [ i] ) ;
587+
588+ return Ok ( ( value, params) ) ;
605589 }
606- _ => unreachable ! ( ) ,
590+ } ;
591+
592+ // Found another path segment.
593+ let ( param, rest) = path. split_at ( i) ;
594+
595+ // If there is a static child, continue the search.
596+ if let [ child] = current. children . as_slice ( ) {
597+ // Store the parameter value.
598+ // Parameters are normalized so the key is irrelevant for now.
599+ params. push ( b"" , param) ;
600+
601+ // Continue searching.
602+ path = rest;
603+ current = child;
604+ backtracking = false ;
605+ continue ' walk;
607606 }
607+
608+ // Try backtracking in case we skipped a wildcard that may match.
609+ try_backtrack ! ( ) ;
610+
611+ // Otherwise, there are no matching routes in the tree.
612+ return Err ( MatchError :: NotFound ) ;
608613 }
609- }
614+ NodeType :: CatchAll => {
615+ // Catch-all segments are only allowed at the end of the route, meaning
616+ // this node must contain the value.
617+ let value = match current. value {
618+ // Found the matching value.
619+ Some ( ref value) => value,
620+ // Otherwise, there are no matching routes in the tree.
621+ None => return Err ( MatchError :: NotFound ) ,
622+ } ;
610623
611- // Check for an exact match.
612- if * path == * current. prefix {
613- // Found the matching value.
614- if let Some ( ref value) = current. value {
615624 // Remap the keys of any route parameters we accumulated during the search.
616625 params. for_each_key_mut ( |( i, key) | * key = & current. remapping [ i] ) ;
626+
627+ // Store the final catch-all parameter (`{*...}`).
628+ let key = & current. prefix [ 2 ..current. prefix . len ( ) - 1 ] ;
629+ params. push ( key, path) ;
630+
617631 return Ok ( ( value, params) ) ;
618632 }
633+ _ => unreachable ! ( ) ,
619634 }
620-
621- // Try backtracking in case we skipped a wildcard that may match.
622- try_backtrack ! ( ) ;
623-
624- // Otherwise, there are no matching routes in the tree.
625- return Err ( MatchError :: NotFound ) ;
626635 }
627636 }
628637
0 commit comments