1 mod maybe_pending {
2     use futures::io::AsyncWrite;
3     use futures::task::{Context, Poll};
4     use std::io;
5     use std::pin::Pin;
6 
7     pub struct MaybePending {
8         pub inner: Vec<u8>,
9         ready: bool,
10     }
11 
12     impl MaybePending {
new(inner: Vec<u8>) -> Self13         pub fn new(inner: Vec<u8>) -> Self {
14             Self { inner, ready: false }
15         }
16     }
17 
18     impl AsyncWrite for MaybePending {
poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>19         fn poll_write(
20             mut self: Pin<&mut Self>,
21             cx: &mut Context<'_>,
22             buf: &[u8],
23         ) -> Poll<io::Result<usize>> {
24             if self.ready {
25                 self.ready = false;
26                 Pin::new(&mut self.inner).poll_write(cx, buf)
27             } else {
28                 self.ready = true;
29                 Poll::Pending
30             }
31         }
32 
poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>33         fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
34             Pin::new(&mut self.inner).poll_flush(cx)
35         }
36 
poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>37         fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
38             Pin::new(&mut self.inner).poll_close(cx)
39         }
40     }
41 }
42 
43 mod util {
44     use futures::future::Future;
45 
run<F: Future + Unpin>(mut f: F) -> F::Output46     pub fn run<F: Future + Unpin>(mut f: F) -> F::Output {
47         use futures::future::FutureExt;
48         use futures::task::Poll;
49         use futures_test::task::noop_context;
50 
51         let mut cx = noop_context();
52         loop {
53             if let Poll::Ready(x) = f.poll_unpin(&mut cx) {
54                 return x;
55             }
56         }
57     }
58 }
59 
60 #[test]
buf_writer()61 fn buf_writer() {
62     use futures::executor::block_on;
63     use futures::io::{AsyncWriteExt, BufWriter};
64 
65     let mut writer = BufWriter::with_capacity(2, Vec::new());
66 
67     block_on(writer.write(&[0, 1])).unwrap();
68     assert_eq!(writer.buffer(), []);
69     assert_eq!(*writer.get_ref(), [0, 1]);
70 
71     block_on(writer.write(&[2])).unwrap();
72     assert_eq!(writer.buffer(), [2]);
73     assert_eq!(*writer.get_ref(), [0, 1]);
74 
75     block_on(writer.write(&[3])).unwrap();
76     assert_eq!(writer.buffer(), [2, 3]);
77     assert_eq!(*writer.get_ref(), [0, 1]);
78 
79     block_on(writer.flush()).unwrap();
80     assert_eq!(writer.buffer(), []);
81     assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
82 
83     block_on(writer.write(&[4])).unwrap();
84     block_on(writer.write(&[5])).unwrap();
85     assert_eq!(writer.buffer(), [4, 5]);
86     assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
87 
88     block_on(writer.write(&[6])).unwrap();
89     assert_eq!(writer.buffer(), [6]);
90     assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]);
91 
92     block_on(writer.write(&[7, 8])).unwrap();
93     assert_eq!(writer.buffer(), []);
94     assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]);
95 
96     block_on(writer.write(&[9, 10, 11])).unwrap();
97     assert_eq!(writer.buffer(), []);
98     assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
99 
100     block_on(writer.flush()).unwrap();
101     assert_eq!(writer.buffer(), []);
102     assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
103 }
104 
105 #[test]
buf_writer_inner_flushes()106 fn buf_writer_inner_flushes() {
107     use futures::executor::block_on;
108     use futures::io::{AsyncWriteExt, BufWriter};
109 
110     let mut w = BufWriter::with_capacity(3, Vec::new());
111     block_on(w.write(&[0, 1])).unwrap();
112     assert_eq!(*w.get_ref(), []);
113     block_on(w.flush()).unwrap();
114     let w = w.into_inner();
115     assert_eq!(w, [0, 1]);
116 }
117 
118 #[test]
buf_writer_seek()119 fn buf_writer_seek() {
120     use futures::executor::block_on;
121     use futures::io::{AsyncSeekExt, AsyncWriteExt, BufWriter, Cursor, SeekFrom};
122 
123     // FIXME: when https://github.com/rust-lang/futures-rs/issues/1510 fixed,
124     // use `Vec::new` instead of `vec![0; 8]`.
125     let mut w = BufWriter::with_capacity(3, Cursor::new(vec![0; 8]));
126     block_on(w.write_all(&[0, 1, 2, 3, 4, 5])).unwrap();
127     block_on(w.write_all(&[6, 7])).unwrap();
128     assert_eq!(block_on(w.seek(SeekFrom::Current(0))).ok(), Some(8));
129     assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]);
130     assert_eq!(block_on(w.seek(SeekFrom::Start(2))).ok(), Some(2));
131     block_on(w.write_all(&[8, 9])).unwrap();
132     block_on(w.flush()).unwrap();
133     assert_eq!(&w.into_inner().into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]);
134 }
135 
136 #[test]
maybe_pending_buf_writer()137 fn maybe_pending_buf_writer() {
138     use futures::io::{AsyncWriteExt, BufWriter};
139 
140     use maybe_pending::MaybePending;
141     use util::run;
142 
143     let mut writer = BufWriter::with_capacity(2, MaybePending::new(Vec::new()));
144 
145     run(writer.write(&[0, 1])).unwrap();
146     assert_eq!(writer.buffer(), []);
147     assert_eq!(&writer.get_ref().inner, &[0, 1]);
148 
149     run(writer.write(&[2])).unwrap();
150     assert_eq!(writer.buffer(), [2]);
151     assert_eq!(&writer.get_ref().inner, &[0, 1]);
152 
153     run(writer.write(&[3])).unwrap();
154     assert_eq!(writer.buffer(), [2, 3]);
155     assert_eq!(&writer.get_ref().inner, &[0, 1]);
156 
157     run(writer.flush()).unwrap();
158     assert_eq!(writer.buffer(), []);
159     assert_eq!(&writer.get_ref().inner, &[0, 1, 2, 3]);
160 
161     run(writer.write(&[4])).unwrap();
162     run(writer.write(&[5])).unwrap();
163     assert_eq!(writer.buffer(), [4, 5]);
164     assert_eq!(&writer.get_ref().inner, &[0, 1, 2, 3]);
165 
166     run(writer.write(&[6])).unwrap();
167     assert_eq!(writer.buffer(), [6]);
168     assert_eq!(writer.get_ref().inner, &[0, 1, 2, 3, 4, 5]);
169 
170     run(writer.write(&[7, 8])).unwrap();
171     assert_eq!(writer.buffer(), []);
172     assert_eq!(writer.get_ref().inner, &[0, 1, 2, 3, 4, 5, 6, 7, 8]);
173 
174     run(writer.write(&[9, 10, 11])).unwrap();
175     assert_eq!(writer.buffer(), []);
176     assert_eq!(writer.get_ref().inner, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
177 
178     run(writer.flush()).unwrap();
179     assert_eq!(writer.buffer(), []);
180     assert_eq!(&writer.get_ref().inner, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
181 }
182 
183 #[test]
maybe_pending_buf_writer_inner_flushes()184 fn maybe_pending_buf_writer_inner_flushes() {
185     use futures::io::{AsyncWriteExt, BufWriter};
186 
187     use maybe_pending::MaybePending;
188     use util::run;
189 
190     let mut w = BufWriter::with_capacity(3, MaybePending::new(Vec::new()));
191     run(w.write(&[0, 1])).unwrap();
192     assert_eq!(&w.get_ref().inner, &[]);
193     run(w.flush()).unwrap();
194     let w = w.into_inner().inner;
195     assert_eq!(w, [0, 1]);
196 }
197 
198 #[test]
maybe_pending_buf_writer_seek()199 fn maybe_pending_buf_writer_seek() {
200     use futures::io::{AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt, BufWriter, Cursor, SeekFrom};
201     use futures::task::{Context, Poll};
202     use std::io;
203     use std::pin::Pin;
204 
205     use util::run;
206 
207     struct MaybePendingSeek {
208         inner: Cursor<Vec<u8>>,
209         ready_write: bool,
210         ready_seek: bool,
211     }
212 
213     impl MaybePendingSeek {
214         fn new(inner: Vec<u8>) -> Self {
215             Self { inner: Cursor::new(inner), ready_write: false, ready_seek: false }
216         }
217     }
218 
219     impl AsyncWrite for MaybePendingSeek {
220         fn poll_write(
221             mut self: Pin<&mut Self>,
222             cx: &mut Context<'_>,
223             buf: &[u8],
224         ) -> Poll<io::Result<usize>> {
225             if self.ready_write {
226                 self.ready_write = false;
227                 Pin::new(&mut self.inner).poll_write(cx, buf)
228             } else {
229                 self.ready_write = true;
230                 Poll::Pending
231             }
232         }
233 
234         fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
235             Pin::new(&mut self.inner).poll_flush(cx)
236         }
237 
238         fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
239             Pin::new(&mut self.inner).poll_close(cx)
240         }
241     }
242 
243     impl AsyncSeek for MaybePendingSeek {
244         fn poll_seek(mut self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom)
245             -> Poll<io::Result<u64>>
246         {
247             if self.ready_seek {
248                 self.ready_seek = false;
249                 Pin::new(&mut self.inner).poll_seek(cx, pos)
250             } else {
251                 self.ready_seek = true;
252                 Poll::Pending
253             }
254         }
255     }
256 
257     // FIXME: when https://github.com/rust-lang/futures-rs/issues/1510 fixed,
258     // use `Vec::new` instead of `vec![0; 8]`.
259     let mut w = BufWriter::with_capacity(3, MaybePendingSeek::new(vec![0; 8]));
260     run(w.write_all(&[0, 1, 2, 3, 4, 5])).unwrap();
261     run(w.write_all(&[6, 7])).unwrap();
262     assert_eq!(run(w.seek(SeekFrom::Current(0))).ok(), Some(8));
263     assert_eq!(&w.get_ref().inner.get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]);
264     assert_eq!(run(w.seek(SeekFrom::Start(2))).ok(), Some(2));
265     run(w.write_all(&[8, 9])).unwrap();
266     run(w.flush()).unwrap();
267     assert_eq!(&w.into_inner().inner.into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]);
268 }
269