Ergonomic path manipulation for Rust — normalize, absolutize, relativize, and slash-convert with zero-cost Cow returns.
cargo add sugar_pathuse sugar_path::SugarPath;
// Normalize messy paths
assert_eq!("foo/./bar/../baz".normalize(), "foo/baz".as_path());
// Absolutize relative paths
let abs = "src/main.rs".absolutize();
// Get relative paths between two locations
assert_eq!("/a/b/c/d".as_path().relative("/a/b/f/g"), "../../c/d".as_path());
// Cross-platform slash conversion
assert_eq!("hello/world".as_path().to_slash_lossy(), "hello/world");All methods are provided by the SugarPath trait, implemented for Path, &str, and String.
| Method | Description |
|---|---|
as_path() |
Convert &str / String to &Path — lets you call SugarPath methods on strings directly |
to_slash() |
Convert a path to a /-separated string (None if invalid UTF-8) |
to_slash_lossy() |
Like to_slash(), but replaces invalid UTF-8 with U+FFFD |
use std::path::Path;
use sugar_path::SugarPath;
assert_eq!("foo".as_path().join("bar"), Path::new("foo/bar"));normalize() resolves . and .. segments and collapses repeated separators. Returns Cow::Borrowed when the path is already clean.
use std::path::Path;
use sugar_path::SugarPath;
#[cfg(target_family = "unix")]
assert_eq!(
Path::new("/foo/bar//baz/asdf/quux/..").normalize(),
Path::new("/foo/bar/baz/asdf")
);absolutize() resolves a relative path against the current working directory. absolutize_with() lets you supply a custom base.
use std::borrow::Cow;
use sugar_path::SugarPath;
#[cfg(target_family = "unix")]
{
assert_eq!("./world".absolutize_with(Cow::Borrowed("/hello".as_path())), "/hello/world".as_path());
assert_eq!("../world".absolutize_with(Cow::Borrowed("/hello".as_path())), "/world".as_path());
}relative() computes the relative path from self to a target.
use std::path::Path;
use sugar_path::SugarPath;
assert_eq!(Path::new("/base").relative("/base/lib"), Path::new(".."));
assert_eq!(Path::new("/base").relative("/var/lib"), Path::new("../../base"));
assert_eq!(Path::new("/a/b/c/d").relative("/a/b/f/g"), Path::new("../../c/d"));| Feature | Description |
|---|---|
cached_current_dir |
Cache std::env::current_dir() so absolutize() only reads it once |
sugar_path = { version = "2", features = ["cached_current_dir"] }- Zero-alloc fast paths — methods return
Cow<'_, Path>, borrowing the input when no transformation is needed. memchr-accelerated scanning for separator detection.SmallVec<[_; 8]>keeps component lists on the stack for typical path depths.
- Unix and Windows, tested in CI on Ubuntu, macOS, and Windows.
to_slash/to_slash_lossyprovide consistent/-separated output across all platforms.- On Windows, forward slashes in input are normalized to
\.
MIT