tokio-fs: Add async versions of most of std::fs (#494)

* create_dir
* create_dir_all
* hard_link
* read_dir
* read_link
* remove_dir
* remove_file
* rename
* set_permissions that works with path
* symlink_metadata
* symlink on unix
* symlink_dir on windows
* symlink_file on windows
This commit is contained in:
Brian Olsen 2018-08-01 06:39:27 +02:00 committed by Carl Lerche
parent 0f76470172
commit 0490280d66
18 changed files with 888 additions and 1 deletions

View File

@ -7,4 +7,6 @@
//! the context of the Tokio runtime as they require Tokio specific features to
//! function.
pub use tokio_fs::{file, metadata, File, OpenOptions};
pub use tokio_fs::{create_dir, create_dir_all, file, hard_link, metadata, os, read_dir, read_link};
pub use tokio_fs::{remove_dir, remove_file, rename, set_permissions, symlink_metadata, File};
pub use tokio_fs::OpenOptions;

View File

@ -28,3 +28,4 @@ rand = "0.4.2"
tempdir = "0.3.7"
tokio-io = { version = "0.1.6", path = "../tokio-io" }
tokio-codec = { version = "0.1.0", path = "../tokio-codec" }
tokio = { version = "0.1.7", path = ".." }

View File

@ -0,0 +1,46 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Creates a new, empty directory at the provided path
///
/// This is an async version of [`std::fs::create_dir`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir.html
pub fn create_dir<P: AsRef<Path>>(path: P) -> CreateDirFuture<P> {
CreateDirFuture::new(path)
}
/// Future returned by `create_dir`.
#[derive(Debug)]
pub struct CreateDirFuture<P>
where
P: AsRef<Path>
{
path: P,
}
impl<P> CreateDirFuture<P>
where
P: AsRef<Path>
{
fn new(path: P) -> CreateDirFuture<P> {
CreateDirFuture {
path: path,
}
}
}
impl<P> Future for CreateDirFuture<P>
where
P: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::create_dir(&self.path) )
}
}

View File

@ -0,0 +1,47 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Recursively create a directory and all of its parent components if they
/// are missing.
///
/// This is an async version of [`std::fs::create_dir_all`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html
pub fn create_dir_all<P: AsRef<Path>>(path: P) -> CreateDirAllFuture<P> {
CreateDirAllFuture::new(path)
}
/// Future returned by `create_dir_all`.
#[derive(Debug)]
pub struct CreateDirAllFuture<P>
where
P: AsRef<Path>
{
path: P,
}
impl<P> CreateDirAllFuture<P>
where
P: AsRef<Path>
{
fn new(path: P) -> CreateDirAllFuture<P> {
CreateDirAllFuture {
path: path,
}
}
}
impl<P> Future for CreateDirAllFuture<P>
where
P: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::create_dir_all(&self.path) )
}
}

54
tokio-fs/src/hard_link.rs Normal file
View File

@ -0,0 +1,54 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Creates a new hard link on the filesystem.
///
/// The `dst` path will be a link pointing to the `src` path. Note that systems
/// often require these two paths to both be located on the same filesystem.
///
/// This is an async version of [`std::fs::hard_link`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.hard_link.html
pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> HardLinkFuture<P, Q> {
HardLinkFuture::new(src, dst)
}
/// Future returned by `hard_link`.
#[derive(Debug)]
pub struct HardLinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
src: P,
dst: Q,
}
impl<P, Q> HardLinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
fn new(src: P, dst: Q) -> HardLinkFuture<P, Q> {
HardLinkFuture {
src: src,
dst: dst,
}
}
}
impl<P, Q> Future for HardLinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::hard_link(&self.src, &self.dst) )
}
}

View File

@ -33,18 +33,39 @@ extern crate futures;
extern crate tokio_io;
extern crate tokio_threadpool;
mod create_dir;
mod create_dir_all;
pub mod file;
mod hard_link;
mod metadata;
pub mod os;
mod read_dir;
mod read_link;
mod remove_dir;
mod remove_file;
mod rename;
mod set_permissions;
mod stdin;
mod stdout;
mod stderr;
mod symlink_metadata;
pub use create_dir::{create_dir, CreateDirFuture};
pub use create_dir_all::{create_dir_all, CreateDirAllFuture};
pub use file::File;
pub use file::OpenOptions;
pub use hard_link::{hard_link, HardLinkFuture};
pub use metadata::{metadata, MetadataFuture};
pub use read_dir::{read_dir, ReadDirFuture, ReadDir, DirEntry};
pub use read_link::{read_link, ReadLinkFuture};
pub use remove_dir::{remove_dir, RemoveDirFuture};
pub use remove_file::{remove_file, RemoveFileFuture};
pub use rename::{rename, RenameFuture};
pub use set_permissions::{set_permissions, SetPermissionsFuture};
pub use stdin::{stdin, Stdin};
pub use stdout::{stdout, Stdout};
pub use stderr::{stderr, Stderr};
pub use symlink_metadata::{symlink_metadata, SymlinkMetadataFuture};
use futures::Poll;
use futures::Async::*;

