Skip to content

Commit 0a289df

Browse files
committed
Make sure a windows drive letter segment always ends with a slash.
1 parent 3c71cac commit 0a289df

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,7 @@ fn path_to_file_url_segments_windows(
23362336
}
23372337
let mut components = path.components();
23382338

2339+
let host_start = serialization.len() + 1;
23392340
let host_end;
23402341
let host_internal;
23412342
match components.next() {
@@ -2362,15 +2363,24 @@ fn path_to_file_url_segments_windows(
23622363
_ => return Err(()),
23632364
}
23642365

2366+
let mut path_only_has_prefix = true;
23652367
for component in components {
23662368
if component == Component::RootDir {
23672369
continue;
23682370
}
2371+
path_only_has_prefix = false;
23692372
// FIXME: somehow work with non-unicode?
23702373
let component = component.as_os_str().to_str().ok_or(())?;
23712374
serialization.push('/');
23722375
serialization.extend(percent_encode(component.as_bytes(), PATH_SEGMENT));
23732376
}
2377+
// A windows drive letter must end with a slash.
2378+
if serialization.len() > host_start
2379+
&& parser::is_windows_drive_letter(&serialization[host_start..])
2380+
&& path_only_has_prefix
2381+
{
2382+
serialization.push('/');
2383+
}
23742384
Ok((host_end, host_internal))
23752385
}
23762386

src/parser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,8 @@ pub fn to_u32(i: usize) -> ParseResult<u32> {
13931393

13941394
/// Wether the scheme is file:, the path has a single segment, and that segment
13951395
/// is a Windows drive letter
1396-
fn is_windows_drive_letter(segment: &str) -> bool {
1396+
#[inline]
1397+
pub fn is_windows_drive_letter(segment: &str) -> bool {
13971398
segment.len() == 2 && starts_with_windows_drive_letter(segment)
13981399
}
13991400

tests/unit.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,15 @@ fn test_options_reuse() {
549549
assert_eq!(url.as_str(), "http://mozilla.org/sub/path");
550550
assert_eq!(*violations.borrow(), vec!(ExpectedDoubleSlash, Backslash));
551551
}
552+
553+
/// https://github.com/servo/rust-url/issues/505
554+
#[test]
555+
fn test_url_from_file_path() {
556+
use std::path::PathBuf;
557+
use url::Url;
558+
559+
let p = PathBuf::from("c:///");
560+
let u = Url::from_file_path(p).unwrap();
561+
let path = u.to_file_path().unwrap();
562+
assert_eq!("C:\\",path.to_str().unwrap());
563+
}

0 commit comments

Comments
 (0)