use std::io::{self, BufRead, Read};
use httparse;
use futures::{Async, Future, Poll};
use {Error, Metadata, Method, Version};
use status::RawStatus;
use header::Headers;
use connection::TransportStream;
use unsafe_types::UnsafeRawStatus;
use super::Connection;
#[derive(Debug)]
pub struct ReadResponse<T>(Option<Connection<T>>);
impl<T: TransportStream> ReadResponse<T> {
pub fn new(mut connection: Connection<T>) -> Self {
connection.inner.buffer.enter_read_phase();
ReadResponse(Some(connection))
}
}
impl<T: TransportStream> Future for ReadResponse<T> {
type Item = Response<T>;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut connection = self.0.take().expect("Cannot poll ReadResponse twice");
let (bytes, headers) = unsafe { connection.inner.buffer_and_headers() };
let mut res = httparse::Response::new(headers);
if let httparse::Status::Complete(body_offset) =
track!(res.parse(bytes).map_err(Error::from))?
{
connection.inner.buffer.consume(body_offset);
let version = if res.version.unwrap() == 0 {
Version::Http1_0
} else {
debug_assert_eq!(res.version.unwrap(), 1);
Version::Http1_1
};
let status = RawStatus::new(res.code.unwrap(), res.reason.unwrap());
Ok(Async::Ready(Response {
version: version,
status: status,
headers: Headers::new(res.headers),
connection: connection,
}))
} else {
let filled = track!(connection.inner.fill_buffer().map_err(Error::from))?;
self.0 = Some(connection);
if filled {
self.poll()
} else {
Ok(Async::NotReady)
}
}
}
}
#[derive(Debug)]
pub struct Response<T> {
version: Version,
status: UnsafeRawStatus,
headers: Headers<'static>,
connection: Connection<T>,
}
impl<T> Response<T> {
pub fn version(&self) -> Version {
self.version
}
pub fn status(&self) -> &RawStatus {
&self.status
}
pub fn headers(&self) -> &Headers {
&self.headers
}
pub fn finish(self) -> Connection<T> {
self.connection
}
}
impl<T: TransportStream> Read for Response<T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if !self.connection.inner.buffer.is_empty() {
self.connection.inner.buffer.read(buf)
} else {
self.connection.inner.stream.read(buf)
}
}
}
impl<T> Metadata for Response<T> {
fn version(&self) -> Version {
self.version
}
fn headers(&self) -> &Headers {
&self.headers
}
fn status(&self) -> Option<&RawStatus> {
Some(&self.status)
}
fn method(&self) -> Option<Method> {
None
}
fn path(&self) -> Option<&str> {
None
}
}