#![warn(unsafe_code)]
#![warn(missing_docs)]
#![cfg_attr(not(debug_assertions), deny(warnings))]
#![deny(rust_2018_idioms)]
#![deny(rust_2021_compatibility)]
#![deny(missing_debug_implementations)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(clippy::all)]
#![deny(clippy::explicit_deref_methods)]
#![deny(clippy::explicit_into_iter_loop)]
#![deny(clippy::explicit_iter_loop)]
#![deny(clippy::must_use_candidate)]
#![cfg_attr(not(test), deny(clippy::panic_in_result_fn))]
#![cfg_attr(not(debug_assertions), deny(clippy::used_underscore_binding))]
use typed_path::{
Utf8UnixComponent, Utf8UnixPath, Utf8UnixPathBuf, Utf8WindowsComponent, Utf8WindowsPath,
Utf8WindowsPathBuf, Utf8WindowsPrefix,
};
#[derive(Debug, PartialEq)]
pub enum Error {
RelativePath,
InvalidPrefix,
}
pub fn windows_to_wsl(windows_path: &str) -> Result<String, Error> {
let path = Utf8WindowsPath::new(windows_path);
if !path.is_absolute() {
return Err(Error::RelativePath);
}
let expected_length = windows_path.len() + 4;
let mut output = Utf8UnixPathBuf::with_capacity(expected_length);
for component in path.components() {
match component {
Utf8WindowsComponent::Prefix(prefix_component) => match prefix_component.kind() {
Utf8WindowsPrefix::VerbatimDisk(disk) => {
output.push("/mnt");
output.push(disk.to_ascii_lowercase().to_string());
}
Utf8WindowsPrefix::Disk(disk) => {
output.push("/mnt");
output.push(disk.to_ascii_lowercase().to_string());
}
Utf8WindowsPrefix::VerbatimUNC(hostname, _) => {
if hostname == "wsl.localhost" {
output.push("/");
} else {
return Err(Error::InvalidPrefix);
}
}
_ => {
return Err(Error::InvalidPrefix);
}
},
Utf8WindowsComponent::RootDir => (),
Utf8WindowsComponent::CurDir => output.push("."),
Utf8WindowsComponent::Normal(name) => output.push(name),
Utf8WindowsComponent::ParentDir => output.push(".."),
};
}
Ok(output.normalize().into_string())
}
pub fn wsl_to_windows(wsl_path: &str) -> Result<String, Error> {
let path = Utf8UnixPath::new(wsl_path);
if !path.is_absolute() {
return Err(Error::RelativePath);
}
let mut components = path.components();
if components.next() != Some(Utf8UnixComponent::RootDir) {
return Err(Error::InvalidPrefix);
}
if components.next() != Some(Utf8UnixComponent::Normal("mnt")) {
return Err(Error::InvalidPrefix);
}
let expected_length = wsl_path.len();
let mut output = Utf8WindowsPathBuf::with_capacity(expected_length);
if let Some(Utf8UnixComponent::Normal(drive)) = components.next() {
if drive.len() != 1 {
return Err(Error::InvalidPrefix);
}
output.push(format!("{}:\\", drive.to_ascii_uppercase()));
} else {
return Err(Error::InvalidPrefix);
}
for component in components {
match component {
Utf8UnixComponent::RootDir => (),
Utf8UnixComponent::CurDir => output.push("."),
Utf8UnixComponent::Normal(name) => output.push(name),
Utf8UnixComponent::ParentDir => output.push(".."),
};
}
Ok(output.normalize().into_string())
}