6
tokio-fs/src/os/mod.rs Normal file
View File

@ -0,0 +1,6 @@
//! OS-specific functionality.
#[cfg(unix)]
pub mod unix;
#[cfg(windows)]
pub mod windows;

55
tokio-fs/src/os/unix.rs Normal file
View File

@ -0,0 +1,55 @@
//! Unix-specific extensions to primitives in the `tokio_fs` module.
use std::io;
use std::path::Path;
use std::os::unix::fs;
use futures::{Future, Poll};
/// Creates a new symbolic link on the filesystem.
///
/// The `dst` path will be a symbolic link pointing to the `src` path.
///
/// This is an async version of [`std::os::unix::fs::symlink`][std]
///
/// [std]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFuture<P, Q> {
SymlinkFuture::new(src, dst)
}
/// Future returned by `symlink`.
#[derive(Debug)]
pub struct SymlinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
src: P,
dst: Q,
}
impl<P, Q> SymlinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
fn new(src: P, dst: Q) -> SymlinkFuture<P, Q> {
SymlinkFuture {
src: src,
dst: dst,
}
}
}
impl<P, Q> Future for SymlinkFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::symlink(&self.src, &self.dst) )
}
}

View File

@ -0,0 +1,7 @@
//! Windows-specific extensions for the primitives in the `tokio_fs` module.
mod symlink_dir;
mod symlink_file;
pub use self::symlink_dir::{symlink_dir, SymlinkDirFuture};
pub use self::symlink_file::{symlink_file, SymlinkFileFuture};

View File

@ -0,0 +1,54 @@
use std::io;
use std::path::Path;
use std::os::windows::fs;
use futures::{Future, Poll};
/// Creates a new directory symlink on the filesystem.
///
/// The `dst` path will be a directory symbolic link pointing to the `src`
/// path.
///
/// This is an async version of [`std::os::windows::fs::symlink_dir`][std]
///
/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
SymlinkDirFuture::new(src, dst)
}
/// Future returned by `symlink_dir`.
#[derive(Debug)]
pub struct SymlinkDirFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
src: P,
dst: Q,
}
impl<P, Q> SymlinkDirFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
fn new(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
SymlinkDirFuture {
src: src,
dst: dst,
}
}
}
impl<P, Q> Future for SymlinkDirFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::symlink_dir(&self.src, &self.dst) )
}
}

View File

@ -0,0 +1,54 @@
use std::io;
use std::path::Path;
use std::os::windows::fs;
use futures::{Future, Poll};
/// Creates a new file symbolic link on the filesystem.
///
/// The `dst` path will be a file symbolic link pointing to the `src`
/// path.
///
/// This is an async version of [`std::os::windows::fs::symlink_file`][std]
///
/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
SymlinkFileFuture::new(src, dst)
}
/// Future returned by `symlink_file`.
#[derive(Debug)]
pub struct SymlinkFileFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
src: P,
dst: Q,
}
impl<P, Q> SymlinkFileFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
fn new(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
SymlinkFileFuture {
src: src,
dst: dst,
}
}
}
impl<P, Q> Future for SymlinkFileFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::symlink_file(&self.src, &self.dst) )
}
}

247
tokio-fs/src/read_dir.rs Normal file
View File

