use constants::API_URI;
use model::{InfoResult, Search, SearchBy, SearchResult};
use std::fmt::{Display, Write};
use std::io::Read;
use reqwest::{Client as ReqwestClient, RequestBuilder, StatusCode, Url};
use serde::de::DeserializeOwned;
use serde_json;
use {Error, Result};
pub trait AurRequester {
fn aur_info<T: Display>(&self, packages: &[T])
-> Result<Search<InfoResult>>;
fn aur_search_by(&self, query: &str, by: SearchBy)
-> Result<Search<SearchResult>>;
fn aur_search(&self, query: &str)
-> Result<Search<SearchResult>>
{
self.aur_search_by(query, SearchBy::NameDesc)
}
fn aur_orphans(&self)
-> Result<Search<SearchResult>>
{
self.aur_search_by("", SearchBy::Maintainer)
}
}
impl AurRequester for ReqwestClient {
fn aur_info<T: Display>(&self, packages: &[T])
-> Result<Search<InfoResult>> {
let mut url = format!("{}&type=info", API_URI);
for package in packages {
write!(url, "&arg[]={}", package)?;
}
let uri = Url::parse(&url)?;
handle_request::<Search<InfoResult>>(self.get(uri))
}
fn aur_search_by(&self, query: &str, by: SearchBy)
-> Result<Search<SearchResult>> {
let url = format!("{}&type=search&arg={}&by={}", API_URI, query, by);
let uri = Url::parse(&url)?;
handle_request::<Search<SearchResult>>(self.get(uri))
}
}
fn handle_request<T: DeserializeOwned>(request: RequestBuilder) -> Result<T> {
let response = request.send()?;
match response.status() {
StatusCode::OK => {},
StatusCode::BAD_REQUEST => {
return Err(Error::ReqwestBad(Box::new(response)));
},
_ => return Err(Error::ReqwestInvalid(Box::new(response))),
}
from_reader(response)
}
#[inline]
fn from_reader<T: DeserializeOwned, U: Read>(reader: U) -> Result<T> {
serde_json::from_reader(reader).map_err(From::from)
}