tokio_io/io/read_to_end.rs
1use std::io;
2use std::mem;
3
4use futures::{Future, Poll};
5
6use AsyncRead;
7
8/// A future which can be used to easily read the entire contents of a stream
9/// into a vector.
10///
11/// Created by the [`read_to_end`] function.
12///
13/// [`read_to_end`]: fn.read_to_end.html
14#[derive(Debug)]
15pub struct ReadToEnd<A> {
16 state: State<A>,
17}
18
19#[derive(Debug)]
20enum State<A> {
21 Reading { a: A, buf: Vec<u8> },
22 Empty,
23}
24
25/// Creates a future which will read all the bytes associated with the I/O
26/// object `A` into the buffer provided.
27///
28/// In the case of an error the buffer and the object will be discarded, with
29/// the error yielded. In the case of success both the object and the buffer
30/// will be returned, with all data read from the stream appended to the buffer.
31pub fn read_to_end<A>(a: A, buf: Vec<u8>) -> ReadToEnd<A>
32where
33 A: AsyncRead,
34{
35 ReadToEnd {
36 state: State::Reading { a: a, buf: buf },
37 }
38}
39
40impl<A> Future for ReadToEnd<A>
41where
42 A: AsyncRead,
43{
44 type Item = (A, Vec<u8>);
45 type Error = io::Error;
46
47 fn poll(&mut self) -> Poll<(A, Vec<u8>), io::Error> {
48 match self.state {
49 State::Reading {
50 ref mut a,
51 ref mut buf,
52 } => {
53 // If we get `Ok`, then we know the stream hit EOF and we're done. If we
54 // hit "would block" then all the read data so far is in our buffer, and
55 // otherwise we propagate errors
56 try_nb!(a.read_to_end(buf));
57 }
58 State::Empty => panic!("poll ReadToEnd after it's done"),
59 }
60
61 match mem::replace(&mut self.state, State::Empty) {
62 State::Reading { a, buf } => Ok((a, buf).into()),
63 State::Empty => unreachable!(),
64 }
65 }
66}