@ -0,0 +1,247 @@
use std::ffi::OsString;
use std::fs::{self, DirEntry as StdDirEntry, ReadDir as StdReadDir, FileType, Metadata};
use std::io;
#[cfg(unix)]
use std::os::unix::fs::DirEntryExt;
use std::path::{Path, PathBuf};
use futures::{Future, Poll, Stream};
/// Returns a stream over the entries within a directory.
///
/// This is an async version of [`std::fs::read_dir`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
pub fn read_dir<P>(path: P) -> ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
ReadDirFuture::new(path)
}
/// Future returned by `read_dir`.
#[derive(Debug)]
pub struct ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
path: P,
}
impl<P> ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static
{
fn new(path: P) -> ReadDirFuture<P> {
ReadDirFuture {
path: path,
}
}
}
impl<P> Future for ReadDirFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
type Item = ReadDir;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, io::Error> {
::blocking_io(|| Ok(ReadDir(fs::read_dir(&self.path)?)))
}
}
/// Stream of the entries in a directory.
///
/// This stream is returned from the [`read_dir`] function of this module and
/// will yield instances of [`DirEntry`]. Through a [`DirEntry`]
/// information like the entry's path and possibly other metadata can be
/// learned.
///
/// # Errors
///
/// This [`Stream`] will return an [`Err`] if there's some sort of intermittent
/// IO error during iteration.
///
/// [`read_dir`]: fn.read_dir.html
/// [`DirEntry`]: struct.DirEntry.html
/// [`Stream`]: ../futures/stream/trait.Stream.html
/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
#[derive(Debug)]
pub struct ReadDir(StdReadDir);
impl Stream for ReadDir {
type Item = DirEntry;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
::blocking_io(|| {
match self.0.next() {
Some(Err(err)) => Err(err),
Some(Ok(item)) => Ok(Some(DirEntry(item))),
None => Ok(None)
}
})
}
}
/// Entries returned by the [`ReadDir`] stream.
///
/// [`ReadDir`]: struct.ReadDir.html
///
/// This is a specialized version of [`std::fs::DirEntry`][std] for usage from the
/// Tokio runtime.
///
/// An instance of `DirEntry` represents an entry inside of a directory on the
/// filesystem. Each entry can be inspected via methods to learn about the full
/// path or possibly other metadata through per-platform extension traits.
///
/// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
#[derive(Debug)]
pub struct DirEntry(StdDirEntry);
impl DirEntry {
/// Destructures the `tokio_fs::DirEntry` into a [`std::fs::DirEntry`][std].
///
/// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
pub fn into_std(self) -> StdDirEntry {
self.0
}
/// Returns the full path to the file that this entry represents.
///
/// The full path is created by joining the original path to `read_dir`
/// with the filename of this entry.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate tokio_fs;
/// use futures::{Future, Stream};
///
/// fn main() {
/// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
/// println!("{:?}", dir.path());
/// Ok(())
/// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
/// tokio::run(fut);
/// }
/// ```
///
/// This prints output like:
///
/// ```text
/// "./whatever.txt"
/// "./foo.html"
/// "./hello_world.rs"
/// ```
///
/// The exact text, of course, depends on what files you have in `.`.
pub fn path(&self) -> PathBuf {
self.0.path()
}
/// Returns the bare file name of this directory entry without any other
/// leading path component.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate tokio_fs;
/// use futures::{Future, Stream};
///
/// fn main() {
/// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
/// // Here, `dir` is a `DirEntry`.
/// println!("{:?}", dir.file_name());
/// Ok(())
/// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
/// tokio::run(fut);
/// }
/// ```
pub fn file_name(&self) -> OsString {
self.0.file_name()
}
/// Return the metadata for the file that this entry points at.
///
/// This function will not traverse symlinks if this entry points at a
/// symlink.
///
/// # Platform-specific behavior
///
/// On Windows this function is cheap to call (no extra system calls
/// needed), but on Unix platforms this function is the equivalent of
/// calling `symlink_metadata` on the path.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate tokio_fs;
/// use futures::{Future, Stream};
/// use futures::future::poll_fn;
///
/// fn main() {
/// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
/// // Here, `dir` is a `DirEntry`.
/// let path = dir.path();
/// poll_fn(move || dir.poll_metadata()).map(move |metadata| {
/// println!("{:?}: {:?}", path, metadata.permissions());
/// })
/// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
/// tokio::run(fut);
/// }
/// ```
pub fn poll_metadata(&self) -> Poll<Metadata, io::Error> {
::blocking_io(|| self.0.metadata())
}
/// Return the file type for the file that this entry points at.
///
/// This function will not traverse symlinks if this entry points at a
/// symlink.
///
/// # Platform-specific behavior
///
/// On Windows and most Unix platforms this function is free (no extra
/// system calls needed), but some Unix platforms may require the equivalent
/// call to `symlink_metadata` to learn about the target file type.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate tokio_fs;
/// use futures::{Future, Stream};
/// use futures::future::poll_fn;
///
/// fn main() {
/// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
/// // Here, `dir` is a `DirEntry`.
/// let path = dir.path();
/// poll_fn(move || dir.poll_file_type()).map(move |file_type| {
/// // Now let's show our entry's file type!
/// println!("{:?}: {:?}", path, file_type);
/// })
/// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
/// tokio::run(fut);
/// }
/// ```
pub fn poll_file_type(&self) -> Poll<FileType, io::Error> {
::blocking_io(|| self.0.file_type())
}
}
#[cfg(unix)]
impl DirEntryExt for DirEntry {
fn ino(&self) -> u64 {
self.0.ino()
}
}

46
tokio-fs/src/read_link.rs Normal file
View File

