mirror of
https://github.com/async-rs/async-std.git
synced 2025-01-31 09:45:36 +00:00
Merge pull request #311 from async-rs/missing-write-methods
Add Write::write_fmt
This commit is contained in:
commit
33da049717
3 changed files with 101 additions and 2 deletions
|
@ -1,11 +1,13 @@
|
|||
mod flush;
|
||||
mod write;
|
||||
mod write_all;
|
||||
mod write_fmt;
|
||||
mod write_vectored;
|
||||
|
||||
use flush::FlushFuture;
|
||||
use write::WriteFuture;
|
||||
use write_all::WriteAllFuture;
|
||||
use write_fmt::WriteFmtFuture;
|
||||
use write_vectored::WriteVectoredFuture;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
@ -13,12 +15,12 @@ use cfg_if::cfg_if;
|
|||
use crate::io::IoSlice;
|
||||
use crate::utils::extension_trait;
|
||||
|
||||
use crate::io;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "docs")] {
|
||||
use std::pin::Pin;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::io;
|
||||
use crate::task::{Context, Poll};
|
||||
}
|
||||
}
|
||||
|
@ -197,6 +199,50 @@ extension_trait! {
|
|||
{
|
||||
WriteAllFuture { writer: self, buf }
|
||||
}
|
||||
|
||||
#[doc = r#"
|
||||
Writes a formatted string into this writer, returning any error encountered.
|
||||
|
||||
This method will continuously call [`write`] until there is no more data to be
|
||||
written or an error is returned. This future will not resolve until the entire
|
||||
buffer has been successfully written or such an error occurs.
|
||||
|
||||
[`write`]: #tymethod.write
|
||||
|
||||
# Examples
|
||||
|
||||
```no_run
|
||||
# fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
#
|
||||
use async_std::io::prelude::*;
|
||||
use async_std::fs::File;
|
||||
|
||||
let mut buffer = File::create("foo.txt").await?;
|
||||
|
||||
// this call
|
||||
write!(buffer, "{:.*}", 2, 1.234567).await?;
|
||||
// turns into this:
|
||||
buffer.write_fmt(format_args!("{:.*}", 2, 1.234567)).await?;
|
||||
#
|
||||
# Ok(()) }) }
|
||||
```
|
||||
"#]
|
||||
fn write_fmt<'a>(
|
||||
&'a mut self,
|
||||
fmt: std::fmt::Arguments<'_>,
|
||||
) -> impl Future<Output = io::Result<()>> + 'a [WriteFmtFuture<'a, Self>]
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
// In order to not have to implement an async version of `fmt` including private types
|
||||
// and all, we convert `Arguments` to a `Result<Vec<u8>>` and pass that to the Future.
|
||||
// Doing an owned conversion saves us from juggling references.
|
||||
let mut string = String::new();
|
||||
let res = std::fmt::write(&mut string, fmt)
|
||||
.map(|_| string.into_bytes())
|
||||
.map_err(|_| io::Error::new(io::ErrorKind::Other, "formatter error"));
|
||||
WriteFmtFuture { writer: self, res: Some(res), buffer: None, amt: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write + Unpin + ?Sized> Write for Box<T> {
|
||||
|
|
50
src/io/write/write_fmt.rs
Normal file
50
src/io/write/write_fmt.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use std::pin::Pin;
|
||||
|
||||
use crate::future::Future;
|
||||
use crate::io::{self, Write};
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct WriteFmtFuture<'a, T: Unpin + ?Sized> {
|
||||
pub(crate) writer: &'a mut T,
|
||||
pub(crate) res: Option<io::Result<Vec<u8>>>,
|
||||
pub(crate) buffer: Option<Vec<u8>>,
|
||||
pub(crate) amt: u64,
|
||||
}
|
||||
|
||||
impl<T: Write + Unpin + ?Sized> Future for WriteFmtFuture<'_, T> {
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// Process the interal Result the first time we run.
|
||||
if self.buffer.is_none() {
|
||||
match self.res.take().unwrap() {
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
Ok(buffer) => self.buffer = Some(buffer),
|
||||
};
|
||||
}
|
||||
|
||||
// Get the types from the future.
|
||||
let Self {
|
||||
writer,
|
||||
amt,
|
||||
buffer,
|
||||
..
|
||||
} = &mut *self;
|
||||
let mut buffer = buffer.as_mut().unwrap();
|
||||
|
||||
// Copy the data from the buffer into the writer until it's done.
|
||||
loop {
|
||||
if buffer.is_empty() {
|
||||
futures_core::ready!(Pin::new(&mut **writer).poll_flush(cx))?;
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
let i = futures_core::ready!(Pin::new(&mut **writer).poll_write(cx, &mut buffer))?;
|
||||
if i == 0 {
|
||||
return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
|
||||
}
|
||||
*amt += i as u64;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,3 +77,6 @@ cfg_if! {
|
|||
}
|
||||
|
||||
pub(crate) mod utils;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use std::{write, writeln};
|
||||
|
|
Loading…
Reference in a new issue