diff options
Diffstat (limited to 'third_party/rust/tokio-fs/src/file')
-rw-r--r-- | third_party/rust/tokio-fs/src/file/create.rs | 37 | ||||
-rw-r--r-- | third_party/rust/tokio-fs/src/file/metadata.rs | 39 | ||||
-rw-r--r-- | third_party/rust/tokio-fs/src/file/mod.rs | 243 | ||||
-rw-r--r-- | third_party/rust/tokio-fs/src/file/open.rs | 38 | ||||
-rw-r--r-- | third_party/rust/tokio-fs/src/file/open_options.rs | 103 | ||||
-rw-r--r-- | third_party/rust/tokio-fs/src/file/seek.rs | 37 |
6 files changed, 497 insertions, 0 deletions
diff --git a/third_party/rust/tokio-fs/src/file/create.rs b/third_party/rust/tokio-fs/src/file/create.rs new file mode 100644 index 0000000000..4027418563 --- /dev/null +++ b/third_party/rust/tokio-fs/src/file/create.rs @@ -0,0 +1,37 @@ +use super::File; + +use futures::{Future, Poll}; + +use std::fs::File as StdFile; +use std::io; +use std::path::Path; + +/// Future returned by `File::create` and resolves to a `File` instance. +#[derive(Debug)] +pub struct CreateFuture<P> { + path: P, +} + +impl<P> CreateFuture<P> +where P: AsRef<Path> + Send + 'static, +{ + pub(crate) fn new(path: P) -> Self { + CreateFuture { path } + } +} + +impl<P> Future for CreateFuture<P> +where P: AsRef<Path> + Send + 'static, +{ + type Item = File; + type Error = io::Error; + + fn poll(&mut self) -> Poll<Self::Item, Self::Error> { + let std = try_ready!(::blocking_io(|| { + StdFile::create(&self.path) + })); + + let file = File::from_std(std); + Ok(file.into()) + } +} diff --git a/third_party/rust/tokio-fs/src/file/metadata.rs b/third_party/rust/tokio-fs/src/file/metadata.rs new file mode 100644 index 0000000000..b55ca103c1 --- /dev/null +++ b/third_party/rust/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<File>, +} + +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<Self::Item, Self::Error> { + 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/third_party/rust/tokio-fs/src/file/mod.rs b/third_party/rust/tokio-fs/src/file/mod.rs new file mode 100644 index 0000000000..c3ae431121 --- /dev/null +++ b/third_party/rust/tokio-fs/src/file/mod.rs @@ -0,0 +1,243 @@ +//! Types for working with [`File`]. +//! +//! [`File`]: file/struct.File.html + +mod create; +mod metadata; +mod open; +mod open_options; +mod seek; + +pub use self::create::CreateFuture; +pub use self::metadata::MetadataFuture; +pub use self::open::OpenFuture; +pub use self::open_options::OpenOptions; +pub use self::seek::SeekFuture; + +use tokio_io::{AsyncRead, AsyncWrite}; + +use futures::Poll; + +use std::fs::{File as StdFile, Metadata, Permissions}; +use std::io::{self, Read, Write, Seek}; +use std::path::Path; + +/// A reference to an open file on the filesystem. +/// +/// This is a specialized version of [`std::fs::File`][std] for usage from the +/// Tokio runtime. +/// +/// An instance of a `File` can be read and/or written depending on what options +/// it was opened with. Files also implement Seek to alter the logical cursor +/// that the file contains internally. +/// +/// Files are automatically closed when they go out of scope. +/// +/// [std]: https://doc.rust-lang.org/std/fs/struct.File.html +#[derive(Debug)] +pub struct File { + std: Option<StdFile>, +} + +impl File { + /// Attempts to open a file in read-only mode. + /// + /// See [`OpenOptions`] for more details. + /// + /// [`OpenOptions`]: struct.OpenOptions.html + /// + /// # Errors + /// + /// `OpenFuture` results in an error if called from outside of the Tokio + /// runtime or if the underlying [`open`] call results in an error. + /// + /// [`open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open + pub fn open<P>(path: P) -> OpenFuture<P> + where P: AsRef<Path> + Send + 'static, + { + OpenOptions::new().read(true).open(path) + } + + /// Opens a file in write-only mode. + /// + /// This function will create a file if it does not exist, and will truncate + /// it if it does. + /// + /// See [`OpenOptions`] for more details. + /// + /// [`OpenOptions`]: struct.OpenOptions.html + /// + /// # Errors + /// + /// `CreateFuture` results in an error if called from outside of the Tokio + /// runtime or if the underlying [`create`] call results in an error. + /// + /// [`create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create + pub fn create<P>(path: P) -> CreateFuture<P> + where P: AsRef<Path> + Send + 'static, + { + CreateFuture::new(path) + } + + /// Convert a [`std::fs::File`][std] to a `tokio_fs::File`. + /// + /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html + pub(crate) fn from_std(std: StdFile) -> File { + File { std: Some(std) } + } + + /// Seek to an offset, in bytes, in a stream. + /// + /// A seek beyond the end of a stream is allowed, but implementation + /// defined. + /// + /// If the seek operation completed successfully, this method returns the + /// new position from the start of the stream. That position can be used + /// later with `SeekFrom::Start`. + /// + /// # Errors + /// + /// Seeking to a negative offset is considered an error. + pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll<u64, io::Error> { + ::blocking_io(|| self.std().seek(pos)) + } + + /// Seek to an offset, in bytes, in a stream. + /// + /// Similar to `poll_seek`, but returning a `Future`. + /// + /// This method consumes the `File` and returns it back when the future + /// completes. + pub fn seek(self, pos: io::SeekFrom) -> SeekFuture { + SeekFuture::new(self, pos) + } + + /// Attempts to sync all OS-internal metadata to disk. + /// + /// This function will attempt to ensure that all in-core data reaches the + /// filesystem before returning. + pub fn poll_sync_all(&mut self) -> Poll<(), io::Error> { + ::blocking_io(|| self.std().sync_all()) + } + + /// This function is similar to `poll_sync_all`, except that it may not + /// synchronize file metadata to the filesystem. + /// + /// This is intended for use cases that must synchronize content, but don't + /// need the metadata on disk. The goal of this method is to reduce disk + /// operations. + /// + /// Note that some platforms may simply implement this in terms of `poll_sync_all`. + pub fn poll_sync_data(&mut self) -> Poll<(), io::Error> { + ::blocking_io(|| self.std().sync_data()) + } + + /// Truncates or extends the underlying file, updating the size of this file to become size. + /// + /// If the size is less than the current file's size, then the file will be + /// shrunk. If it is greater than the current file's size, then the file + /// will be extended to size and have all of the intermediate data filled in + /// with 0s. + /// + /// # Errors + /// + /// This function will return an error if the file is not opened for + /// writing. + pub fn poll_set_len(&mut self, size: u64) -> Poll<(), io::Error> { + ::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<Metadata, io::Error> { + ::blocking_io(|| self.std().metadata()) + } + + /// Create a new `File` instance that shares the same underlying file handle + /// as the existing `File` instance. Reads, writes, and seeks will affect both + /// File instances simultaneously. + pub fn poll_try_clone(&mut self) -> Poll<File, io::Error> { + ::blocking_io(|| { + let std = self.std().try_clone()?; + Ok(File::from_std(std)) + }) + } + + /// Changes the permissions on the underlying file. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `fchmod` function on Unix and + /// the `SetFileInformationByHandle` function on Windows. Note that, this + /// [may change in the future][changes]. + /// + /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior + /// + /// # Errors + /// + /// This function will return an error if the user lacks permission change + /// attributes on the underlying file. It may also return an error in other + /// os-specific unspecified cases. + pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll<(), io::Error> { + ::blocking_io(|| self.std().set_permissions(perm)) + } + + /// Destructures the `tokio_fs::File` into a [`std::fs::File`][std]. + /// + /// # Panics + /// + /// This function will panic if `shutdown` has been called. + /// + /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html + pub fn into_std(mut self) -> StdFile { + self.std.take().expect("`File` instance already shutdown") + } + + fn std(&mut self) -> &mut StdFile { + self.std.as_mut().expect("`File` instance already shutdown") + } +} + +impl Read for File { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + ::would_block(|| self.std().read(buf)) + } +} + +impl AsyncRead for File { + unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { + false + } +} + +impl Write for File { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + ::would_block(|| self.std().write(buf)) + } + + fn flush(&mut self) -> io::Result<()> { + ::would_block(|| self.std().flush()) + } +} + +impl AsyncWrite for File { + fn shutdown(&mut self) -> Poll<(), io::Error> { + ::blocking_io(|| { + self.std = None; + Ok(()) + }) + } +} + +impl Drop for File { + fn drop(&mut self) { + if let Some(_std) = self.std.take() { + // This is probably fine as closing a file *shouldn't* be a blocking + // operation. That said, ideally `shutdown` is called first. + } + } +} diff --git a/third_party/rust/tokio-fs/src/file/open.rs b/third_party/rust/tokio-fs/src/file/open.rs new file mode 100644 index 0000000000..197ec237af --- /dev/null +++ b/third_party/rust/tokio-fs/src/file/open.rs @@ -0,0 +1,38 @@ +use super::File; + +use futures::{Future, Poll}; + +use std::fs::OpenOptions as StdOpenOptions; +use std::io; +use std::path::Path; + +/// Future returned by `File::open` and resolves to a `File` instance. +#[derive(Debug)] +pub struct OpenFuture<P> { + options: StdOpenOptions, + path: P, +} + +impl<P> OpenFuture<P> +where P: AsRef<Path> + Send + 'static, +{ + pub(crate) fn new(options: StdOpenOptions, path: P) -> Self { + OpenFuture { options, path } + } +} + +impl<P> Future for OpenFuture<P> +where P: AsRef<Path> + Send + 'static, +{ + type Item = File; + type Error = io::Error; + + fn poll(&mut self) -> Poll<Self::Item, Self::Error> { + let std = try_ready!(::blocking_io(|| { + self.options.open(&self.path) + })); + + let file = File::from_std(std); + Ok(file.into()) + } +} diff --git a/third_party/rust/tokio-fs/src/file/open_options.rs b/third_party/rust/tokio-fs/src/file/open_options.rs new file mode 100644 index 0000000000..99cc71c5b0 --- /dev/null +++ b/third_party/rust/tokio-fs/src/file/open_options.rs @@ -0,0 +1,103 @@ +use super::OpenFuture; + +use std::convert::From; +use std::fs::OpenOptions as StdOpenOptions; +use std::path::Path; + +/// Options and flags which can be used to configure how a file is opened. +/// +/// This is a specialized version of [`std::fs::OpenOptions`] for usage from +/// the Tokio runtime. +/// +/// `From<std::fs::OpenOptions>` is implemented for more advanced configuration +/// than the methods provided here. +/// +/// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html +#[derive(Clone, Debug)] +pub struct OpenOptions(StdOpenOptions); + +impl OpenOptions { + /// Creates a blank new set of options ready for configuration. + /// + /// All options are initially set to `false`. + /// + /// # Examples + /// + /// ```ignore + /// use tokio::fs::OpenOptions; + /// + /// let mut options = OpenOptions::new(); + /// let future = options.read(true).open("foo.txt"); + /// ``` + pub fn new() -> OpenOptions { + OpenOptions(StdOpenOptions::new()) + } + + /// See the underlying [`read`] call for details. + /// + /// [`read`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.read + pub fn read(&mut self, read: bool) -> &mut OpenOptions { + self.0.read(read); + self + } + + /// See the underlying [`write`] call for details. + /// + /// [`write`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.write + pub fn write(&mut self, write: bool) -> &mut OpenOptions { + self.0.write(write); + self + } + + /// See the underlying [`append`] call for details. + /// + /// [`append`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.append + pub fn append(&mut self, append: bool) -> &mut OpenOptions { + self.0.append(append); + self + } + + /// See the underlying [`truncate`] call for details. + /// + /// [`truncate`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.truncate + pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { + self.0.truncate(truncate); + self + } + + /// See the underlying [`create`] call for details. + /// + /// [`create`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create + pub fn create(&mut self, create: bool) -> &mut OpenOptions { + self.0.create(create); + self + } + + /// See the underlying [`create_new`] call for details. + /// + /// [`create_new`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new + pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions { + self.0.create_new(create_new); + self + } + + /// Opens a file at `path` with the options specified by `self`. + /// + /// # Errors + /// + /// `OpenOptionsFuture` results in an error if called from outside of the + /// Tokio runtime or if the underlying [`open`] call results in an error. + /// + /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open + pub fn open<P>(&self, path: P) -> OpenFuture<P> + where P: AsRef<Path> + Send + 'static + { + OpenFuture::new(self.0.clone(), path) + } +} + +impl From<StdOpenOptions> for OpenOptions { + fn from(options: StdOpenOptions) -> OpenOptions { + OpenOptions(options) + } +} diff --git a/third_party/rust/tokio-fs/src/file/seek.rs b/third_party/rust/tokio-fs/src/file/seek.rs new file mode 100644 index 0000000000..0765d3db90 --- /dev/null +++ b/third_party/rust/tokio-fs/src/file/seek.rs @@ -0,0 +1,37 @@ +use super::File; + +use futures::{Future, Poll}; + +use std::io; + +/// Future returned by `File::seek`. +#[derive(Debug)] +pub struct SeekFuture { + inner: Option<File>, + pos: io::SeekFrom, +} + +impl SeekFuture { + pub(crate) fn new(file: File, pos: io::SeekFrom) -> Self { + Self { + pos, + inner: Some(file), + } + } +} + +impl Future for SeekFuture { + type Item = (File, u64); + type Error = io::Error; + + fn poll(&mut self) -> Poll<Self::Item, Self::Error> { + let pos = try_ready!( + self.inner + .as_mut() + .expect("Cannot poll `SeekFuture` after it resolves") + .poll_seek(self.pos) + ); + let inner = self.inner.take().unwrap(); + Ok((inner, pos).into()) + } +} |