@@ -1813,8 +1813,10 @@ impl Url {
18131813 return Err ( ParseError :: SetHostOnCannotBeABaseUrl ) ;
18141814 }
18151815
1816+ let scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1817+
18161818 if let Some ( host) = host {
1817- if host. is_empty ( ) && SchemeType :: from ( self . scheme ( ) ) . is_special ( ) {
1819+ if host. is_empty ( ) && scheme_type . is_special ( ) && !scheme_type . is_file ( ) {
18181820 return Err ( ParseError :: EmptyHost ) ;
18191821 }
18201822 let mut host_substr = host;
@@ -1838,15 +1840,20 @@ impl Url {
18381840 self . set_host_internal ( Host :: parse_opaque ( host_substr) ?, None ) ;
18391841 }
18401842 } else if self . has_host ( ) {
1841- let scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1842- if scheme_type. is_special ( ) {
1843+ if scheme_type. is_special ( ) && !scheme_type. is_file ( ) {
18431844 return Err ( ParseError :: EmptyHost ) ;
18441845 } else if self . serialization . len ( ) == self . path_start as usize {
18451846 self . serialization . push ( '/' ) ;
18461847 }
18471848 debug_assert ! ( self . byte_at( self . scheme_end) == b':' ) ;
18481849 debug_assert ! ( self . byte_at( self . path_start) == b'/' ) ;
1849- let new_path_start = self . scheme_end + 1 ;
1850+
1851+ let new_path_start = if scheme_type. is_file ( ) {
1852+ self . scheme_end + 3
1853+ } else {
1854+ self . scheme_end + 1
1855+ } ;
1856+
18501857 self . serialization
18511858 . drain ( new_path_start as usize ..self . path_start as usize ) ;
18521859 let offset = self . path_start - new_path_start;
@@ -2730,6 +2737,7 @@ fn path_to_file_url_segments_windows(
27302737 let host_start = serialization. len ( ) + 1 ;
27312738 let host_end;
27322739 let host_internal;
2740+
27332741 match components. next ( ) {
27342742 Some ( Component :: Prefix ( ref p) ) => match p. kind ( ) {
27352743 Prefix :: Disk ( letter) | Prefix :: VerbatimDisk ( letter) => {
@@ -2750,7 +2758,6 @@ fn path_to_file_url_segments_windows(
27502758 }
27512759 _ => return Err ( ( ) ) ,
27522760 } ,
2753-
27542761 _ => return Err ( ( ) ) ,
27552762 }
27562763
@@ -2759,19 +2766,23 @@ fn path_to_file_url_segments_windows(
27592766 if component == Component :: RootDir {
27602767 continue ;
27612768 }
2769+
27622770 path_only_has_prefix = false ;
27632771 // FIXME: somehow work with non-unicode?
27642772 let component = component. as_os_str ( ) . to_str ( ) . ok_or ( ( ) ) ?;
2773+
27652774 serialization. push ( '/' ) ;
27662775 serialization. extend ( percent_encode ( component. as_bytes ( ) , PATH_SEGMENT ) ) ;
27672776 }
2777+
27682778 // A windows drive letter must end with a slash.
27692779 if serialization. len ( ) > host_start
27702780 && parser:: is_windows_drive_letter ( & serialization[ host_start..] )
27712781 && path_only_has_prefix
27722782 {
27732783 serialization. push ( '/' ) ;
27742784 }
2785+
27752786 Ok ( ( host_end, host_internal) )
27762787}
27772788
@@ -2795,23 +2806,28 @@ fn file_url_segments_to_pathbuf(
27952806 } else {
27962807 Vec :: new ( )
27972808 } ;
2809+
27982810 for segment in segments {
27992811 bytes. push ( b'/' ) ;
28002812 bytes. extend ( percent_decode ( segment. as_bytes ( ) ) ) ;
28012813 }
2814+
28022815 // A windows drive letter must end with a slash.
28032816 if bytes. len ( ) > 2
28042817 && matches ! ( bytes[ bytes. len( ) - 2 ] , b'a' ..=b'z' | b'A' ..=b'Z' )
28052818 && matches ! ( bytes[ bytes. len( ) - 1 ] , b':' | b'|' )
28062819 {
28072820 bytes. push ( b'/' ) ;
28082821 }
2822+
28092823 let os_str = OsStr :: from_bytes ( & bytes) ;
28102824 let path = PathBuf :: from ( os_str) ;
2825+
28112826 debug_assert ! (
28122827 path. is_absolute( ) ,
28132828 "to_file_path() failed to produce an absolute Path"
28142829 ) ;
2830+
28152831 Ok ( path)
28162832}
28172833
0 commit comments