1
- use std :: path :: MAIN_SEPARATOR ;
1
+ use path_parsing :: { find_last_non_sep_pos , find_last_sep_pos } ;
2
2
use std:: str;
3
3
4
4
pub fn chop_basename < ' a > ( input : & ' a str ) -> Option < ( & ' a str , & ' a str ) > {
5
- if input. is_empty ( ) {
5
+ let bytes = input. as_bytes ( ) ;
6
+ let len = find_last_non_sep_pos ( & bytes) ? + 1 ;
7
+ let base_start = find_last_sep_pos ( & bytes[ ..len] ) . map_or ( 0 , |pos| pos + 1 ) ;
8
+ if base_start == len {
6
9
return None ;
7
10
}
8
-
9
- let input = input. trim_right_matches ( MAIN_SEPARATOR ) ;
10
- let end = input. rsplitn ( 2 , MAIN_SEPARATOR ) . nth ( 0 ) . unwrap ( ) . len ( ) ;
11
- let base = & input[ input. len ( ) -end..input. len ( ) ] ;
12
- let directory = & input[ 0 ..input. len ( ) -base. len ( ) ] ;
13
-
14
- if directory. is_empty ( ) && ( base. is_empty ( ) || base. chars ( ) . next ( ) . unwrap ( ) == MAIN_SEPARATOR ) {
15
- return None
16
- } ;
17
-
18
- Some ( ( directory, base) )
11
+ Some ( ( & input[ 0 ..base_start] , & input[ base_start..len] ) )
19
12
}
20
13
21
14
#[ test]
@@ -27,5 +20,11 @@ fn it_chops_the_basename_and_dirname() {
27
20
assert_eq ! ( chop_basename( "asdf.txt" ) , Some ( ( "" , "asdf.txt" ) ) ) ;
28
21
assert_eq ! ( chop_basename( "asdf/" ) , Some ( ( "" , "asdf" ) ) ) ;
29
22
assert_eq ! ( chop_basename( "/asdf/" ) , Some ( ( "/" , "asdf" ) ) ) ;
23
+ assert_eq ! ( chop_basename( "a///b" ) , Some ( ( "a///" , "b" ) ) ) ;
24
+ assert_eq ! ( chop_basename( "a///b//" ) , Some ( ( "a///" , "b" ) ) ) ;
25
+ assert_eq ! ( chop_basename( "/a///b//" ) , Some ( ( "/a///" , "b" ) ) ) ;
26
+ assert_eq ! ( chop_basename( "/a///b//" ) , Some ( ( "/a///" , "b" ) ) ) ;
27
+
28
+ assert_eq ! ( chop_basename( "./../..///.../..//" ) , Some ( ( "./../..///.../" , ".." ) ) ) ;
30
29
}
31
30
0 commit comments