use typed_path::Utf8UnixPath;
use crate::filesystem::{FsError, FsResult, Utf8UnixPathSegment};
pub fn split_last(path: &Utf8UnixPath) -> FsResult<(Option<&Utf8UnixPath>, Utf8UnixPathSegment)> {
if path.has_root() {
return Err(FsError::PathHasRoot(path.to_string()));
}
if path.as_str().is_empty() {
return Err(FsError::PathIsEmpty);
}
let filename = path
.file_name()
.ok_or_else(|| FsError::InvalidPathComponent(path.to_string()))?
.parse()?;
let parent = path
.parent()
.and_then(|p| (!p.as_str().is_empty()).then_some(p));
Ok((parent, filename))
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
use typed_path::Utf8UnixPathBuf;
#[test]
fn test_split_last() -> FsResult<()> {
assert_eq!(
split_last(&Utf8UnixPathBuf::from("foo/bar/baz"))?,
(
Some(Utf8UnixPath::new("foo/bar")),
Utf8UnixPathSegment::from_str("baz")?
)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("foo/bar"))?,
(
Some(Utf8UnixPath::new("foo")),
Utf8UnixPathSegment::from_str("bar")?
)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("baz"))?,
(None, Utf8UnixPathSegment::from_str("baz")?)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("foo/bar/baz"))?,
(
Some(Utf8UnixPath::new("foo/bar")),
Utf8UnixPathSegment::from_str("baz")?
)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("path with/spaces in/file name"))?,
(
Some(Utf8UnixPath::new("path with/spaces in")),
Utf8UnixPathSegment::from_str("file name")?
)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("路径/文件"))?,
(
Some(Utf8UnixPath::new("路径")),
Utf8UnixPathSegment::from_str("文件")?
)
);
assert_eq!(
split_last(&Utf8UnixPathBuf::from("foo/bar/"))?,
(
Some(Utf8UnixPath::new("foo")),
Utf8UnixPathSegment::from_str("bar")?
)
);
assert!(matches!(
split_last(&Utf8UnixPathBuf::from("")),
Err(FsError::PathIsEmpty)
));
assert!(matches!(
split_last(&Utf8UnixPathBuf::from("/")),
Err(FsError::PathHasRoot(_))
));
assert!(matches!(
split_last(&Utf8UnixPathBuf::from("/foo")),
Err(FsError::PathHasRoot(_))
));
Ok(())
}
}