feat(snix/castore/Path): add extension() method

This returns the extension, similar to the method we already have for
PathComponent.

Change-Id: Ia1719951c453c196beb991686dbee23bae1049af
Reviewed-on: https://cl.snix.dev/c/snix/+/30322
Autosubmit: Florian Klink <flokli@flokli.de>
Reviewed-by: Stefan Junker <mail@stefanjunker.de>
Tested-by: besadii
This commit is contained in:
Florian Klink 2025-04-15 14:55:40 +02:00
parent 8c525dcc2d
commit 15b1415860

View file

@ -122,6 +122,20 @@ impl Path {
self.components_bytes().last()
}
/// Returns the extension (without leading dot) of the Path, if possible.
pub fn extension(&self) -> Option<&[u8]> {
let file_name = match self.inner[..].rsplit_once_str(b"/") {
Some((_, r)) => r,
None => &self.inner[..],
};
let mut iter = file_name.rsplitn(2, |b| *b == b'.');
let e = iter.next();
// Return None if there's no dot.
iter.next()?;
e
}
pub fn as_bytes(&self) -> &[u8] {
&self.inner
}
@ -467,4 +481,15 @@ mod test {
) {
PathBuf::from_host_path(&host_path, canonicalize_dotdot).expect_err("must fail");
}
#[rstest]
#[case::without_dot(PathBuf { inner: "foo".into()}, None)]
#[case::simple(PathBuf { inner: "foo.txt".into()}, Some(&b"txt"[..]))]
#[case::empty(PathBuf { inner: "foo.".into()}, Some(&b""[..]))]
#[case::multiple(PathBuf { inner: "foo.bar.txt".into()}, Some(&b"txt"[..]))]
#[case::with_components(PathBuf { inner: "foo/foo.txt".into()}, Some(&b"txt"[..]))]
#[case::path(PathBuf { inner: "foo.a/foo".into()}, None)]
fn extension(#[case] p: PathBuf, #[case] exp_extension: Option<&[u8]>) {
assert_eq!(exp_extension, p.extension())
}
}