diff --git a/tokio-fs/src/file/metadata.rs b/tokio-fs/src/file/metadata.rs new file mode 100644 index 000000000..b55ca103c --- /dev/null +++ b/tokio-fs/src/file/metadata.rs @@ -0,0 +1,39 @@ +use super::File; + +use futures::{Future, Poll}; + +use std::fs::File as StdFile; +use std::fs::Metadata; +use std::io; + +const POLL_AFTER_RESOLVE: &str = "Cannot poll MetadataFuture after it resolves"; + +/// Future returned by `File::metadata` and resolves to a `(Metadata, File)` instance. +#[derive(Debug)] +pub struct MetadataFuture { + file: Option, +} + +impl MetadataFuture { + pub(crate) fn new(file: File) -> Self { + MetadataFuture { file: Some(file) } + } + + fn std(&mut self) -> &mut StdFile { + self.file.as_mut().expect(POLL_AFTER_RESOLVE).std() + } +} + +impl Future for MetadataFuture { + type Item = (File, Metadata); + type Error = io::Error; + + fn poll(&mut self) -> Poll { + let metadata = try_ready!(::blocking_io(|| { + StdFile::metadata(self.std()) + })); + + let file = self.file.take().expect(POLL_AFTER_RESOLVE); + Ok((file, metadata).into()) + } +} diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file/mod.rs index f4f168615..5d64db1a6 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file/mod.rs @@ -3,10 +3,12 @@ //! [`File`]: file/struct.File.html mod create; +mod metadata; mod open; mod open_options; pub use self::create::CreateFuture; +pub use self::metadata::MetadataFuture; pub use self::open::OpenFuture; pub use self::open_options::OpenOptions; @@ -133,6 +135,11 @@ impl File { ::blocking_io(|| self.std().set_len(size)) } + /// Queries metadata about the underlying file. + pub fn metadata(self) -> MetadataFuture { + MetadataFuture::new(self) + } + /// Queries metadata about the underlying file. pub fn poll_metadata(&mut self) -> Poll { ::blocking_io(|| self.std().metadata()) diff --git a/tokio-fs/tests/file.rs b/tokio-fs/tests/file.rs index 5f97deb9a..690623682 100644 --- a/tokio-fs/tests/file.rs +++ b/tokio-fs/tests/file.rs @@ -41,7 +41,9 @@ fn read_write() { let contents = contents.clone(); File::create(file_path) - .and_then(move |file| io::write_all(file, contents)) + .and_then(|file| file.metadata()) + .inspect(|&(_, ref metadata)| assert!(metadata.is_file())) + .and_then(move |(file, _)| io::write_all(file, contents)) .and_then(|(mut file, _)| { poll_fn(move || file.poll_sync_all()) })