Skip to content

Commit e5f2221

Browse files
Nemo157cramertj
authored andcommitted
Add LimitedWrite test adaptor for AsyncWrite
1 parent 806f228 commit e5f2221

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use futures_io::{self as io, AsyncWrite};
2+
use pin_utils::{unsafe_pinned, unsafe_unpinned};
3+
use std::{
4+
cmp,
5+
marker::Unpin,
6+
pin::Pin,
7+
task::{Context, Poll},
8+
};
9+
10+
/// Writer for the [`limited_write`](super::AsyncWriteTestExt::limited_write) method.
11+
#[derive(Debug)]
12+
pub struct LimitedWrite<W: AsyncWrite> {
13+
writer: W,
14+
limit: usize,
15+
}
16+
17+
impl<W: AsyncWrite + Unpin> Unpin for LimitedWrite<W> {}
18+
19+
impl<W: AsyncWrite> LimitedWrite<W> {
20+
unsafe_pinned!(writer: W);
21+
unsafe_unpinned!(limit: usize);
22+
23+
pub(crate) fn new(writer: W, limit: usize) -> LimitedWrite<W> {
24+
LimitedWrite { writer, limit }
25+
}
26+
27+
/// Acquires a reference to the underlying writer that this adaptor is wrapping.
28+
pub fn get_ref(&self) -> &W {
29+
&self.writer
30+
}
31+
32+
/// Acquires a mutable reference to the underlying writer that this adaptor is wrapping.
33+
pub fn get_mut(&mut self) -> &mut W {
34+
&mut self.writer
35+
}
36+
37+
/// Acquires a pinned mutable reference to the underlying writer that this adaptor is wrapping.
38+
pub fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut W> {
39+
self.writer()
40+
}
41+
42+
/// Consumes this adaptor returning the underlying writer.
43+
pub fn into_inner(self) -> W {
44+
self.writer
45+
}
46+
}
47+
48+
impl<W: AsyncWrite> AsyncWrite for LimitedWrite<W> {
49+
fn poll_write(
50+
mut self: Pin<&mut Self>,
51+
cx: &mut Context<'_>,
52+
buf: &[u8],
53+
) -> Poll<io::Result<usize>> {
54+
let limit = *self.as_mut().limit();
55+
self.writer()
56+
.poll_write(cx, &buf[..cmp::min(limit, buf.len())])
57+
}
58+
59+
fn poll_flush(
60+
self: Pin<&mut Self>,
61+
cx: &mut Context<'_>,
62+
) -> Poll<io::Result<()>> {
63+
self.writer().poll_flush(cx)
64+
}
65+
66+
fn poll_close(
67+
self: Pin<&mut Self>,
68+
cx: &mut Context<'_>,
69+
) -> Poll<io::Result<()>> {
70+
self.writer().poll_close(cx)
71+
}
72+
}

futures-test/src/io/write/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use futures_io::AsyncWrite;
55
mod interleave_pending_write;
66
pub use self::interleave_pending_write::InterleavePendingWrite;
77

8+
mod limited_write;
9+
pub use self::limited_write::LimitedWrite;
10+
811
/// Additional combinators for testing async writers.
912
pub trait AsyncWriteTestExt: AsyncWrite {
1013
/// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending)
@@ -48,6 +51,40 @@ pub trait AsyncWriteTestExt: AsyncWrite {
4851
{
4952
InterleavePendingWrite::new(self)
5053
}
54+
55+
/// Limit the number of bytes allowed to be written on each call to `poll_write`.
56+
///
57+
/// # Examples
58+
///
59+
/// ```
60+
/// #![feature(async_await)]
61+
/// use futures::task::Poll;
62+
/// use futures::io::AsyncWrite;
63+
/// use futures_test::task::noop_context;
64+
/// use futures_test::io::AsyncWriteTestExt;
65+
/// use pin_utils::pin_mut;
66+
///
67+
/// let writer = std::io::Cursor::new([0u8; 4]).limited_write(2);
68+
/// pin_mut!(writer);
69+
///
70+
/// let mut cx = noop_context();
71+
///
72+
/// assert_eq!(writer.as_mut().poll_write(&mut cx, &[1, 2])?, Poll::Ready(2));
73+
/// assert_eq!(writer.get_ref().get_ref(), &[1, 2, 0, 0]);
74+
/// assert_eq!(writer.as_mut().poll_write(&mut cx, &[3])?, Poll::Ready(1));
75+
/// assert_eq!(writer.get_ref().get_ref(), &[1, 2, 3, 0]);
76+
/// assert_eq!(writer.as_mut().poll_write(&mut cx, &[4, 5])?, Poll::Ready(1));
77+
/// assert_eq!(writer.get_ref().get_ref(), &[1, 2, 3, 4]);
78+
/// assert_eq!(writer.as_mut().poll_write(&mut cx, &[5])?, Poll::Ready(0));
79+
///
80+
/// # Ok::<(), std::io::Error>(())
81+
/// ```
82+
fn limited_write(self, limit: usize) -> LimitedWrite<Self>
83+
where
84+
Self: Sized,
85+
{
86+
LimitedWrite::new(self, limit)
87+
}
5188
}
5289

5390
impl<W> AsyncWriteTestExt for W where W: AsyncWrite {}

0 commit comments

Comments
 (0)