@@ -525,6 +525,29 @@ impl ResourceDef {
525
525
}
526
526
}
527
527
528
+ /// Joins two resources.
529
+ ///
530
+ /// Resulting resource is prefix if `other` is prefix.
531
+ ///
532
+ /// # Examples
533
+ /// ```
534
+ /// # use actix_router::ResourceDef;
535
+ /// let joined = ResourceDef::prefix("/root").join(&ResourceDef::prefix("/seg"));
536
+ /// assert_eq!(joined, ResourceDef::prefix("/root/seg"));
537
+ /// ```
538
+ pub fn join ( & self , other : & ResourceDef ) -> ResourceDef {
539
+ let patterns = self
540
+ . pattern_iter ( )
541
+ . flat_map ( move |this| other. pattern_iter ( ) . map ( move |other| ( this, other) ) )
542
+ . map ( |( this, other) | [ this, other] . join ( "" ) )
543
+ . collect :: < Vec < _ > > ( ) ;
544
+
545
+ match patterns. len ( ) {
546
+ 1 => ResourceDef :: from_single_pattern ( & patterns[ 0 ] , other. is_prefix ( ) ) ,
547
+ _ => ResourceDef :: new ( patterns) ,
548
+ }
549
+ }
550
+
528
551
/// Returns `true` if `path` matches this resource.
529
552
///
530
553
/// The behavior of this method depends on how the `ResourceDef` was constructed. For example,
@@ -1636,6 +1659,51 @@ mod tests {
1636
1659
assert_eq ! ( re. find_match( "/abc/def" ) , result) ;
1637
1660
}
1638
1661
1662
+ #[ test]
1663
+ fn join ( ) {
1664
+ // test joined defs match the same paths as each component separately
1665
+
1666
+ fn seq_find_match ( re1 : & ResourceDef , re2 : & ResourceDef , path : & str ) -> Option < usize > {
1667
+ let len1 = re1. find_match ( path) ?;
1668
+ let len2 = re2. find_match ( & path[ len1..] ) ?;
1669
+ Some ( len1 + len2)
1670
+ }
1671
+
1672
+ macro_rules! join_test {
1673
+ ( $pat1: expr, $pat2: expr => $( $test: expr) ,+) => { {
1674
+ let pat1 = $pat1;
1675
+ let pat2 = $pat2;
1676
+ $( {
1677
+ let _path = $test;
1678
+ let ( re1, re2) = ( ResourceDef :: prefix( pat1) , ResourceDef :: new( pat2) ) ;
1679
+ let _seq = seq_find_match( & re1, & re2, _path) ;
1680
+ let _join = re1. join( & re2) . find_match( _path) ;
1681
+ assert_eq!(
1682
+ _seq, _join,
1683
+ "patterns: prefix {:?}, {:?}; mismatch on \" {}\" ; seq={:?}; join={:?}" ,
1684
+ pat1, pat2, _path, _seq, _join
1685
+ ) ;
1686
+ assert!( !re1. join( & re2) . is_prefix( ) ) ;
1687
+
1688
+ let ( re1, re2) = ( ResourceDef :: prefix( pat1) , ResourceDef :: prefix( pat2) ) ;
1689
+ let _seq = seq_find_match( & re1, & re2, _path) ;
1690
+ let _join = re1. join( & re2) . find_match( _path) ;
1691
+ assert_eq!(
1692
+ _seq, _join,
1693
+ "patterns: prefix {:?}, prefix {:?}; mismatch on \" {}\" ; seq={:?}; join={:?}" ,
1694
+ pat1, pat2, _path, _seq, _join
1695
+ ) ;
1696
+ assert!( re1. join( & re2) . is_prefix( ) ) ;
1697
+ } ) +
1698
+ } }
1699
+ }
1700
+
1701
+ join_test ! ( "" , "" => "" , "/hello" , "/" ) ;
1702
+ join_test ! ( "/user" , "" => "" , "/user" , "/user/123" , "/user11" , "user" , "user/123" ) ;
1703
+ join_test ! ( "" , "/user" => "" , "/user" , "foo" , "/user11" , "user" , "user/123" ) ;
1704
+ join_test ! ( "/user" , "/xx" => "" , "" , "/" , "/user" , "/xx" , "/userxx" , "/user/xx" ) ;
1705
+ }
1706
+
1639
1707
#[ test]
1640
1708
fn match_methods_agree ( ) {
1641
1709
macro_rules! match_methods_agree {
0 commit comments