use futures::future::{self, Future};
use futures::Stream;
use hyper::client::{Client as HyperClient, Connect};
use hyper::error::Error as HyperError;
use hyper::Uri;
use serde_json;
use std::str::FromStr;
use ::builder::Search;
use ::model::*;
use ::{API_URL, Error};
macro_rules! try_uri {
($uri:ident) => {
match Uri::from_str($uri) {
Ok(v) => v,
Err(why) => return Box::new(future::err(Error::Uri(why))),
}
}
}
pub trait KitsuRequester {
fn get_anime(&self, id: u64)
-> Box<Future<Item = Response<Anime>, Error = Error>>;
fn get_character(&self, id: u64)
-> Box<Future<Item = Response<Character>, Error = Error>>;
fn get_manga(&self, id: u64)
-> Box<Future<Item = Response<Manga>, Error = Error>>;
fn get_producer(&self, id: u64)
-> Box<Future<Item = Response<Producer>, Error = Error>>;
fn get_user(&self, id: u64)
-> Box<Future<Item = Response<User>, Error = Error>>;
fn search_anime<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Anime>>, Error = Error>>;
fn search_characters<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Character>>, Error = Error>>;
fn search_manga<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Manga>>, Error = Error>>;
fn search_users<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<User>>, Error = Error>>;
}
impl<B, C: Connect> KitsuRequester for HyperClient<C, B>
where B: Stream<Error = HyperError> + 'static, B::Item: AsRef<[u8]> {
fn get_anime(&self, id: u64)
-> Box<Future<Item = Response<Anime>, Error = Error>> {
let url = format!("{}/anime/{}", API_URL, id);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn get_character(&self, id: u64)
-> Box<Future<Item = Response<Character>, Error = Error>> {
let url = format!("{}/characters/{}", API_URL, id);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn get_manga(&self, id: u64)
-> Box<Future<Item = Response<Manga>, Error = Error>> {
let url = format!("{}/manga/{}", API_URL, id);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn get_producer(&self, id: u64)
-> Box<Future<Item = Response<Producer>, Error = Error>> {
let url = format!("{}/producer/{}", API_URL, id);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn get_user(&self, id: u64)
-> Box<Future<Item = Response<User>, Error = Error>> {
let url = format!("{}/users/{}", API_URL, id);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn search_anime<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Anime>>, Error = Error>> {
let params = f(Search::default()).0;
let url = format!("{}/anime?{}", API_URL, params);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn search_characters<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Character>>, Error = Error>> {
let params = f(Search::default()).0;
let url = format!("{}/characters?{}", API_URL, params);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn search_manga<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<Manga>>, Error = Error>> {
let params = f(Search::default()).0;
let url = format!("{}/manga?{}", API_URL, params);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn search_users<F: FnOnce(Search) -> Search>(&self, f: F)
-> Box<Future<Item = Response<Vec<User>>, Error = Error>> {
let params = f(Search::default()).0;
let url = format!("{}/users?{}", API_URL, params);
let c = &url;
let uri = try_uri!(c);
Box::new(self.get(uri)
.and_then(|res| res.body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
}