poppable-path 0.1.0

A trait for removing the last component of a path-like thing
Documentation
  • Coverage
  • 100%
    3 out of 3 items documented1 out of 3 items with examples
  • Size
  • Source code size: 6.54 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.09 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 10s Average build duration of successful builds.
  • all releases: 10s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • neithernut

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