11use fancy_regex:: Regex ;
22use serde:: { Deserialize , Deserializer , de:: Error } ;
3- use std:: { borrow:: Cow , path :: Component } ;
3+ use std:: borrow:: Cow ;
44
5- use path_slash:: PathBufExt ;
65use std:: path:: { MAIN_SEPARATOR_STR , Path , PathBuf } ;
76
87#[ derive( Debug , Default , Clone ) ]
@@ -33,35 +32,61 @@ impl<T> Trie<T> {
3332 }
3433}
3534
36- fn clean_path ( path : PathBuf ) -> PathBuf {
37- let mut out = Vec :: new ( ) ;
35+ pub fn normalize_path < P : AsRef < str > > ( original : P ) -> String {
36+ let original_str
37+ = original. as_ref ( ) ;
38+
39+ let check_str_root
40+ = original_str. strip_prefix ( "/" ) ;
41+ let str_minus_root
42+ = check_str_root. unwrap_or ( original_str) ;
43+
44+ let components
45+ = str_minus_root. split ( & [ '/' , '\\' ] [ ..] ) ;
46+
47+ let mut out: Vec < & str >
48+ = Vec :: new ( ) ;
3849
39- for comp in path. components ( ) {
40- println ! ( "Component: {:?}" , comp) ;
50+ for comp in components {
4151 match comp {
42- Component :: CurDir => ( ) ,
43- Component :: ParentDir => match out. last ( ) {
44- Some ( Component :: RootDir ) => ( ) ,
45- Some ( Component :: Normal ( _) ) => {
52+ "" | "." => {
53+ // Those components don't progress the path
54+ } ,
55+
56+ ".." => match out. last ( ) {
57+ None if check_str_root. is_some ( ) => {
58+ // No need to add a ".." since we're already at the root
59+ } ,
60+
61+ Some ( & ".." ) | None => {
62+ out. push ( comp) ;
63+ } ,
64+
65+ Some ( _) => {
4666 out. pop ( ) ;
47- }
48- None
49- | Some ( Component :: CurDir )
50- | Some ( Component :: ParentDir )
51- | Some ( Component :: Prefix ( _ ) ) => out. push ( comp) ,
67+ } ,
68+ } ,
69+
70+ comp => {
71+ out. push ( comp)
5272 } ,
53- comp => out. push ( comp) ,
5473 }
5574 }
5675
57- if !out. is_empty ( ) { out. iter ( ) . collect ( ) } else { PathBuf :: from ( "." ) }
58- }
76+ if check_str_root. is_some ( ) {
77+ if out. is_empty ( ) {
78+ return "/" . to_string ( ) ;
79+ } else {
80+ out. insert ( 0 , "" ) ;
81+ }
82+ }
5983
60- pub fn normalize_path < P : AsRef < str > > ( original : P ) -> String {
61- let original_str = original . as_ref ( ) ;
84+ let mut str
85+ = out . join ( "/" ) ;
6286
63- let p = PathBuf :: from ( original_str) ;
64- let mut str = clean_path ( p) . to_slash_lossy ( ) . to_string ( ) ;
87+ if out. is_empty ( ) {
88+ return "." . to_string ( ) ;
89+ }
6590
6691 if ( original_str. ends_with ( '/' ) || original_str. ends_with ( MAIN_SEPARATOR_STR ) )
6792 && !str. ends_with ( '/' )
@@ -85,12 +110,17 @@ mod tests {
85110 assert_eq ! ( normalize_path( "foo//bar" ) , "foo/bar" ) ;
86111 assert_eq ! ( normalize_path( "foo/./bar" ) , "foo/bar" ) ;
87112 assert_eq ! ( normalize_path( "foo/../bar" ) , "bar" ) ;
113+ assert_eq ! ( normalize_path( "foo/..//bar" ) , "bar" ) ;
88114 assert_eq ! ( normalize_path( "foo/bar/.." ) , "foo" ) ;
89115 assert_eq ! ( normalize_path( "foo/../../bar" ) , "../bar" ) ;
90116 assert_eq ! ( normalize_path( "../foo/../../bar" ) , "../../bar" ) ;
91117 assert_eq ! ( normalize_path( "./foo" ) , "foo" ) ;
92118 assert_eq ! ( normalize_path( "../foo" ) , "../foo" ) ;
119+ assert_eq ! ( normalize_path( "../D:/foo" ) , "../D:/foo" ) ;
93120 assert_eq ! ( normalize_path( "/foo/bar" ) , "/foo/bar" ) ;
121+ assert_eq ! ( normalize_path( "/../foo/bar" ) , "/foo/bar" ) ;
122+ assert_eq ! ( normalize_path( "/foo/../../bar/baz" ) , "/bar/baz" ) ;
123+ assert_eq ! ( normalize_path( "/../foo/bar" ) , "/foo/bar" ) ;
94124 assert_eq ! ( normalize_path( "/foo/bar/" ) , "/foo/bar/" ) ;
95125 }
96126}
0 commit comments