@@ -871,6 +871,38 @@ pub fn is_verbatim(path: &Path) -> bool {
871
871
prefix_is_verbatim ( path. prefix )
872
872
}
873
873
874
+ /// Returns the non-verbatim equivalent of the input path, if possible.
875
+ /// If the input path is a device namespace path, None is returned.
876
+ /// If the input path is not verbatim, it is returned as-is.
877
+ /// If the input path is verbatim, but the same path can be expressed as
878
+ /// non-verbatim, the non-verbatim version is returned.
879
+ /// Otherwise, None is returned.
880
+ pub fn make_non_verbatim ( path : & Path ) -> Option < Path > {
881
+ let new_path = match path. prefix {
882
+ Some ( VerbatimPrefix ( _) ) | Some ( DeviceNSPrefix ( _) ) => return None ,
883
+ Some ( UNCPrefix ( _, _) ) | Some ( DiskPrefix ) | None => return Some ( path. clone ( ) ) ,
884
+ Some ( VerbatimDiskPrefix ) => {
885
+ // \\?\D:\
886
+ Path :: new ( path. repr . slice_from ( 4 ) )
887
+ }
888
+ Some ( VerbatimUNCPrefix ( _, _) ) => {
889
+ // \\?\UNC\server\share
890
+ Path :: new ( format ! ( r"\\{}" , path. repr. slice_from( 7 ) ) )
891
+ }
892
+ } ;
893
+ if new_path. prefix . is_none ( ) {
894
+ // \\?\UNC\server is a VerbatimUNCPrefix
895
+ // but \\server is nothing
896
+ return None ;
897
+ }
898
+ // now ensure normalization didn't change anything
899
+ if path. repr . slice_from ( path. prefix_len ( ) ) == new_path. repr . slice_from ( new_path. prefix_len ( ) ) {
900
+ Some ( new_path)
901
+ } else {
902
+ None
903
+ }
904
+ }
905
+
874
906
/// The standard path separator character
875
907
pub static SEP : char = '\\' ;
876
908
/// The standard path separator byte
@@ -2284,4 +2316,38 @@ mod tests {
2284
2316
t!( s: "." , [ b!( "." ) ] ) ;
2285
2317
// since this is really a wrapper around str_components, those tests suffice
2286
2318
}
2319
+
2320
+ #[ test]
2321
+ fn test_make_non_verbatim( ) {
2322
+ macro_rules! t(
2323
+ ( $path: expr, $exp: expr) => (
2324
+ {
2325
+ let path = Path :: new( $path) ;
2326
+ let exp: Option <& str > = $exp;
2327
+ let exp = exp. map( |s| Path :: new( s) ) ;
2328
+ assert_eq!( make_non_verbatim( & path) , exp) ;
2329
+ }
2330
+ )
2331
+ )
2332
+
2333
+ t!( r"\a\b\c" , Some ( r"\a\b\c" ) ) ;
2334
+ t!( r"a\b\c" , Some ( r"a\b\c" ) ) ;
2335
+ t!( r"C:\a\b\c" , Some ( r"C:\a\b\c" ) ) ;
2336
+ t!( r"C:a\b\c" , Some ( r"C:a\b\c" ) ) ;
2337
+ t!( r"\\server\share\foo" , Some ( r"\\server\share\foo" ) ) ;
2338
+ t!( r"\\.\foo" , None ) ;
2339
+ t!( r"\\?\foo" , None ) ;
2340
+ t!( r"\\?\C:" , None ) ;
2341
+ t!( r"\\?\C:foo" , None ) ;
2342
+ t!( r"\\?\C:\" , Some ( r"C:\" ) ) ;
2343
+ t!( r"\\?\C:\foo" , Some ( r"C:\foo" ) ) ;
2344
+ t!( r"\\?\C:\foo\bar\baz" , Some ( r"C:\foo\bar\baz" ) ) ;
2345
+ t!( r"\\?\C:\foo\.\bar\baz" , None ) ;
2346
+ t!( r"\\?\C:\foo\bar\..\baz" , None ) ;
2347
+ t!( r"\\?\C:\foo\bar\.." , None ) ;
2348
+ t!( r"\\?\UNC\server\share\foo" , Some ( r"\\server\share\foo" ) ) ;
2349
+ t!( r"\\?\UNC\server\share" , Some ( r"\\server\share" ) ) ;
2350
+ t!( r"\\?\UNC\server" , None ) ;
2351
+ t!( r"\\?\UNC\server\" , None ) ;
2352
+ }
2287
2353
}
0 commit comments