@@ -8,6 +8,10 @@ mod tests;
88pub const MAIN_SEP_STR : & str = "\\ " ;
99pub const MAIN_SEP : char = '\\' ;
1010
11+ // The unsafety here stems from converting between `&OsStr` and `&[u8]`
12+ // and back. This is safe to do because (1) we only look at ASCII
13+ // contents of the encoding and (2) new &OsStr values are produced
14+ // only from ASCII-bounded slices of existing &OsStr values.
1115fn os_str_as_u8_slice ( s : & OsStr ) -> & [ u8 ] {
1216 unsafe { mem:: transmute ( s) }
1317}
@@ -33,62 +37,57 @@ pub fn is_valid_drive_letter(disk: u8) -> bool {
3337
3438pub fn parse_prefix ( path : & OsStr ) -> Option < Prefix < ' _ > > {
3539 use Prefix :: { DeviceNS , Disk , Verbatim , VerbatimDisk , VerbatimUNC , UNC } ;
36- unsafe {
37- // The unsafety here stems from converting between &OsStr and &[u8]
38- // and back. This is safe to do because (1) we only look at ASCII
39- // contents of the encoding and (2) new &OsStr values are produced
40- // only from ASCII-bounded slices of existing &OsStr values.
41- let path = os_str_as_u8_slice ( path) ;
4240
43- // \\
44- if let Some ( path) = path. strip_prefix ( br"\\" ) {
45- // \\?\
46- if let Some ( path) = path. strip_prefix ( br"?\" ) {
47- // \\?\UNC\server\share
48- if let Some ( path) = path. strip_prefix ( br"UNC\" ) {
49- let ( server, share) = match get_first_two_components ( path, is_verbatim_sep) {
50- Some ( ( server, share) ) => {
51- ( u8_slice_as_os_str ( server) , u8_slice_as_os_str ( share) )
52- }
53- None => ( u8_slice_as_os_str ( path) , OsStr :: new ( "" ) ) ,
54- } ;
55- return Some ( VerbatimUNC ( server, share) ) ;
56- } else {
57- // \\?\path
58- match path {
59- // \\?\C:\path
60- [ c, b':' , b'\\' , ..] if is_valid_drive_letter ( * c) => {
61- return Some ( VerbatimDisk ( c. to_ascii_uppercase ( ) ) ) ;
62- }
63- // \\?\cat_pics
64- _ => {
65- let idx = path. iter ( ) . position ( |& b| b == b'\\' ) . unwrap_or ( path. len ( ) ) ;
66- let slice = & path[ ..idx] ;
67- return Some ( Verbatim ( u8_slice_as_os_str ( slice) ) ) ;
68- }
41+ let path = os_str_as_u8_slice ( path) ;
42+
43+ // \\
44+ if let Some ( path) = path. strip_prefix ( br"\\" ) {
45+ // \\?\
46+ if let Some ( path) = path. strip_prefix ( br"?\" ) {
47+ // \\?\UNC\server\share
48+ if let Some ( path) = path. strip_prefix ( br"UNC\" ) {
49+ let ( server, share) = match get_first_two_components ( path, is_verbatim_sep) {
50+ Some ( ( server, share) ) => unsafe {
51+ ( u8_slice_as_os_str ( server) , u8_slice_as_os_str ( share) )
52+ } ,
53+ None => ( unsafe { u8_slice_as_os_str ( path) } , OsStr :: new ( "" ) ) ,
54+ } ;
55+ return Some ( VerbatimUNC ( server, share) ) ;
56+ } else {
57+ // \\?\path
58+ match path {
59+ // \\?\C:\path
60+ [ c, b':' , b'\\' , ..] if is_valid_drive_letter ( * c) => {
61+ return Some ( VerbatimDisk ( c. to_ascii_uppercase ( ) ) ) ;
62+ }
63+ // \\?\cat_pics
64+ _ => {
65+ let idx = path. iter ( ) . position ( |& b| b == b'\\' ) . unwrap_or ( path. len ( ) ) ;
66+ let slice = & path[ ..idx] ;
67+ return Some ( Verbatim ( unsafe { u8_slice_as_os_str ( slice) } ) ) ;
6968 }
7069 }
71- } else if let Some ( path) = path. strip_prefix ( b".\\ " ) {
72- // \\.\COM42
73- let idx = path. iter ( ) . position ( |& b| b == b'\\' ) . unwrap_or ( path. len ( ) ) ;
74- let slice = & path[ ..idx] ;
75- return Some ( DeviceNS ( u8_slice_as_os_str ( slice) ) ) ;
76- }
77- match get_first_two_components ( path, is_sep_byte) {
78- Some ( ( server, share) ) if !server. is_empty ( ) && !share. is_empty ( ) => {
79- // \\server\share
80- return Some ( UNC ( u8_slice_as_os_str ( server) , u8_slice_as_os_str ( share) ) ) ;
81- }
82- _ => { }
8370 }
84- } else if let [ c, b':' , ..] = path {
85- // C:
86- if is_valid_drive_letter ( * c) {
87- return Some ( Disk ( c. to_ascii_uppercase ( ) ) ) ;
71+ } else if let Some ( path) = path. strip_prefix ( b".\\ " ) {
72+ // \\.\COM42
73+ let idx = path. iter ( ) . position ( |& b| b == b'\\' ) . unwrap_or ( path. len ( ) ) ;
74+ let slice = & path[ ..idx] ;
75+ return Some ( DeviceNS ( unsafe { u8_slice_as_os_str ( slice) } ) ) ;
76+ }
77+ match get_first_two_components ( path, is_sep_byte) {
78+ Some ( ( server, share) ) if !server. is_empty ( ) && !share. is_empty ( ) => {
79+ // \\server\share
80+ return Some ( unsafe { UNC ( u8_slice_as_os_str ( server) , u8_slice_as_os_str ( share) ) } ) ;
8881 }
82+ _ => { }
83+ }
84+ } else if let [ c, b':' , ..] = path {
85+ // C:
86+ if is_valid_drive_letter ( * c) {
87+ return Some ( Disk ( c. to_ascii_uppercase ( ) ) ) ;
8988 }
90- return None ;
9189 }
90+ None
9291}
9392
9493/// Returns the first two path components with predicate `f`.
0 commit comments