Skip to content

Implement async Path & PathBuf #320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e27b578
WIP init Path and PathBuf async stubs
Wassasin Oct 13, 2019
3bd6a9d
Implemented components
Wassasin Oct 13, 2019
930b818
Use std variants of Path and PathBuf internally
Wassasin Oct 13, 2019
e690b55
Implemented fs::metadata and Path::exists
Wassasin Oct 13, 2019
6bbfd03
Fixed various tests
Wassasin Oct 13, 2019
6c6106a
Implemented Path::{metadata, symlink_metadata}
Wassasin Oct 13, 2019
a57ba7e
Implemented Path::into_path_buf
Wassasin Oct 13, 2019
759e357
Implemented Path::ancestors
Wassasin Oct 13, 2019
5235cd5
Implemented Path::display
Wassasin Oct 13, 2019
4070833
Implemented Path::ends_with
Wassasin Oct 13, 2019
a7eaae9
Implemented Path::extension
Wassasin Oct 13, 2019
a6e1abe
Implemented Path::file_name
Wassasin Oct 13, 2019
28e936f
Implemented Path::file_stem
Wassasin Oct 13, 2019
3a9597c
Implemented Path::has_root
Wassasin Oct 13, 2019
20f58ea
Implemented Path::is_absolute
Wassasin Oct 13, 2019
df9a01f
Implemented Path::is_file
Wassasin Oct 13, 2019
5d87006
Implemented Path::is_relative
Wassasin Oct 13, 2019
0c03b92
Implemented Path::iter
Wassasin Oct 13, 2019
cc57db0
Implemented Path::join
Wassasin Oct 13, 2019
141954d
Implemented Path::parent
Wassasin Oct 13, 2019
89f73d3
Implemented Path::read_dir
Wassasin Oct 13, 2019
d349333
Implemented Path::read_link
Wassasin Oct 13, 2019
942403c
Implemented Path::starts_with
Wassasin Oct 13, 2019
df53a07
Implemented Path::strip_prefix
Wassasin Oct 13, 2019
ea43d7f
Implemented Path::to_str
Wassasin Oct 13, 2019
a17b017
Implemented Path::to_string_lossy
Wassasin Oct 13, 2019
3c24b18
Implemented Path::with_extension
Wassasin Oct 13, 2019
409a10a
Implemented Path::with_file_name
Wassasin Oct 13, 2019
1bd17f1
Implemented PathBuf::as_path
Wassasin Oct 13, 2019
80eaa28
Implemented PathBuf::into_boxed_path
Wassasin Oct 13, 2019
47ef222
Implemented PathBuf::into_os_string
Wassasin Oct 13, 2019
71125d5
Implemented PathBuf::new
Wassasin Oct 13, 2019
07f9e48
Implemented PathBuf::pop
Wassasin Oct 13, 2019
cc417cc
Implemented PathBuf::push
Wassasin Oct 13, 2019
54c94b7
Implemented PathBuf::set_extension
Wassasin Oct 13, 2019
8df55dd
Implemented PathBuf::set_file_name
Wassasin Oct 13, 2019
ba87048
Implemented our own Path::ancestors iterator
Wassasin Oct 14, 2019
0adcb50
Add ToOwned and Borrow impls
Oct 14, 2019
f9cfee9
Formatting
Oct 14, 2019
504f8cb
Use crate::path everywhere
Oct 14, 2019
5c1e052
Fix failing tests
Oct 14, 2019
aa13ba7
Refactor
Oct 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/fs/canonicalize.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::{Path, PathBuf};
use crate::path::{Path, PathBuf};

use crate::io;
use crate::task::blocking;
Expand Down Expand Up @@ -32,6 +32,8 @@ use crate::task::blocking;
/// # Ok(()) }) }
/// ```
pub async fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
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())
}
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,14 @@ pub mod future;
pub mod io;
pub mod net;
pub mod os;
pub mod path;
pub mod prelude;
pub mod stream;
pub mod sync;
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;

Expand Down
6 changes: 6 additions & 0 deletions src/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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;
105 changes: 105 additions & 0 deletions src/path/path.rs
Original file line number Diff line number Diff line change
@@ -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<PathBuf> {
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<S: AsRef<OsStr> + ?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<Path> 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)
}
}
34 changes: 34 additions & 0 deletions src/path/pathbuf.rs
Original file line number Diff line number Diff line change
@@ -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<std::path::PathBuf> for PathBuf {
fn from(path: std::path::PathBuf) -> PathBuf {
PathBuf {
inner: path.into_os_string(),
}
}
}

impl Into<std::path::PathBuf> for PathBuf {
fn into(self) -> std::path::PathBuf {
self.inner.into()
}
}

impl From<OsString> 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)
}
}