@@ -962,16 +962,49 @@ impl cmp::Eq for Components<'_> {}
962
962
impl < ' a > cmp:: PartialOrd for Components < ' a > {
963
963
#[ inline]
964
964
fn partial_cmp ( & self , other : & Components < ' a > ) -> Option < cmp:: Ordering > {
965
- Iterator :: partial_cmp ( self . clone ( ) , other. clone ( ) )
965
+ Some ( compare_components ( self . clone ( ) , other. clone ( ) ) )
966
966
}
967
967
}
968
968
969
969
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
970
970
impl cmp:: Ord for Components < ' _ > {
971
971
#[ inline]
972
972
fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
973
- Iterator :: cmp ( self . clone ( ) , other. clone ( ) )
973
+ compare_components ( self . clone ( ) , other. clone ( ) )
974
+ }
975
+ }
976
+
977
+ fn compare_components ( mut left : Components < ' _ > , mut right : Components < ' _ > ) -> cmp:: Ordering {
978
+ // Fast path for long shared prefixes
979
+ //
980
+ // - compare raw bytes to find first mismatch
981
+ // - backtrack to find separator before mismatch to avoid ambiguous parsings of '.' or '..' characters
982
+ // - if found update state to only do a component-wise comparison on the remainder,
983
+ // otherwise do it on the full path
984
+ //
985
+ // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into
986
+ // the middle of one
987
+ if left. prefix . is_none ( ) && right. prefix . is_none ( ) && left. front == right. front {
988
+ // this might benefit from a [u8]::first_mismatch simd implementation, if it existed
989
+ let first_difference =
990
+ match left. path . iter ( ) . zip ( right. path . iter ( ) ) . position ( |( & a, & b) | a != b) {
991
+ None if left. path . len ( ) == right. path . len ( ) => return cmp:: Ordering :: Equal ,
992
+ None => left. path . len ( ) . min ( right. path . len ( ) ) ,
993
+ Some ( diff) => diff,
994
+ } ;
995
+
996
+ if let Some ( previous_sep) =
997
+ left. path [ ..first_difference] . iter ( ) . rposition ( |& b| left. is_sep_byte ( b) )
998
+ {
999
+ let mismatched_component_start = previous_sep + 1 ;
1000
+ left. path = & left. path [ mismatched_component_start..] ;
1001
+ left. front = State :: Body ;
1002
+ right. path = & right. path [ mismatched_component_start..] ;
1003
+ right. front = State :: Body ;
1004
+ }
974
1005
}
1006
+
1007
+ Iterator :: cmp ( left, right)
975
1008
}
976
1009
977
1010
/// An iterator over [`Path`] and its ancestors.
@@ -1704,15 +1737,15 @@ impl cmp::Eq for PathBuf {}
1704
1737
impl cmp:: PartialOrd for PathBuf {
1705
1738
#[ inline]
1706
1739
fn partial_cmp ( & self , other : & PathBuf ) -> Option < cmp:: Ordering > {
1707
- self . components ( ) . partial_cmp ( other. components ( ) )
1740
+ Some ( compare_components ( self . components ( ) , other. components ( ) ) )
1708
1741
}
1709
1742
}
1710
1743
1711
1744
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1712
1745
impl cmp:: Ord for PathBuf {
1713
1746
#[ inline]
1714
1747
fn cmp ( & self , other : & PathBuf ) -> cmp:: Ordering {
1715
- self . components ( ) . cmp ( other. components ( ) )
1748
+ compare_components ( self . components ( ) , other. components ( ) )
1716
1749
}
1717
1750
}
1718
1751
@@ -2686,7 +2719,7 @@ impl fmt::Display for Display<'_> {
2686
2719
impl cmp:: PartialEq for Path {
2687
2720
#[ inline]
2688
2721
fn eq ( & self , other : & Path ) -> bool {
2689
- self . components ( ) . eq ( other. components ( ) )
2722
+ self . components ( ) == other. components ( )
2690
2723
}
2691
2724
}
2692
2725
@@ -2706,15 +2739,15 @@ impl cmp::Eq for Path {}
2706
2739
impl cmp:: PartialOrd for Path {
2707
2740
#[ inline]
2708
2741
fn partial_cmp ( & self , other : & Path ) -> Option < cmp:: Ordering > {
2709
- self . components ( ) . partial_cmp ( other. components ( ) )
2742
+ Some ( compare_components ( self . components ( ) , other. components ( ) ) )
2710
2743
}
2711
2744
}
2712
2745
2713
2746
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2714
2747
impl cmp:: Ord for Path {
2715
2748
#[ inline]
2716
2749
fn cmp ( & self , other : & Path ) -> cmp:: Ordering {
2717
- self . components ( ) . cmp ( other. components ( ) )
2750
+ compare_components ( self . components ( ) , other. components ( ) )
2718
2751
}
2719
2752
}
2720
2753
0 commit comments