From e27b578c27057478d01bdc3abe5fe48c2ace5cc7 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Sun, 13 Oct 2019 13:06:39 +0200 Subject: [PATCH] WIP init Path and PathBuf async stubs --- src/fs/canonicalize.rs | 8 ++-- src/lib.rs | 3 +- src/path/mod.rs | 6 +++ src/path/path.rs | 105 +++++++++++++++++++++++++++++++++++++++++ src/path/pathbuf.rs | 34 +++++++++++++ 5 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 src/path/path.rs create mode 100644 src/path/pathbuf.rs diff --git a/src/fs/canonicalize.rs b/src/fs/canonicalize.rs index c484aeeb..84278cb5 100644 --- a/src/fs/canonicalize.rs +++ b/src/fs/canonicalize.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use crate::path::{Path, PathBuf}; use crate::io; use crate::task::blocking; @@ -32,6 +32,8 @@ use crate::task::blocking; /// # Ok(()) }) } /// ``` pub async fn canonicalize>(path: P) -> io::Result { - let path = path.as_ref().to_owned(); - blocking::spawn(async move { std::fs::canonicalize(path) }).await + let path: std::path::PathBuf = path.as_ref().to_path_buf().into(); + Ok(blocking::spawn(async move { std::fs::canonicalize(&path) }) + .await? + .into()) } diff --git a/src/lib.rs b/src/lib.rs index fa4e946f..83453cd6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,7 @@ pub mod future; pub mod io; pub mod net; pub mod os; +pub mod path; pub mod prelude; pub mod stream; pub mod sync; @@ -62,8 +63,6 @@ pub mod task; cfg_if! { if #[cfg(any(feature = "unstable", feature = "docs"))] { - #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - pub mod path; #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub mod pin; diff --git a/src/path/mod.rs b/src/path/mod.rs index 91532439..35a67179 100644 --- a/src/path/mod.rs +++ b/src/path/mod.rs @@ -4,6 +4,9 @@ //! //! [`std::path`]: https://doc.rust-lang.org/std/path/index.html +mod path; +mod pathbuf; + // Structs re-export #[doc(inline)] pub use std::path::{Ancestors, Components, Display, Iter, PrefixComponent, StripPrefixError}; @@ -19,3 +22,6 @@ pub use std::path::MAIN_SEPARATOR; // Functions re-export #[doc(inline)] pub use std::path::is_separator; + +pub use path::Path; +pub use pathbuf::PathBuf; diff --git a/src/path/path.rs b/src/path/path.rs new file mode 100644 index 00000000..11dda640 --- /dev/null +++ b/src/path/path.rs @@ -0,0 +1,105 @@ +use std::ffi::OsStr; + +use crate::path::PathBuf; +use crate::{fs, io}; + +/// This struct is an async version of [`std::path::Path`]. +/// +/// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +pub struct Path { + inner: OsStr, +} + +impl Path { + /// Yields the underlying [`OsStr`] slice. + /// + /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html + pub fn as_os_str(&self) -> &OsStr { + &self.inner + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This is an alias to [`fs::canonicalize`]. + /// + /// [`fs::canonicalize`]: ../fs/fn.canonicalize.html + /// + /// # Examples + /// + /// ```no_run + /// use crate::path::{Path, PathBuf}; + /// + /// let path = Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); + /// ``` + pub async fn canonicalize(&self) -> io::Result { + fs::canonicalize(self).await + } + + /// Directly wraps a string slice as a `Path` slice. + /// + /// This is a cost-free conversion. + /// + /// # Examples + /// + /// ``` + /// use crate::path::Path; + /// + /// Path::new("foo.txt"); + /// ``` + /// + /// You can create `Path`s from `String`s, or even other `Path`s: + /// + /// ``` + /// use crate::path::Path; + /// + /// let string = String::from("foo.txt"); + /// let from_string = Path::new(&string); + /// let from_path = Path::new(&from_string); + /// assert_eq!(from_string, from_path); + /// ``` + pub fn new + ?Sized>(s: &S) -> &Path { + unsafe { &*(s.as_ref() as *const OsStr as *const Path) } + } + + /// Converts a `Path` to an owned [`PathBuf`]. + /// + /// [`PathBuf`]: struct.PathBuf.html + /// + /// # Examples + /// + /// ``` + /// use crate::path::{Path, PathBuf}; + /// + /// let path_buf = Path::new("foo.txt").to_path_buf(); + /// assert_eq!(path_buf, PathBuf::from("foo.txt")); + /// ``` + pub fn to_path_buf(&self) -> PathBuf { + PathBuf::from(self.inner.to_os_string()) + } +} + +impl<'a> From<&'a std::path::Path> for &'a Path { + fn from(path: &'a std::path::Path) -> &'a Path { + &Path::new(path.as_os_str()) + } +} + +impl<'a> Into<&'a std::path::Path> for &'a Path { + fn into(self) -> &'a std::path::Path { + std::path::Path::new(&self.inner) + } +} + +impl AsRef for Path { + fn as_ref(&self) -> &Path { + 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) + } +} diff --git a/src/path/pathbuf.rs b/src/path/pathbuf.rs new file mode 100644 index 00000000..8e379adb --- /dev/null +++ b/src/path/pathbuf.rs @@ -0,0 +1,34 @@ +use std::ffi::OsString; + +/// This struct is an async version of [`std::path::PathBuf`]. +/// +/// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html +pub struct PathBuf { + inner: OsString, +} + +impl From for PathBuf { + fn from(path: std::path::PathBuf) -> PathBuf { + PathBuf { + inner: path.into_os_string(), + } + } +} + +impl Into for PathBuf { + fn into(self) -> std::path::PathBuf { + self.inner.into() + } +} + +impl From for PathBuf { + fn from(path: OsString) -> PathBuf { + PathBuf { inner: path } + } +} + +impl std::fmt::Debug for PathBuf { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Debug::fmt(&self.inner, formatter) + } +}