#path #removing #component #last #path-buf #traits #poppable

poppable-path

A trait for removing the last component of a path-like thing

1 unstable release

new 0.1.0 Jan 8, 2025

#3 in #removing

40 downloads per month

MIT license

6KB
54 lines

Poppable paths

This Rust crate provides the [Poppable] trait for removing the last component of [Path]-like things.

Motivation

If you are like me[^1], you sometimes end up writing a lot of generic code involving traits with provided methods. For example something like

trait PathGenerator<'a> {
    /// Something path-like that may or may not depend on the lifetime `'a`
    type Path: AsRef<std::path::Path>;

    fn path(&'a self) -> Self::Path;

    fn dir(&'a self) -> Option<PathBuf> {
        let path = self.path().as_ref().to_owned();
        if path.is_dir() {
            Some(path)
        } else if !path.pop() {
            None
        } else if path.is_dir() {
            Some(path)
        } else {
            None
        }
    }
}

Which includes a maybe very unnecessary allocation in the form of a conversion to PathBuf. If we knew that the Self::Path returned by PathGenerator::path was &'a Path, we could use Path::parent rather than PathBuf::pop. If we knew it was PathBuf we could just mutate and return that value directly.

The purpose of this crate is helping in these situations. Because if we can have our cake and eat it we have our cake and eat eet:

trait PathGenerator<'a> {
    type Path: Poppable + AsRef<std::path::Path>;

    fn path(&'a self) -> Self::Path;

    fn dir(&'a self) -> Option<Self::Path> {
        let mut path = self.path();
        if path.as_ref().is_dir() {
            Some(path)
        } else if !path.pop() {
            None
        } else if path.as_ref().is_dir() {
            Some(path)
        } else {
            None
        }
    }
}

License

This work is licensed under the MIT license. See the LICENSE file for details.

[^1]: an idiot

No runtime deps