path-absolutize
Extension trait that turns any Rust Path or PathBuf into a clean absolute path without touching the filesystem.
Repository Health
Technical Analysis
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
Absolutizetrait implemented for bothPathandPathBuf, usable immediately afteruse path_absolutize::*with no setup absolutize()for resolving a path against the actual current working directory, returning aCow<Path>to avoid unnecessary allocation when the path is already absoluteabsolutize_from()for resolving a relative path against an explicit, caller-supplied working directory instead of the real CWDabsolutize_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_workdirCargo feature that caches the CWD once viapath_dedot::CWDfor 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.