@@ -1813,8 +1813,10 @@ impl Url {
1813
1813
return Err ( ParseError :: SetHostOnCannotBeABaseUrl ) ;
1814
1814
}
1815
1815
1816
+ let scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1817
+
1816
1818
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 ( ) {
1818
1820
return Err ( ParseError :: EmptyHost ) ;
1819
1821
}
1820
1822
let mut host_substr = host;
@@ -1838,15 +1840,20 @@ impl Url {
1838
1840
self . set_host_internal ( Host :: parse_opaque ( host_substr) ?, None ) ;
1839
1841
}
1840
1842
} 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 ( ) {
1843
1844
return Err ( ParseError :: EmptyHost ) ;
1844
1845
} else if self . serialization . len ( ) == self . path_start as usize {
1845
1846
self . serialization . push ( '/' ) ;
1846
1847
}
1847
1848
debug_assert ! ( self . byte_at( self . scheme_end) == b':' ) ;
1848
1849
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
+
1850
1857
self . serialization
1851
1858
. drain ( new_path_start as usize ..self . path_start as usize ) ;
1852
1859
let offset = self . path_start - new_path_start;
@@ -2730,6 +2737,7 @@ fn path_to_file_url_segments_windows(
2730
2737
let host_start = serialization. len ( ) + 1 ;
2731
2738
let host_end;
2732
2739
let host_internal;
2740
+
2733
2741
match components. next ( ) {
2734
2742
Some ( Component :: Prefix ( ref p) ) => match p. kind ( ) {
2735
2743
Prefix :: Disk ( letter) | Prefix :: VerbatimDisk ( letter) => {
@@ -2750,7 +2758,6 @@ fn path_to_file_url_segments_windows(
2750
2758
}
2751
2759
_ => return Err ( ( ) ) ,
2752
2760
} ,
2753
-
2754
2761
_ => return Err ( ( ) ) ,
2755
2762
}
2756
2763
@@ -2759,19 +2766,23 @@ fn path_to_file_url_segments_windows(
2759
2766
if component == Component :: RootDir {
2760
2767
continue ;
2761
2768
}
2769
+
2762
2770
path_only_has_prefix = false ;
2763
2771
// FIXME: somehow work with non-unicode?
2764
2772
let component = component. as_os_str ( ) . to_str ( ) . ok_or ( ( ) ) ?;
2773
+
2765
2774
serialization. push ( '/' ) ;
2766
2775
serialization. extend ( percent_encode ( component. as_bytes ( ) , PATH_SEGMENT ) ) ;
2767
2776
}
2777
+
2768
2778
// A windows drive letter must end with a slash.
2769
2779
if serialization. len ( ) > host_start
2770
2780
&& parser:: is_windows_drive_letter ( & serialization[ host_start..] )
2771
2781
&& path_only_has_prefix
2772
2782
{
2773
2783
serialization. push ( '/' ) ;
2774
2784
}
2785
+
2775
2786
Ok ( ( host_end, host_internal) )
2776
2787
}
2777
2788
@@ -2795,23 +2806,28 @@ fn file_url_segments_to_pathbuf(
2795
2806
} else {
2796
2807
Vec :: new ( )
2797
2808
} ;
2809
+
2798
2810
for segment in segments {
2799
2811
bytes. push ( b'/' ) ;
2800
2812
bytes. extend ( percent_decode ( segment. as_bytes ( ) ) ) ;
2801
2813
}
2814
+
2802
2815
// A windows drive letter must end with a slash.
2803
2816
if bytes. len ( ) > 2
2804
2817
&& matches ! ( bytes[ bytes. len( ) - 2 ] , b'a' ..=b'z' | b'A' ..=b'Z' )
2805
2818
&& matches ! ( bytes[ bytes. len( ) - 1 ] , b':' | b'|' )
2806
2819
{
2807
2820
bytes. push ( b'/' ) ;
2808
2821
}
2822
+
2809
2823
let os_str = OsStr :: from_bytes ( & bytes) ;
2810
2824
let path = PathBuf :: from ( os_str) ;
2825
+
2811
2826
debug_assert ! (
2812
2827
path. is_absolute( ) ,
2813
2828
"to_file_path() failed to produce an absolute Path"
2814
2829
) ;
2830
+
2815
2831
Ok ( path)
2816
2832
}
2817
2833
0 commit comments