use std::path::{Path, PathBuf};
pub fn safe_canonicalize(path: &Path) -> std::io::Result<PathBuf> {
let canon = std::fs::canonicalize(path)?;
Ok(strip_verbatim(canon))
}
pub fn safe_canonicalize_or_self(path: &Path) -> PathBuf {
safe_canonicalize(path).unwrap_or_else(|_| path.to_path_buf())
}
pub fn strip_verbatim(path: PathBuf) -> PathBuf {
let s = path.to_string_lossy();
if let Some(stripped) = strip_verbatim_str(&s) {
PathBuf::from(stripped)
} else {
path
}
}
pub fn strip_verbatim_str(path: &str) -> Option<String> {
let normalized = path.replace('\\', "/");
if let Some(rest) = normalized.strip_prefix("//?/UNC/") {
Some(format!("//{rest}"))
} else {
normalized.strip_prefix("//?/").map(|rest| rest.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strip_regular_verbatim() {
let p = PathBuf::from(r"\\?\C:\Users\dev\project");
let result = strip_verbatim(p);
assert_eq!(result, PathBuf::from("C:/Users/dev/project"));
}
#[test]
fn strip_unc_verbatim() {
let p = PathBuf::from(r"\\?\UNC\server\share\dir");
let result = strip_verbatim(p);
assert_eq!(result, PathBuf::from("//server/share/dir"));
}
#[test]
fn no_prefix_unchanged() {
let p = PathBuf::from("/home/user/project");
let result = strip_verbatim(p.clone());
assert_eq!(result, p);
}
#[test]
fn windows_drive_unchanged() {
let p = PathBuf::from("C:/Users/dev");
let result = strip_verbatim(p.clone());
assert_eq!(result, p);
}
#[test]
fn strip_str_regular() {
assert_eq!(
strip_verbatim_str(r"\\?\E:\code\lean-ctx"),
Some("E:/code/lean-ctx".to_string())
);
}
#[test]
fn strip_str_unc() {
assert_eq!(
strip_verbatim_str(r"\\?\UNC\myserver\data"),
Some("//myserver/data".to_string())
);
}
#[test]
fn strip_str_forward_slash_variant() {
assert_eq!(
strip_verbatim_str("//?/C:/Users/dev"),
Some("C:/Users/dev".to_string())
);
}
#[test]
fn strip_str_no_prefix() {
assert_eq!(strip_verbatim_str("/home/user"), None);
}
#[test]
fn safe_canonicalize_or_self_nonexistent() {
let p = Path::new("/this/path/should/not/exist/xyzzy");
let result = safe_canonicalize_or_self(p);
assert_eq!(result, p.to_path_buf());
}
}