diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/tokio-fs/src | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/tokio-fs/src')
26 files changed, 1636 insertions, 0 deletions
diff --git a/third_party/rust/tokio-fs/src/create_dir.rs b/third_party/rust/tokio-fs/src/create_dir.rs new file mode 100644 index 0000000000..a174a5d97f --- /dev/null +++ b/third_party/rust/tokio-fs/src/create_dir.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/create_dir_all.rs b/third_party/rust/tokio-fs/src/create_dir_all.rs new file mode 100644 index 0000000000..3e32480673 --- /dev/null +++ b/third_party/rust/tokio-fs/src/create_dir_all.rs @@ -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) ) + } +} 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()) + } +} diff --git a/third_party/rust/tokio-fs/src/hard_link.rs b/third_party/rust/tokio-fs/src/hard_link.rs new file mode 100644 index 0000000000..e8ea511520 --- /dev/null +++ b/third_party/rust/tokio-fs/src/hard_link.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/lib.rs b/third_party/rust/tokio-fs/src/lib.rs new file mode 100644 index 0000000000..2beec8c0c6 --- /dev/null +++ b/third_party/rust/tokio-fs/src/lib.rs @@ -0,0 +1,104 @@ +//! Asynchronous file and standard stream adaptation. +//! +//! This module contains utility methods and adapter types for input/output to +//! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and +//! filesystem manipulation, for use within (and only within) a Tokio runtime. +//! +//! Tasks run by *worker* threads should not block, as this could delay +//! servicing reactor events. Portable filesystem operations are blocking, +//! however. This module offers adapters which use a [`blocking`] annotation +//! to inform the runtime that a blocking operation is required. When +//! necessary, this allows the runtime to convert the current thread from a +//! *worker* to a *backup* thread, where blocking is acceptable. +//! +//! ## Usage +//! +//! Where possible, users should prefer the provided asynchronous-specific +//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll` +//! type. Adaptions also extend to traits like `std::io::Read` where methods +//! return `std::io::Result`. Be warned that these adapted methods may return +//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted +//! to a *backup* thread immediately. See [tokio-threadpool] for more details +//! of the threading model and [`blocking`]. +//! +//! [`blocking`]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool/fn.blocking.html +//! [`AsyncRead`]: https://docs.rs/tokio-io/0.1/tokio_io/trait.AsyncRead.html +//! [tokio-threadpool]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool + +#![deny(missing_docs, missing_debug_implementations, warnings)] +#![doc(html_root_url = "https://docs.rs/tokio-fs/0.1.3")] + +#[macro_use] +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::*; + +use std::io; +use std::io::ErrorKind::{Other, WouldBlock}; + +fn blocking_io<F, T>(f: F) -> Poll<T, io::Error> +where F: FnOnce() -> io::Result<T>, +{ + match tokio_threadpool::blocking(f) { + Ok(Ready(Ok(v))) => Ok(v.into()), + Ok(Ready(Err(err))) => Err(err), + Ok(NotReady) => Ok(NotReady), + Err(_) => Err(blocking_err()), + } +} + +fn would_block<F, T>(f: F) -> io::Result<T> +where F: FnOnce() -> io::Result<T>, +{ + match tokio_threadpool::blocking(f) { + Ok(Ready(Ok(v))) => Ok(v), + Ok(Ready(Err(err))) => { + debug_assert_ne!(err.kind(), WouldBlock); + Err(err) + } + Ok(NotReady) => Err(WouldBlock.into()), + Err(_) => Err(blocking_err()), + } +} + +fn blocking_err() -> io::Error { + io::Error::new(Other, "`blocking` annotated I/O must be called \ + from the context of the Tokio runtime.") +} diff --git a/third_party/rust/tokio-fs/src/metadata.rs b/third_party/rust/tokio-fs/src/metadata.rs new file mode 100644 index 0000000000..200d58e080 --- /dev/null +++ b/third_party/rust/tokio-fs/src/metadata.rs @@ -0,0 +1,45 @@ +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. +pub fn metadata<P>(path: P) -> MetadataFuture<P> +where + P: AsRef<Path> + Send + 'static, +{ + MetadataFuture::new(path) +} + +/// Future returned by `metadata`. +#[derive(Debug)] +pub struct MetadataFuture<P> +where + P: AsRef<Path> + Send + 'static, +{ + path: P, +} + +impl<P> MetadataFuture<P> +where + P: AsRef<Path> + Send + 'static, +{ + pub(crate) fn new(path: P) -> Self { + Self { path } + } +} + +impl<P> Future for MetadataFuture<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::metadata(&self.path)) + } +} diff --git a/third_party/rust/tokio-fs/src/os/mod.rs b/third_party/rust/tokio-fs/src/os/mod.rs new file mode 100644 index 0000000000..ae57c48476 --- /dev/null +++ b/third_party/rust/tokio-fs/src/os/mod.rs @@ -0,0 +1,6 @@ +//! OS-specific functionality. + +#[cfg(unix)] +pub mod unix; +#[cfg(windows)] +pub mod windows; diff --git a/third_party/rust/tokio-fs/src/os/unix.rs b/third_party/rust/tokio-fs/src/os/unix.rs new file mode 100644 index 0000000000..5f8eedeba3 --- /dev/null +++ b/third_party/rust/tokio-fs/src/os/unix.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/os/windows/mod.rs b/third_party/rust/tokio-fs/src/os/windows/mod.rs new file mode 100644 index 0000000000..eaeed043eb --- /dev/null +++ b/third_party/rust/tokio-fs/src/os/windows/mod.rs @@ -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}; diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs new file mode 100644 index 0000000000..9806ff3a3f --- /dev/null +++ b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs new file mode 100644 index 0000000000..583b615874 --- /dev/null +++ b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/read_dir.rs b/third_party/rust/tokio-fs/src/read_dir.rs new file mode 100644 index 0000000000..3818c7102b --- /dev/null +++ b/third_party/rust/tokio-fs/src/read_dir.rs @@ -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() + } +} diff --git a/third_party/rust/tokio-fs/src/read_link.rs b/third_party/rust/tokio-fs/src/read_link.rs new file mode 100644 index 0000000000..5e5bf2a30e --- /dev/null +++ b/third_party/rust/tokio-fs/src/read_link.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/remove_dir.rs b/third_party/rust/tokio-fs/src/remove_dir.rs new file mode 100644 index 0000000000..5aa73bfb5f --- /dev/null +++ b/third_party/rust/tokio-fs/src/remove_dir.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/remove_file.rs b/third_party/rust/tokio-fs/src/remove_file.rs new file mode 100644 index 0000000000..f617418579 --- /dev/null +++ b/third_party/rust/tokio-fs/src/remove_file.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/rename.rs b/third_party/rust/tokio-fs/src/rename.rs new file mode 100644 index 0000000000..210f53bb5a --- /dev/null +++ b/third_party/rust/tokio-fs/src/rename.rs @@ -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) ) + } +} diff --git a/third_party/rust/tokio-fs/src/set_permissions.rs b/third_party/rust/tokio-fs/src/set_permissions.rs new file mode 100644 index 0000000000..a850448626 --- /dev/null +++ b/third_party/rust/tokio-fs/src/set_permissions.rs @@ -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()) ) + } +} diff --git a/third_party/rust/tokio-fs/src/stderr.rs b/third_party/rust/tokio-fs/src/stderr.rs new file mode 100644 index 0000000000..cf64390757 --- /dev/null +++ b/third_party/rust/tokio-fs/src/stderr.rs @@ -0,0 +1,45 @@ +use tokio_io::{AsyncWrite}; + +use futures::Poll; + +use std::io::{self, Write, Stderr as StdStderr}; + +/// A handle to the standard error stream of a process. +/// +/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent +/// writes to `Stderr` must be executed with care. +/// +/// Created by the [`stderr`] function. +/// +/// [`stderr`]: fn.stderr.html +/// [`AsyncWrite`]: trait.AsyncWrite.html +#[derive(Debug)] +pub struct Stderr { + std: StdStderr, +} + +/// Constructs a new handle to the standard error of the current process. +/// +/// The returned handle allows writing to standard error from the within the +/// Tokio runtime. +pub fn stderr() -> Stderr { + let std = io::stderr(); + Stderr { std } +} + +impl Write for Stderr { + 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 Stderr { + fn shutdown(&mut self) -> Poll<(), io::Error> { + Ok(().into()) + } +} + diff --git a/third_party/rust/tokio-fs/src/stdin.rs b/third_party/rust/tokio-fs/src/stdin.rs new file mode 100644 index 0000000000..f41b8dc84c --- /dev/null +++ b/third_party/rust/tokio-fs/src/stdin.rs @@ -0,0 +1,38 @@ +use tokio_io::{AsyncRead}; + +use std::io::{self, Read, Stdin as StdStdin}; + +/// A handle to the standard input stream of a process. +/// +/// The handle implements the [`AsyncRead`] trait, but beware that concurrent +/// reads of `Stdin` must be executed with care. +/// +/// Created by the [`stdin`] function. +/// +/// [`stdin`]: fn.stdin.html +/// [`AsyncRead`]: trait.AsyncRead.html +#[derive(Debug)] +pub struct Stdin { + std: StdStdin, +} + +/// Constructs a new handle to the standard input of the current process. +/// +/// The returned handle allows reading from standard input from the within the +/// Tokio runtime. +pub fn stdin() -> Stdin { + let std = io::stdin(); + Stdin { std } +} + +impl Read for Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + ::would_block(|| self.std.read(buf)) + } +} + +impl AsyncRead for Stdin { + unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { + false + } +} diff --git a/third_party/rust/tokio-fs/src/stdout.rs b/third_party/rust/tokio-fs/src/stdout.rs new file mode 100644 index 0000000000..1c4cd5ad05 --- /dev/null +++ b/third_party/rust/tokio-fs/src/stdout.rs @@ -0,0 +1,44 @@ +use tokio_io::{AsyncWrite}; + +use futures::Poll; + +use std::io::{self, Write, Stdout as StdStdout}; + +/// A handle to the standard output stream of a process. +/// +/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent +/// writes to `Stdout` must be executed with care. +/// +/// Created by the [`stdout`] function. +/// +/// [`stdout`]: fn.stdout.html +/// [`AsyncWrite`]: trait.AsyncWrite.html +#[derive(Debug)] +pub struct Stdout { + std: StdStdout, +} + +/// Constructs a new handle to the standard output of the current process. +/// +/// The returned handle allows writing to standard out from the within the Tokio +/// runtime. +pub fn stdout() -> Stdout { + let std = io::stdout(); + Stdout { std } +} + +impl Write for Stdout { + 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 Stdout { + fn shutdown(&mut self) -> Poll<(), io::Error> { + Ok(().into()) + } +} diff --git a/third_party/rust/tokio-fs/src/symlink_metadata.rs b/third_party/rust/tokio-fs/src/symlink_metadata.rs new file mode 100644 index 0000000000..db02769e20 --- /dev/null +++ b/third_party/rust/tokio-fs/src/symlink_metadata.rs @@ -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)) + } +} |