use futures::sink::Sink;
use futures::future::FutureResult;
use futures::{Async, AsyncSink, Future, IntoFuture};
use client::{Error, Encoder, EncoderDone, Head, RecvMode};
use client::errors::ErrorEnum;
use client::buffered;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BodyKind {
Fixed(u64),
Chunked,
Eof,
}
pub trait Codec<S> {
type Future: Future<Item=EncoderDone<S>, Error=Error>;
fn start_write(&mut self, e: Encoder<S>)
-> Self::Future;
fn headers_received(&mut self, headers: &Head) -> Result<RecvMode, Error>;
fn data_received(&mut self, data: &[u8], end: bool)
-> Result<Async<usize>, Error>;
}
impl<S, F> Codec<S> for Box<Codec<S, Future=F>>
where F: Future<Item=EncoderDone<S>, Error=Error>
{
type Future = F;
fn start_write(&mut self, e: Encoder<S>) -> F {
(**self).start_write(e)
}
fn headers_received(&mut self, headers: &Head) -> Result<RecvMode, Error> {
(**self).headers_received(headers)
}
fn data_received(&mut self, data: &[u8], end: bool)
-> Result<Async<usize>, Error>
{
(**self).data_received(data, end)
}
}
impl<S, F> Codec<S> for Box<Codec<S, Future=F>+Send>
where F: Future<Item=EncoderDone<S>, Error=Error>
{
type Future = F;
fn start_write(&mut self, e: Encoder<S>) -> F {
(**self).start_write(e)
}
fn headers_received(&mut self, headers: &Head) -> Result<RecvMode, Error> {
(**self).headers_received(headers)
}
fn data_received(&mut self, data: &[u8], end: bool)
-> Result<Async<usize>, Error>
{
(**self).data_received(data, end)
}
}
pub trait Client<S, F>: Sink<SinkItem=Box<Codec<S, Future=F>>>
where F: Future<Item=EncoderDone<S>, Error=Error>,
{
fn fetch_url(&mut self, url: &str)
-> Box<Future<Item=buffered::Response, Error=Error>>
where <Self as Sink>::SinkError: Into<Error>;
}
impl<T, S> Client<S, FutureResult<EncoderDone<S>, Error>> for T
where T: Sink<SinkItem=Box<
Codec<S, Future=FutureResult<EncoderDone<S>, Error>>
>>,
{
fn fetch_url(&mut self, url: &str)
-> Box<Future<Item=buffered::Response, Error=Error>>
where <Self as Sink>::SinkError: Into<Error>
{
let url = match url.parse() {
Ok(u) => u,
Err(_) => {
return Box::new(Err(ErrorEnum::InvalidUrl.into())
.into_future());
}
};
let (codec, receiver) = buffered::Buffered::get(url);
match self.start_send(Box::new(codec)) {
Ok(AsyncSink::NotReady(_)) => {
Box::new(Err(ErrorEnum::Busy.into()).into_future())
}
Ok(AsyncSink::Ready) => {
Box::new(receiver
.map_err(|_| ErrorEnum::Canceled.into())
.and_then(|res| res))
}
Err(e) => {
Box::new(Err(e.into()).into_future())
}
}
}
}