use std::io::{self, Read}; use std::mem; use futures::{Poll, Future}; /// A future which can be used to easily read the entire contents of a stream /// into a vector. /// /// Created by the `read_exact` function. pub struct ReadExact { state: State, } enum State { Reading { a: A, buf: T, pos: usize, }, Empty, } /// Creates a future which will read exactly enough bytes to fill `buf`, /// returning an error if EOF is hit sooner. /// /// The returned future will resolve to both the I/O stream as well as the /// buffer once the read operation is completed. /// /// In the case of an error the buffer and the object will be discarded, with /// the error yielded. In the case of success the object will be destroyed and /// the buffer will be returned, with all data read from the stream appended to /// the buffer. pub fn read_exact(a: A, buf: T) -> ReadExact where A: Read, T: AsMut<[u8]>, { ReadExact { state: State::Reading { a: a, buf: buf, pos: 0, }, } } fn eof() -> io::Error { io::Error::new(io::ErrorKind::UnexpectedEof, "early eof") } impl Future for ReadExact where A: Read, T: AsMut<[u8]>, { type Item = (A, T); type Error = io::Error; fn poll(&mut self) -> Poll<(A, T), io::Error> { match self.state { State::Reading { ref mut a, ref mut buf, ref mut pos } => { let buf = buf.as_mut(); while *pos < buf.len() { let n = try_nb!(a.read(&mut buf[*pos..])); *pos += n; if n == 0 { return Poll::Err(eof()) } } } State::Empty => panic!("poll a WriteAll after it's done"), } match mem::replace(&mut self.state, State::Empty) { State::Reading { a, buf, .. } => Poll::Ok((a, buf)), State::Empty => panic!(), } } }