path-absolutize

Extension trait that turns any Rust Path or PathBuf into a clean absolute path without touching the filesystem.

Library
Cargo
v4.0.1
68stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity40
Maintenance8
Community36
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture70
Code Quality65
Innovation78
Learning Curve85

path-absolutize is a small, focused Rust crate that extends the standard library’s Path and PathBuf types with an Absolutize trait, giving them absolutize(), absolutize_from(), and absolutize_virtually() methods. Unlike std::fs::canonicalize, these methods never check whether the path exists or resolve symlinks — they purely parse . and .. components lexically and join against the current working directory (or a caller-supplied one), which makes them safe to use on paths that don’t exist yet, such as output file paths or user-supplied CLI arguments.

The crate builds on top of path-dedot for dot-parsing and offers an optional fixed_workdir feature that caches the current working directory once instead of re-reading it on every call, trading a small amount of runtime flexibility for better performance in hot paths. With platform-specific implementations for Unix and Windows path semantics, zero required configuration, and a single lightweight dependency, it’s a drop-in utility for CLI tools, build scripts, and file-processing code that need predictable, filesystem-independent path normalization.

What You Get

  • An Absolutize trait implemented for both Path and PathBuf, usable immediately after use path_absolutize::* with no setup
  • absolutize() for resolving a path against the actual current working directory, returning a Cow<Path> to avoid unnecessary allocation when the path is already absolute
  • absolutize_from() for resolving a relative path against an explicit, caller-supplied working directory instead of the real CWD
  • absolutize_virtually() for confining resolution to a virtual root directory, rejecting any path (absolute or relative) that would escape it — useful for sandboxed file access
  • An opt-in fixed_workdir Cargo feature that caches the CWD once via path_dedot::CWD for lower-overhead repeated calls
  • Correct, tested handling of both Unix and Windows path separator and root semantics via dedicated platform modules

Common Use Cases

  • Normalizing user-supplied or config-file paths in a CLI tool before writing output, even when the target file doesn’t exist yet
  • Resolving relative include or import paths in build scripts and code generators relative to a known base directory
  • Sandboxing file access in a service that accepts client-provided paths, using absolutize_virtually() to reject attempts to escape a designated root
  • Normalizing paths for consistent display, logging, or comparison without triggering filesystem I/O or symlink resolution
  • Resolving relative paths for embedded scripting or plugin systems where paths should be interpreted against a caller-defined working directory

Under The Hood

Architecture path-absolutize is built around a single public Absolutize trait (defined in src/absolutize.rs) implemented for both std::path::Path and std::path::PathBuf in src/lib.rs, with PathBuf’s implementation simply delegating to Path’s. The actual dot-resolution logic lives in platform-specific modules — src/unix.rs and src/windows.rs — selected at compile time via #[cfg(unix)]/#[cfg(windows)], because absolute-path and root semantics differ meaningfully between the two (single-rooted / on Unix versus drive-letter and UNC paths on Windows). absolutize_virtually() composes absolutize() on the virtual root with the sibling path-dedot crate’s lexical dot-parsing (ParseDot::parse_dot) to validate that the resolved path stays within bounds before returning it.

Tech Stack The crate is pure, dependency-light Rust (edition 2021, minimum Rust 1.80) with exactly one runtime dependency, path-dedot, which it also re-exports (pub extern crate path_dedot) so downstream users can access path_dedot::CWD directly when the fixed_workdir feature is enabled. Dev-dependencies are limited to bencher for benchmarking and, on Windows only, slash-formatter for test assertions. There is no async runtime, no unsafe code observed in the reviewed paths, and no I/O beyond an optional std::env::current_dir() call gated behind a small get_cwd! macro in src/macros.rs that swaps between a live syscall and the cached fixed_workdir value.

Code Quality The implementation is compact (roughly 900 lines across src/) and readable, using Cow<Path> throughout to avoid allocating when a path is already absolute and unchanged. Correctness is exercised through platform-specific integration tests (tests/unix.rs, tests/windows.rs) and an unusually large set of runnable doctests embedded in lib.rs’s module-level documentation, which double as both examples and regression tests for every documented parsing rule (leading dot, leading double-dot, non-rooted relative paths, and virtual-root boundary violations). Error handling is minimal by design — io::Result is used only where a real filesystem call (current_dir()) or a boundary violation can fail.

API Design The crate follows the idiomatic Rust extension-trait pattern: a single use path_absolutize::* import is all that’s needed to call .absolutize() directly on any Path or PathBuf value, with no builder, no configuration struct, and no runtime setup. Method names are self-describing and consistently prefixed (absolutize, absolutize_from, absolutize_virtually), and the crate-level documentation walks through every parsing rule with a matching, compilable example, which keeps the learning curve very shallow for a utility this size.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search