poppable-path

Crates.iopoppable-path
lib.rspoppable-path
version
sourcesrc
created_at2025-01-08 21:01:43.011434
updated_at2025-01-08 21:01:43.011434
descriptionA trait for removing the last component of a path-like thing
homepage
repository
max_upload_size
id1509072
Cargo.toml error:TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
maintainers (github:ngyn-rs:maintainers)

documentation

README

Poppable paths

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

Motivation

If you are like me1, 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.

Footnotes

  1. an idiot

Commit count: 0

cargo fmt