pathdiff

Tiny Rust library for computing a relative path between two paths

Library
Cargo
v0.2.3
68stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
28/100Needs Attention
Development Activity0
Maintenance0
Community40
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture65
Code Quality78
Innovation55
Learning Curve85

pathdiff is a minimal Rust crate with a single core job: given two filesystem paths, compute a relative path from one to the other. Its diff_paths(path, base) function is adapted directly from rustc’s own internal path-relativization logic (originally used to compute rpaths), handling edge cases like absolute-vs-relative mismatches, ./.. components, and shared path prefixes correctly rather than relying on naive string manipulation.

The crate has essentially no runtime overhead beyond the standard library’s std::path types, and optionally supports UTF-8-only paths via the camino crate’s Utf8Path/Utf8PathBuf types behind a feature flag, exposing an equivalent diff_utf8_paths function. With over 165 million downloads, it has become a de facto standard building block wherever Rust tooling needs to display or construct relative paths — build systems, linters, documentation generators, and general CLI tools alike.

What You Get

  • diff_paths(path, base) -> Option<PathBuf> for computing a relative path between two std::path::Path-like inputs
  • Correct handling of absolute-vs-relative path mismatches (returns None when no relative path is meaningful)
  • Correct handling of ./.. normalization and shared path-prefix elimination
  • An optional camino feature adding diff_utf8_paths for UTF-8-only Utf8Path/Utf8PathBuf types
  • Zero mandatory runtime dependencies beyond the standard library
  • Extensive inline doctest and unit test coverage of relative-path edge cases

Common Use Cases

  • Displaying user-friendly relative paths in CLI tool output (e.g. linters, formatters, build tools reporting file locations)
  • Computing relative import/include paths when generating or rewriting source files
  • Producing relative links between generated documentation pages that live at different directory depths
  • Normalizing configuration or manifest paths relative to a project root before further processing

Under The Hood

Architecture - The entire crate is a single file, src/lib.rs, with one core algorithm implemented twice: once for std::path::Path (diff_paths) and once for camino::Utf8Path (diff_utf8_paths, gated behind the camino feature) since Rust’s standard path types and camino’s UTF-8-guaranteed path types aren’t interchangeable. Both implementations walk the component iterators of path and base in lockstep, first stripping a leading . component from each, then either short-circuiting on absolute/relative mismatches or building up a Vec of ParentDir/matched components representing the relative path, returning None for cases where no relative path exists (e.g. relative path with a .. base component it can’t resolve past).

Tech Stack - Pure Rust (edition 2018) with no mandatory dependencies; the only dependency, camino (for UTF-8 path types), is entirely optional and gated behind a feature flag, keeping the default build essentially dependency-free. cfg-if is used only in the dev-dependency test suite to select Windows vs. Unix absolute-path prefixes.

Code Quality - The single source file mixes extensive doctested examples directly in the function’s doc comments (covering absolute/relative combinations, string vs. Path inputs) with a dedicated #[cfg(test)] mod tests covering absolute paths, identity, subset, empty-string, relative, and current-directory edge cases — a strong ratio of test coverage to code size for a crate this small, which matters given how easy off-by-one/prefix bugs are in path-diffing logic. The logic itself is a direct, credited adaptation of rustc’s own internal path_relative_from implementation rather than a from-scratch reimplementation.

API Design - The API is deliberately tiny: one generic function, diff_paths<P: AsRef<Path>, B: AsRef<Path>>(path, base) -> Option<PathBuf>, that accepts anything convertible to a Path (string slices, String, PathBuf, Path references) and returns None only in the genuinely ambiguous case of a relative path measured against an absolute base. This ‘accept anything path-like, return an Option’ design requires zero setup or configuration, making it trivial to drop into any codebase that needs relative-path computation.

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