From b95bd6c1fe6403db3becb776bf0613577980c97c Mon Sep 17 00:00:00 2001 From: k-nasa Date: Thu, 5 Mar 2020 09:22:00 +0900 Subject: [PATCH] fix: Remove unnecessary io modules --- src/io/copy.rs | 10 +- src/io/mod.rs | 74 ++----------- src/io/stderr.rs | 251 ------------------------------------------ src/io/stdin.rs | 269 ---------------------------------------------- src/io/stdio.rs | 21 ---- src/io/stdout.rs | 251 ------------------------------------------ src/io/timeout.rs | 4 +- 7 files changed, 18 insertions(+), 862 deletions(-) delete mode 100644 src/io/stderr.rs delete mode 100644 src/io/stdin.rs delete mode 100644 src/io/stdio.rs delete mode 100644 src/io/stdout.rs diff --git a/src/io/copy.rs b/src/io/copy.rs index f05ed0e..f946c8b 100644 --- a/src/io/copy.rs +++ b/src/io/copy.rs @@ -32,13 +32,14 @@ use crate::utils::Context as _; /// /// # Examples /// -/// ``` +/// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; +/// use async_std::fs::File; /// /// let mut reader: &[u8] = b"hello"; -/// let mut writer = io::stdout(); +/// let mut writer = File::open("foo.txt").await?; /// /// io::copy(&mut reader, &mut writer).await?; /// # @@ -119,13 +120,14 @@ where /// /// # Examples /// -/// ``` +/// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// # /// use async_std::io; +/// use async_std::fs::File; /// /// let mut reader: &[u8] = b"hello"; -/// let mut writer = io::stdout(); +/// let mut writer = File::open("foo.txt").await?; /// /// io::copy(&mut reader, &mut writer).await?; /// # diff --git a/src/io/mod.rs b/src/io/mod.rs index c7c970c..65c204c 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -122,56 +122,6 @@ //! # Ok(()) }) } //! ``` //! -//! ## Standard input and output -//! -//! A very common source of input is standard input: -//! -//! ```no_run -//! use async_std::io; -//! -//! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -//! # -//! let mut input = String::new(); -//! -//! io::stdin().read_line(&mut input).await?; -//! -//! println!("You typed: {}", input.trim()); -//! # -//! # Ok(()) }) } -//! ``` -//! -//! Note that you cannot use the [`?` operator] in functions that do not return -//! a [`Result`][`Result`]. Instead, you can call [`.unwrap()`] -//! or `match` on the return value to catch any possible errors: -//! -//! ```no_run -//! use async_std::io; -//! -//! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -//! # -//! let mut input = String::new(); -//! -//! io::stdin().read_line(&mut input).await.unwrap(); -//! # -//! # Ok(()) }) } -//! ``` -//! -//! And a very common source of output is standard output: -//! -//! ```no_run -//! use async_std::io; -//! use async_std::io::prelude::*; -//! -//! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -//! # -//! io::stdout().write(&[42]).await?; -//! # -//! # Ok(()) }) } -//! ``` -//! -//! Of course, using [`io::stdout`] directly is less common than something like -//! [`println!`]. -//! //! ## Iterator types //! //! A large number of the structures provided by `std::io` are for various @@ -204,10 +154,14 @@ //! //! ```no_run //! use async_std::io; +//! use async_std::fs::File; //! //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { //! # -//! io::copy(&mut io::stdin(), &mut io::stdout()).await?; +//! let mut reader: &[u8] = b"hello"; +//! let mut writer = File::open("foo.txt").await?; +//! +//! io::copy(&mut reader, &mut writer).await?; //! # //! # Ok(()) }) } //! ``` @@ -224,13 +178,14 @@ //! ``` //! #![allow(dead_code)] //! use async_std::io; +//! use std::time::Duration; //! //! async fn read_input() -> io::Result<()> { -//! let mut input = String::new(); -//! -//! io::stdin().read_line(&mut input).await?; +//! let f = io::timeout(Duration::from_secs(5), async { +//! Ok(()) +//! }); //! -//! println!("You typed: {}", input.trim()); +//! assert_eq!(f.await?, ()); //! //! Ok(()) //! } @@ -260,8 +215,6 @@ //! [`BufReader`]: struct.BufReader.html //! [`BufWriter`]: struct.BufWriter.html //! [`Write::write`]: trait.Write.html#tymethod.write -//! [`io::stdout`]: fn.stdout.html -//! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html //! [`?` operator]: https://doc.rust-lang.org/stable/book/appendix-02-operators.html @@ -305,14 +258,7 @@ cfg_std! { } cfg_default! { - pub use stderr::{stderr, Stderr, StderrLock}; - pub use stdin::{stdin, Stdin, StdinLock}; - pub use stdout::{stdout, Stdout, StdoutLock}; pub use timeout::timeout; mod timeout; - mod stderr; - mod stdin; - mod stdio; - mod stdout; } diff --git a/src/io/stderr.rs b/src/io/stderr.rs deleted file mode 100644 index fc5f4a0..0000000 --- a/src/io/stderr.rs +++ /dev/null @@ -1,251 +0,0 @@ -use std::pin::Pin; -use std::sync::Mutex; -use std::future::Future; -use std::io::Write as _; - -use crate::io::{self, Write}; -use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; - -use once_cell::sync::Lazy; - -/// Constructs a new handle to the standard error of the current process. -/// -/// This function is an async version of [`std::io::stderr`]. -/// -/// [`std::io::stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Examples -/// -/// ```no_run -/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -/// # -/// use async_std::io; -/// use async_std::prelude::*; -/// -/// let mut stderr = io::stderr(); -/// stderr.write_all(b"Hello, world!").await?; -/// # -/// # Ok(()) }) } -/// ``` -pub fn stderr() -> Stderr { - Stderr(Mutex::new(State::Idle(Some(Inner { - stderr: std::io::stderr(), - buf: Vec::new(), - last_op: None, - })))) -} - -/// A handle to the standard error of the current process. -/// -/// This writer is created by the [`stderr`] function. See its documentation for -/// more. -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// [`stderr`]: fn.stderr.html -#[derive(Debug)] -pub struct Stderr(Mutex); - -/// A locked reference to the Stderr handle. -/// -/// This handle implements the [`Write`] traits, and is constructed via the [`Stderr::lock`] -/// method. -/// -/// [`Write`]: trait.Read.html -/// [`Stderr::lock`]: struct.Stderr.html#method.lock -#[derive(Debug)] -pub struct StderrLock<'a>(std::io::StderrLock<'a>); - -unsafe impl Send for StderrLock<'_> {} - -/// The state of the asynchronous stderr. -/// -/// The stderr can be either idle or busy performing an asynchronous operation. -#[derive(Debug)] -enum State { - /// The stderr is idle. - Idle(Option), - - /// The stderr is blocked on an asynchronous operation. - /// - /// Awaiting this operation will result in the new state of the stderr. - Busy(JoinHandle), -} - -/// Inner representation of the asynchronous stderr. -#[derive(Debug)] -struct Inner { - /// The blocking stderr handle. - stderr: std::io::Stderr, - - /// The write buffer. - buf: Vec, - - /// The result of the last asynchronous operation on the stderr. - last_op: Option, -} - -/// Possible results of an asynchronous operation on the stderr. -#[derive(Debug)] -enum Operation { - Write(io::Result), - Flush(io::Result<()>), -} - -impl Stderr { - /// Locks this handle to the standard error stream, returning a writable guard. - /// - /// The lock is released when the returned lock goes out of scope. The returned guard also implements the Write trait for writing data. - /// - /// # Examples - /// - /// ```no_run - /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { - /// # - /// use async_std::io; - /// use async_std::prelude::*; - /// - /// let stderr = io::stderr(); - /// let mut handle = stderr.lock().await; - /// - /// handle.write_all(b"hello world").await?; - /// # - /// # Ok(()) }) } - /// ``` - pub async fn lock(&self) -> StderrLock<'static> { - static STDERR: Lazy = Lazy::new(std::io::stderr); - - spawn_blocking(move || StderrLock(STDERR.lock())).await - } -} - -impl Write for Stderr { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::Write(res)) = inner.last_op.take() { - let n = res?; - - // If more data was written than is available in the buffer, let's retry - // the write operation. - if n <= buf.len() { - return Poll::Ready(Ok(n)); - } - } else { - let mut inner = opt.take().unwrap(); - - // Set the length of the inner buffer to the length of the provided buffer. - if inner.buf.len() < buf.len() { - inner.buf.reserve(buf.len() - inner.buf.len()); - } - unsafe { - inner.buf.set_len(buf.len()); - } - - // Copy the data to write into the inner buffer. - inner.buf[..buf.len()].copy_from_slice(buf); - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - let res = std::io::Write::write(&mut inner.stderr, &inner.buf); - inner.last_op = Some(Operation::Write(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stderr is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::Flush(res)) = inner.last_op.take() { - return Poll::Ready(res); - } else { - let mut inner = opt.take().unwrap(); - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - let res = std::io::Write::flush(&mut inner.stderr); - inner.last_op = Some(Operation::Flush(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stderr is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_flush(cx) - } -} - -cfg_unix! { - use crate::os::unix::io::{AsRawFd, RawFd}; - - impl AsRawFd for Stderr { - fn as_raw_fd(&self) -> RawFd { - std::io::stderr().as_raw_fd() - } - } -} - -cfg_windows! { - use crate::os::windows::io::{AsRawHandle, RawHandle}; - - impl AsRawHandle for Stderr { - fn as_raw_handle(&self) -> RawHandle { - std::io::stderr().as_raw_handle() - } - } -} - -impl io::Write for StderrLock<'_> { - fn poll_write( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - Poll::Ready(self.0.write(buf)) - } - - fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - Poll::Ready(self.0.flush()) - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_flush(cx) - } -} diff --git a/src/io/stdin.rs b/src/io/stdin.rs deleted file mode 100644 index b299d09..0000000 --- a/src/io/stdin.rs +++ /dev/null @@ -1,269 +0,0 @@ -use std::future::Future; -use std::pin::Pin; -use std::sync::Mutex; -use std::io::Read as _; - -use crate::future; -use crate::io::{self, Read}; -use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; -use crate::utils::Context as _; - -use once_cell::sync::Lazy; - -/// Constructs a new handle to the standard input of the current process. -/// -/// This function is an async version of [`std::io::stdin`]. -/// -/// [`std::io::stdin`]: https://doc.rust-lang.org/std/io/fn.stdin.html -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Examples -/// -/// ```no_run -/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -/// # -/// use async_std::io; -/// -/// let stdin = io::stdin(); -/// let mut line = String::new(); -/// stdin.read_line(&mut line).await?; -/// # -/// # Ok(()) }) } -/// ``` -pub fn stdin() -> Stdin { - Stdin(Mutex::new(State::Idle(Some(Inner { - stdin: std::io::stdin(), - line: String::new(), - buf: Vec::new(), - last_op: None, - })))) -} - -/// A handle to the standard input of the current process. -/// -/// This reader is created by the [`stdin`] function. See its documentation for -/// more. -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// [`stdin`]: fn.stdin.html -#[derive(Debug)] -pub struct Stdin(Mutex); - -/// A locked reference to the Stdin handle. -/// -/// This handle implements the [`Read`] traits, and is constructed via the [`Stdin::lock`] method. -/// -/// [`Read`]: trait.Read.html -/// [`Stdin::lock`]: struct.Stdin.html#method.lock -#[derive(Debug)] -pub struct StdinLock<'a>(std::io::StdinLock<'a>); - -unsafe impl Send for StdinLock<'_> {} - -/// The state of the asynchronous stdin. -/// -/// The stdin can be either idle or busy performing an asynchronous operation. -#[derive(Debug)] -enum State { - /// The stdin is idle. - Idle(Option), - - /// The stdin is blocked on an asynchronous operation. - /// - /// Awaiting this operation will result in the new state of the stdin. - Busy(JoinHandle), -} - -/// Inner representation of the asynchronous stdin. -#[derive(Debug)] -struct Inner { - /// The blocking stdin handle. - stdin: std::io::Stdin, - - /// The line buffer. - line: String, - - /// The write buffer. - buf: Vec, - - /// The result of the last asynchronous operation on the stdin. - last_op: Option, -} - -/// Possible results of an asynchronous operation on the stdin. -#[derive(Debug)] -enum Operation { - ReadLine(io::Result), - Read(io::Result), -} - -impl Stdin { - /// Reads a line of input into the specified buffer. - /// - /// # Examples - /// - /// ```no_run - /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { - /// # - /// use async_std::io; - /// - /// let stdin = io::stdin(); - /// let mut line = String::new(); - /// stdin.read_line(&mut line).await?; - /// # - /// # Ok(()) }) } - /// ``` - pub async fn read_line(&self, buf: &mut String) -> io::Result { - future::poll_fn(|cx| { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::ReadLine(res)) = inner.last_op.take() { - let n = res?; - - // Copy the read data into the buffer and return. - buf.push_str(&inner.line); - return Poll::Ready(Ok(n)); - } else { - let mut inner = opt.take().unwrap(); - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - inner.line.clear(); - let res = inner.stdin.read_line(&mut inner.line); - inner.last_op = Some(Operation::ReadLine(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stdin is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - }) - .await - .context(|| String::from("could not read line on stdin")) - } - - /// Locks this handle to the standard input stream, returning a readable guard. - /// - /// The lock is released when the returned lock goes out of scope. The returned guard also implements the Read trait for accessing the underlying data. - /// - /// # Examples - /// - /// ```no_run - /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { - /// # - /// use async_std::io; - /// use async_std::prelude::*; - /// - /// let mut buffer = String::new(); - /// - /// let stdin = io::stdin(); - /// let mut handle = stdin.lock().await; - /// - /// handle.read_to_string(&mut buffer).await?; - /// # - /// # Ok(()) }) } - /// ``` - pub async fn lock(&self) -> StdinLock<'static> { - static STDIN: Lazy = Lazy::new(std::io::stdin); - - spawn_blocking(move || StdinLock(STDIN.lock())).await - } -} - -impl Read for Stdin { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::Read(res)) = inner.last_op.take() { - let n = res?; - - // If more data was read than fits into the buffer, let's retry the read - // operation. - if n <= buf.len() { - // Copy the read data into the buffer and return. - buf[..n].copy_from_slice(&inner.buf[..n]); - return Poll::Ready(Ok(n)); - } - } else { - let mut inner = opt.take().unwrap(); - - // Set the length of the inner buffer to the length of the provided buffer. - if inner.buf.len() < buf.len() { - inner.buf.reserve(buf.len() - inner.buf.len()); - } - unsafe { - inner.buf.set_len(buf.len()); - } - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - let res = std::io::Read::read(&mut inner.stdin, &mut inner.buf); - inner.last_op = Some(Operation::Read(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stdin is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - } -} - -cfg_unix! { - use crate::os::unix::io::{AsRawFd, RawFd}; - - impl AsRawFd for Stdin { - fn as_raw_fd(&self) -> RawFd { - std::io::stdin().as_raw_fd() - } - } -} - -cfg_windows! { - use crate::os::windows::io::{AsRawHandle, RawHandle}; - - impl AsRawHandle for Stdin { - fn as_raw_handle(&self) -> RawHandle { - std::io::stdin().as_raw_handle() - } - } -} - -impl Read for StdinLock<'_> { - fn poll_read( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - Poll::Ready(self.0.read(buf)) - } -} diff --git a/src/io/stdio.rs b/src/io/stdio.rs deleted file mode 100644 index 0e11e1a..0000000 --- a/src/io/stdio.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! Internal types for stdio. -//! -//! This module is a port of `libstd/io/stdio.rs`,and contains internal types for `print`/`eprint`. - -use crate::io::{stderr, stdout}; -use crate::prelude::*; -use std::fmt; - -#[doc(hidden)] -pub async fn _print(args: fmt::Arguments<'_>) { - if let Err(e) = stdout().write_fmt(args).await { - panic!("failed printing to stdout: {}", e); - } -} - -#[doc(hidden)] -pub async fn _eprint(args: fmt::Arguments<'_>) { - if let Err(e) = stderr().write_fmt(args).await { - panic!("failed printing to stderr: {}", e); - } -} diff --git a/src/io/stdout.rs b/src/io/stdout.rs deleted file mode 100644 index d98ef13..0000000 --- a/src/io/stdout.rs +++ /dev/null @@ -1,251 +0,0 @@ -use std::pin::Pin; -use std::sync::Mutex; -use std::future::Future; -use std::io::Write as _; - -use crate::io::{self, Write}; -use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; - -use once_cell::sync::Lazy; - -/// Constructs a new handle to the standard output of the current process. -/// -/// This function is an async version of [`std::io::stdout`]. -/// -/// [`std::io::stdout`]: https://doc.rust-lang.org/std/io/fn.stdout.html -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Examples -/// -/// ```no_run -/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { -/// # -/// use async_std::io; -/// use async_std::prelude::*; -/// -/// let mut stdout = io::stdout(); -/// stdout.write_all(b"Hello, world!").await?; -/// # -/// # Ok(()) }) } -/// ``` -pub fn stdout() -> Stdout { - Stdout(Mutex::new(State::Idle(Some(Inner { - stdout: std::io::stdout(), - buf: Vec::new(), - last_op: None, - })))) -} - -/// A handle to the standard output of the current process. -/// -/// This writer is created by the [`stdout`] function. See its documentation -/// for more. -/// -/// ### Note: Windows Portability Consideration -/// -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// [`stdout`]: fn.stdout.html -#[derive(Debug)] -pub struct Stdout(Mutex); - -/// A locked reference to the Stderr handle. -/// -/// This handle implements the [`Write`] traits, and is constructed via the [`Stdout::lock`] -/// method. -/// -/// [`Write`]: trait.Read.html -/// [`Stdout::lock`]: struct.Stdout.html#method.lock -#[derive(Debug)] -pub struct StdoutLock<'a>(std::io::StdoutLock<'a>); - -unsafe impl Send for StdoutLock<'_> {} - -/// The state of the asynchronous stdout. -/// -/// The stdout can be either idle or busy performing an asynchronous operation. -#[derive(Debug)] -enum State { - /// The stdout is idle. - Idle(Option), - - /// The stdout is blocked on an asynchronous operation. - /// - /// Awaiting this operation will result in the new state of the stdout. - Busy(JoinHandle), -} - -/// Inner representation of the asynchronous stdout. -#[derive(Debug)] -struct Inner { - /// The blocking stdout handle. - stdout: std::io::Stdout, - - /// The write buffer. - buf: Vec, - - /// The result of the last asynchronous operation on the stdout. - last_op: Option, -} - -/// Possible results of an asynchronous operation on the stdout. -#[derive(Debug)] -enum Operation { - Write(io::Result), - Flush(io::Result<()>), -} - -impl Stdout { - /// Locks this handle to the standard error stream, returning a writable guard. - /// - /// The lock is released when the returned lock goes out of scope. The returned guard also implements the Write trait for writing data. - /// - /// # Examples - /// - /// ```no_run - /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { - /// # - /// use async_std::io; - /// use async_std::prelude::*; - /// - /// let stdout = io::stdout(); - /// let mut handle = stdout.lock().await; - /// - /// handle.write_all(b"hello world").await?; - /// # - /// # Ok(()) }) } - /// ``` - pub async fn lock(&self) -> StdoutLock<'static> { - static STDOUT: Lazy = Lazy::new(std::io::stdout); - - spawn_blocking(move || StdoutLock(STDOUT.lock())).await - } -} - -impl Write for Stdout { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::Write(res)) = inner.last_op.take() { - let n = res?; - - // If more data was written than is available in the buffer, let's retry - // the write operation. - if n <= buf.len() { - return Poll::Ready(Ok(n)); - } - } else { - let mut inner = opt.take().unwrap(); - - // Set the length of the inner buffer to the length of the provided buffer. - if inner.buf.len() < buf.len() { - inner.buf.reserve(buf.len() - inner.buf.len()); - } - unsafe { - inner.buf.set_len(buf.len()); - } - - // Copy the data to write into the inner buffer. - inner.buf[..buf.len()].copy_from_slice(buf); - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - let res = std::io::Write::write(&mut inner.stdout, &inner.buf); - inner.last_op = Some(Operation::Write(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stdout is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let state = &mut *self.0.lock().unwrap(); - - loop { - match state { - State::Idle(opt) => { - let inner = opt.as_mut().unwrap(); - - // Check if the operation has completed. - if let Some(Operation::Flush(res)) = inner.last_op.take() { - return Poll::Ready(res); - } else { - let mut inner = opt.take().unwrap(); - - // Start the operation asynchronously. - *state = State::Busy(spawn_blocking(move || { - let res = std::io::Write::flush(&mut inner.stdout); - inner.last_op = Some(Operation::Flush(res)); - State::Idle(Some(inner)) - })); - } - } - // Poll the asynchronous operation the stdout is currently blocked on. - State::Busy(task) => *state = futures_core::ready!(Pin::new(task).poll(cx)), - } - } - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_flush(cx) - } -} - -cfg_unix! { - use crate::os::unix::io::{AsRawFd, RawFd}; - - impl AsRawFd for Stdout { - fn as_raw_fd(&self) -> RawFd { - std::io::stdout().as_raw_fd() - } - } -} - -cfg_windows! { - use crate::os::windows::io::{AsRawHandle, RawHandle}; - - impl AsRawHandle for Stdout { - fn as_raw_handle(&self) -> RawHandle { - std::io::stdout().as_raw_handle() - } - } -} - -impl Write for StdoutLock<'_> { - fn poll_write( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - Poll::Ready(self.0.write(buf)) - } - - fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - Poll::Ready(self.0.flush()) - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.poll_flush(cx) - } -} diff --git a/src/io/timeout.rs b/src/io/timeout.rs index 6e22dbf..3627439 100644 --- a/src/io/timeout.rs +++ b/src/io/timeout.rs @@ -23,9 +23,9 @@ use crate::io; /// use async_std::io; /// /// io::timeout(Duration::from_secs(5), async { -/// let stdin = io::stdin(); +/// let stdin = std::io::stdin(); /// let mut line = String::new(); -/// let n = stdin.read_line(&mut line).await?; +/// let n = stdin.read_line(&mut line)?; /// Ok(()) /// }) /// .await?;