path-uri: accept WSL mount URIs on Windows

This commit is contained in:
David Wiesen
2026-06-22 11:37:24 -07:00
parent 5b95745eae
commit bf12add007
2 changed files with 48 additions and 0 deletions

View File

@@ -342,6 +342,18 @@ impl PathUri {
/// URIs created by [`Self::from_abs_path`]. Foreign conventions are rejected rather than being
/// projected onto a syntactically valid but unrelated host path.
pub fn to_abs_path(&self) -> io::Result<AbsolutePathBuf> {
#[cfg(windows)]
if let Some(path) = wsl_mount_uri_to_windows_path(&self.0) {
return AbsolutePathBuf::from_absolute_path_checked(path).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
PathUriParseError::InvalidFileUriPath {
path: self.to_string(),
},
)
});
}
if self.infer_path_convention() != Some(PathConvention::native()) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
@@ -408,6 +420,29 @@ impl PathUri {
}
}
#[cfg(windows)]
fn wsl_mount_uri_to_windows_path(url: &Url) -> Option<PathBuf> {
if url.host_str().is_some() {
return None;
}
let mut segments = url.path_segments()?;
if segments.next()? != "mnt" {
return None;
}
let drive = segments.next()?;
if drive.len() != 1 || !drive.as_bytes()[0].is_ascii_alphabetic() {
return None;
}
let mut path = PathBuf::from(format!("{}:\\", drive.to_ascii_uppercase()));
for segment in segments {
path.push(decode_uri_path(segment));
}
Some(path)
}
impl TryFrom<Url> for PathUri {
type Error = PathUriParseError;

View File

@@ -206,6 +206,19 @@ fn file_uri_fallback_round_trips_non_unicode_windows_paths() {
);
}
#[cfg(windows)]
#[test]
fn wsl_mount_file_uri_maps_to_windows_path() {
let uri =
PathUri::parse("file:///mnt/c/Users/Alice%20Smith/src/main.rs").expect("valid WSL URI");
assert_eq!(
uri.to_abs_path().expect("WSL mount URI should convert"),
AbsolutePathBuf::from_absolute_path_checked(r"C:\Users\Alice Smith\src\main.rs")
.expect("absolute Windows path")
);
}
#[cfg(unix)]
#[test]
fn file_uri_falls_back_for_posix_paths_with_null_bytes() {