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}