use constants::API_URI;
use futures::{Future, Stream, future};
use hyper::body::Body;
use hyper::client::connect::Connect;
use hyper::client::Client as HyperClient;
use hyper::{Request, Uri};
use model::{InfoResult, Search, SearchBy, SearchResult};
use serde_json;
use std::fmt::{Display, Write};
use std::str::FromStr;
use Error;
macro_rules! ftry {
($code:expr) => {
match $code {
Ok(v) => v,
Err(why) => return Box::new(future::err(From::from(why))),
}
}
}
pub trait AurRequester {
fn aur_info<T: Display>(&self, packages: &[T])
-> Box<Future<Item = Search<InfoResult>, Error = Error> + Send>;
fn aur_search_by(&self, query: &str, by: SearchBy)
-> Box<Future<Item = Search<SearchResult>, Error = Error> + Send>;
fn aur_search(&self, query: &str)
-> Box<Future<Item = Search<SearchResult>, Error = Error> + Send>
{
self.aur_search_by(query, SearchBy::NameDesc)
}
fn aur_orphans(&self)
-> Box<Future<Item = Search<SearchResult>, Error = Error> + Send>
{
self.aur_search_by("", SearchBy::Maintainer)
}
}
impl<C> AurRequester for HyperClient<C, Body>
where C: Connect + Sync + 'static,
C::Future: 'static,
C::Transport: 'static {
fn aur_info<T: Display>(&self, packages: &[T])
-> Box<Future<Item = Search<InfoResult>, Error = Error> + Send + 'static> {
let mut url = format!("{}&type=info", API_URI);
for package in packages {
if let Err(why) = write!(url, "&arg[]={}", package) {
return Box::new(future::err(Error::Fmt(why)));
}
}
let c = &url;
let uri = ftry!(Uri::from_str(c));
let mut request = Request::get(uri);
let req = ftry!(request.body(Body::empty()));
Box::new(self.request(req)
.and_then(|res| res.into_body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
fn aur_search_by(&self, query: &str, by: SearchBy)
-> Box<Future<Item = Search<SearchResult>, Error = Error> + Send + 'static> {
let url = format!("{}&type=search&arg={}&by={}", API_URI, query, by);
let c = &url;
let uri = ftry!(Uri::from_str(c));
let mut request = Request::get(uri);
let req = ftry!(request.body(Body::empty()));
Box::new(self.request(req)
.and_then(|res| res.into_body().concat2())
.map_err(From::from)
.and_then(|body| serde_json::from_slice(&body).map_err(From::from)))
}
}