diff --git a/src/path/path.rs b/src/path/path.rs index 11dda64..f16c8c0 100644 --- a/src/path/path.rs +++ b/src/path/path.rs @@ -1,6 +1,6 @@ use std::ffi::OsStr; -use crate::path::PathBuf; +use crate::path::{Components, PathBuf}; use crate::{fs, io}; /// This struct is an async version of [`std::path::Path`]. @@ -28,7 +28,7 @@ impl Path { /// # Examples /// /// ```no_run - /// use crate::path::{Path, PathBuf}; + /// use async_std::path::{Path, PathBuf}; /// /// let path = Path::new("/foo/test/../test/bar.rs"); /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); @@ -37,6 +37,45 @@ impl Path { fs::canonicalize(self).await } + /// Produces an iterator over the [`Component`]s of the path. + /// + /// When parsing the path, there is a small amount of normalization: + /// + /// * Repeated separators are ignored, so `a/b` and `a//b` both have + /// `a` and `b` as components. + /// + /// * Occurrences of `.` are normalized away, except if they are at the + /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and + /// `a/b` all have `a` and `b` as components, but `./a/b` starts with + /// an additional [`CurDir`] component. + /// + /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. + /// + /// Note that no other normalization takes place; in particular, `a/c` + /// and `a/b/../c` are distinct, to account for the possibility that `b` + /// is a symbolic link (so its parent isn't `a`). + /// + /// # Examples + /// + /// ``` + /// use async_std::path::{Path, Component}; + /// use std::ffi::OsStr; + /// + /// let mut components = Path::new("/tmp/foo.txt").components(); + /// + /// assert_eq!(components.next(), Some(Component::RootDir)); + /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp")))); + /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt")))); + /// assert_eq!(components.next(), None) + /// ``` + /// + /// [`Component`]: enum.Component.html + /// [`CurDir`]: enum.Component.html#variant.CurDir + pub fn components(&self) -> Components<'_> { + let path: &std::path::Path = self.into(); + path.components() + } + /// Directly wraps a string slice as a `Path` slice. /// /// This is a cost-free conversion. @@ -44,7 +83,7 @@ impl Path { /// # Examples /// /// ``` - /// use crate::path::Path; + /// use async_std::path::Path; /// /// Path::new("foo.txt"); /// ``` @@ -52,7 +91,7 @@ impl Path { /// You can create `Path`s from `String`s, or even other `Path`s: /// /// ``` - /// use crate::path::Path; + /// use async_std::path::Path; /// /// let string = String::from("foo.txt"); /// let from_string = Path::new(&string); @@ -70,7 +109,7 @@ impl Path { /// # Examples /// /// ``` - /// use crate::path::{Path, PathBuf}; + /// use async_std::path::{Path, PathBuf}; /// /// let path_buf = Path::new("foo.txt").to_path_buf(); /// assert_eq!(path_buf, PathBuf::from("foo.txt")); @@ -98,8 +137,40 @@ impl AsRef for Path { } } +impl AsRef for OsStr { + fn as_ref(&self) -> &Path { + Path::new(self) + } +} + +impl AsRef for str { + fn as_ref(&self) -> &Path { + Path::new(self) + } +} + impl std::fmt::Debug for Path { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Debug::fmt(&self.inner, formatter) } } + +impl std::cmp::PartialEq for Path { + fn eq(&self, other: &Path) -> bool { + self.components().eq(other.components()) + } +} + +impl std::cmp::Eq for Path {} + +impl std::cmp::PartialOrd for Path { + fn partial_cmp(&self, other: &Path) -> Option { + self.components().partial_cmp(other.components()) + } +} + +impl std::cmp::Ord for Path { + fn cmp(&self, other: &Path) -> std::cmp::Ordering { + self.components().cmp(other.components()) + } +} \ No newline at end of file diff --git a/src/path/pathbuf.rs b/src/path/pathbuf.rs index 8e379ad..5ec0ed8 100644 --- a/src/path/pathbuf.rs +++ b/src/path/pathbuf.rs @@ -1,5 +1,7 @@ use std::ffi::OsString; +use crate::path::Path; + /// This struct is an async version of [`std::path::PathBuf`]. /// /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html @@ -27,6 +29,12 @@ impl From for PathBuf { } } +impl AsRef for PathBuf { + fn as_ref(&self) -> &Path { + Path::new(&self.inner) + } +} + impl std::fmt::Debug for PathBuf { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Debug::fmt(&self.inner, formatter)