use std::path::{Component, Path, Prefix};
pub fn portable_absolute_path(path: &Path) -> String {
let mut components = path.components();
let Some(Component::Prefix(prefix)) = components.clone().next() else {
return path.display().to_string();
};
let disk = match prefix.kind() {
Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => letter,
_ => return verbatim_spelling(path),
};
components.next();
if components.clone().next() != Some(Component::RootDir) {
return verbatim_spelling(path);
}
components.next();
let mut rendered = String::with_capacity(path.as_os_str().len());
rendered.push(char::from(disk));
rendered.push(':');
rendered.push('/');
for (index, component) in components.enumerate() {
if index > 0 {
rendered.push('/');
}
rendered.push_str(&component.as_os_str().to_string_lossy());
}
rendered
}
fn verbatim_spelling(path: &Path) -> String {
path.to_string_lossy().replace('\\', "/")
}
#[cfg(test)]
mod tests {
use super::portable_absolute_path;
use std::path::Path;
#[cfg(unix)]
#[test]
fn unix_absolute_path_is_already_portable() {
assert_eq!(portable_absolute_path(Path::new("/a/b/c.md")), "/a/b/c.md");
}
#[cfg(unix)]
#[test]
fn unix_backslash_is_a_filename_character_not_a_separator() {
assert_eq!(portable_absolute_path(Path::new(r"/a/b\c")), r"/a/b\c");
}
#[cfg(windows)]
#[test]
fn verbatim_disk_prefix_is_unwrapped() {
assert_eq!(
portable_absolute_path(Path::new(r"\\?\C:\a\b\c.md")),
"C:/a/b/c.md"
);
}
#[cfg(windows)]
#[test]
fn plain_disk_prefix_keeps_its_drive_and_swaps_separators() {
assert_eq!(
portable_absolute_path(Path::new(r"C:\a\b\c.md")),
"C:/a/b/c.md"
);
}
#[cfg(windows)]
#[test]
fn drive_root_alone_renders_as_the_root() {
assert_eq!(portable_absolute_path(Path::new(r"C:\")), "C:/");
}
#[cfg(windows)]
#[test]
fn verbatim_unc_keeps_its_prefix_so_the_grammar_still_refuses_it() {
assert_eq!(
portable_absolute_path(Path::new(r"\\?\UNC\server\share\a")),
"//?/UNC/server/share/a"
);
}
#[cfg(windows)]
#[test]
fn unc_keeps_its_authority_so_the_grammar_still_refuses_it() {
assert_eq!(
portable_absolute_path(Path::new(r"\\server\share\a")),
"//server/share/a"
);
}
#[cfg(windows)]
#[test]
fn drive_relative_path_is_not_rooted_here() {
assert_eq!(portable_absolute_path(Path::new(r"C:tmp")), "C:tmp");
}
}