@ -0,0 +1,46 @@
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use futures::{Future, Poll};
/// Reads a symbolic link, returning the file that the link points to.
///
/// This is an async version of [`std::fs::read_link`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.read_link.html
pub fn read_link<P: AsRef<Path>>(path: P) -> ReadLinkFuture<P> {
ReadLinkFuture::new(path)
}
/// Future returned by `read_link`.
#[derive(Debug)]
pub struct ReadLinkFuture<P>
where
P: AsRef<Path>
{
path: P,
}
impl<P> ReadLinkFuture<P>
where
P: AsRef<Path>
{
fn new(path: P) -> ReadLinkFuture<P> {
ReadLinkFuture {
path: path,
}
}
}
impl<P> Future for ReadLinkFuture<P>
where
P: AsRef<Path>
{
type Item = PathBuf;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::read_link(&self.path) )
}
}

View File

@ -0,0 +1,46 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Removes an existing, empty directory.
///
/// This is an async version of [`std::fs::remove_dir`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html
pub fn remove_dir<P: AsRef<Path>>(path: P) -> RemoveDirFuture<P> {
RemoveDirFuture::new(path)
}
/// Future returned by `remove_dir`.
#[derive(Debug)]
pub struct RemoveDirFuture<P>
where
P: AsRef<Path>
{
path: P,
}
impl<P> RemoveDirFuture<P>
where
P: AsRef<Path>
{
fn new(path: P) -> RemoveDirFuture<P> {
RemoveDirFuture {
path: path,
}
}
}
impl<P> Future for RemoveDirFuture<P>
where
P: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::remove_dir(&self.path) )
}
}

View File

@ -0,0 +1,50 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Removes a file from the filesystem.
///
/// Note that there is no
/// guarantee that the file is immediately deleted (e.g. depending on
/// platform, other open file descriptors may prevent immediate removal).
///
/// This is an async version of [`std::fs::remove_file`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.remove_file.html
pub fn remove_file<P: AsRef<Path>>(path: P) -> RemoveFileFuture<P> {
RemoveFileFuture::new(path)
}
/// Future returned by `remove_file`.
#[derive(Debug)]
pub struct RemoveFileFuture<P>
where
P: AsRef<Path>
{
path: P,
}
impl<P> RemoveFileFuture<P>
where
P: AsRef<Path>
{
fn new(path: P) -> RemoveFileFuture<P> {
RemoveFileFuture {
path: path,
}
}
}
impl<P> Future for RemoveFileFuture<P>
where
P: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::remove_file(&self.path) )
}
}

54
tokio-fs/src/rename.rs Normal file
View File

@ -0,0 +1,54 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Rename a file or directory to a new name, replacing the original file if
/// `to` already exists.
///
/// This will not work if the new name is on a different mount point.
///
/// This is an async version of [`std::fs::rename`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.rename.html
pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> RenameFuture<P, Q> {
RenameFuture::new(from, to)
}
/// Future returned by `rename`.
#[derive(Debug)]
pub struct RenameFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
from: P,
to: Q,
}
impl<P, Q> RenameFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
fn new(from: P, to: Q) -> RenameFuture<P, Q> {
RenameFuture {
from: from,
to: to,
}
}
}
impl<P, Q> Future for RenameFuture<P, Q>
where
P: AsRef<Path>,
Q: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::rename(&self.from, &self.to) )
}
}

View File

@ -0,0 +1,48 @@
use std::fs;
use std::io;
use std::path::Path;
use futures::{Future, Poll};
/// Changes the permissions found on a file or a directory.
///
/// This is an async version of [`std::fs::set_permissions`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html
pub fn set_permissions<P: AsRef<Path>>(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
SetPermissionsFuture::new(path, perm)
}
/// Future returned by `set_permissions`.
#[derive(Debug)]
pub struct SetPermissionsFuture<P>
where
P: AsRef<Path>
{
path: P,
perm: fs::Permissions,
}
impl<P> SetPermissionsFuture<P>
where
P: AsRef<Path>
{
fn new(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
SetPermissionsFuture {
path: path,
perm: perm,
}
}
}
impl<P> Future for SetPermissionsFuture<P>
where
P: AsRef<Path>
{
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
::blocking_io(|| fs::set_permissions(&self.path, self.perm.clone()) )
}
}

View File

@ -0,0 +1,49 @@
use super::blocking_io;
use futures::{Future, Poll};
use std::fs::{self, Metadata};
use std::io;
use std::path::Path;
/// Queries the file system metadata for a path.
///
/// This is an async version of [`std::fs::symlink_metadata`][std]
///
/// [std]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html
pub fn symlink_metadata<P>(path: P) -> SymlinkMetadataFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
SymlinkMetadataFuture::new(path)
}
/// Future returned by `symlink_metadata`.
#[derive(Debug)]
pub struct SymlinkMetadataFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
path: P,
}
impl<P> SymlinkMetadataFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
pub(crate) fn new(path: P) -> Self {
Self { path }
}
}
impl<P> Future for SymlinkMetadataFuture<P>
where
P: AsRef<Path> + Send + 'static,
{
type Item = Metadata;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
blocking_io(|| fs::symlink_metadata(&self.path))
}
}