nu_path/
trailing_slash.rsuse std::{
borrow::Cow,
path::{Path, PathBuf},
};
pub fn strip_trailing_slash(path: &Path) -> Cow<Path> {
if has_trailing_slash(path) {
let mut out = PathBuf::with_capacity(path.as_os_str().len());
out.extend(path.components());
Cow::Owned(out)
} else {
Cow::Borrowed(path)
}
}
#[cfg(windows)]
pub fn has_trailing_slash(path: &Path) -> bool {
use std::os::windows::ffi::OsStrExt;
let last = path.as_os_str().encode_wide().last();
last == Some(b'\\' as u16) || last == Some(b'/' as u16)
}
#[cfg(unix)]
pub fn has_trailing_slash(path: &Path) -> bool {
use std::os::unix::ffi::OsStrExt;
let last = path.as_os_str().as_bytes().last();
last == Some(&b'/')
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg_attr(not(unix), ignore = "only for Unix")]
#[test]
fn strip_root_unix() {
assert_eq!(Path::new("/"), strip_trailing_slash(Path::new("/")));
}
#[cfg_attr(not(unix), ignore = "only for Unix")]
#[test]
fn strip_non_trailing_unix() {
assert_eq!(
Path::new("/foo/bar"),
strip_trailing_slash(Path::new("/foo/bar"))
);
}
#[cfg_attr(not(unix), ignore = "only for Unix")]
#[test]
fn strip_trailing_unix() {
assert_eq!(
Path::new("/foo/bar"),
strip_trailing_slash(Path::new("/foo/bar/"))
);
}
#[cfg_attr(not(windows), ignore = "only for Windows")]
#[test]
fn strip_root_windows() {
assert_eq!(Path::new(r"C:\"), strip_trailing_slash(Path::new(r"C:\")));
}
#[cfg_attr(not(windows), ignore = "only for Windows")]
#[test]
fn strip_non_trailing_windows() {
assert_eq!(
Path::new(r"C:\foo\bar"),
strip_trailing_slash(Path::new(r"C:\foo\bar"))
);
}
#[cfg_attr(not(windows), ignore = "only for Windows")]
#[test]
fn strip_non_trailing_windows_unc() {
assert_eq!(
Path::new(r"\\foo\bar"),
strip_trailing_slash(Path::new(r"\\foo\bar"))
);
}
#[cfg_attr(not(windows), ignore = "only for Windows")]
#[test]
fn strip_trailing_windows() {
assert_eq!(
Path::new(r"C:\foo\bar"),
strip_trailing_slash(Path::new(r"C:\foo\bar\"))
);
}
#[cfg_attr(not(windows), ignore = "only for Windows")]
#[test]
fn strip_trailing_windows_unc() {
assert_eq!(
Path::new(r"\\foo\bar"),
strip_trailing_slash(Path::new(r"\\foo\bar\"))
);
}
}