diff --git a/url/src/lib.rs b/url/src/lib.rs index 6e6e7497..c7879b4e 100644 --- a/url/src/lib.rs +++ b/url/src/lib.rs @@ -3170,7 +3170,22 @@ fn file_url_segments_to_pathbuf_windows( estimated_capacity ); } + + // NOTE: when url got broken into segments, it loses the trailing slash `\` + // however, on windows, rust lang regards `c:\` as a valid absolute path rather than `c:` + // thus, this if-else add this '\' back for this ad-hoc case. + if string.len() == 2 + && matches!( + string.chars().nth(0).map(|c| c.is_ascii_alphabetic()), + Some(true) + ) + && matches!(string.chars().nth(1), Some(':')) + { + string.push('\\'); + } + let path = PathBuf::from(string); + debug_assert!( path.is_absolute(), "to_file_path() failed to produce an absolute Path" diff --git a/url/tests/unit.rs b/url/tests/unit.rs index 6a9430bd..a252e381 100644 --- a/url/tests/unit.rs +++ b/url/tests/unit.rs @@ -541,6 +541,27 @@ fn append_empty_segment_then_mutate() { assert_eq!(url.to_string(), "http://localhost:6767/foo/bar?a=b"); } +#[test] +#[cfg(feature = "std")] +#[cfg(windows)] +fn extend_empty_segment_to_win_driver() { + let path_str = r"C:\"; + let prefix_path = PathBuf::from(r"C:\"); + let prefix_path = std::fs::canonicalize(prefix_path).expect("Failed to canonicalize path"); + let mut url = Url::from_file_path(prefix_path).expect("Failed to parse path"); + let empty_segment: [&str; 0] = []; + + url.path_segments_mut() + .expect("url path") + .pop_if_empty() + .extend(empty_segment); + + let path = url + .to_file_path() + .expect("Failed to parse the windows driver path"); + assert_eq!(path.to_str(), Some(path_str)); +} + #[test] /// https://github.com/servo/rust-url/issues/243 fn test_set_host() {