summaryrefslogtreecommitdiffstats
path: root/librepology/src/v1/restapi.rs
blob: e9a6cd1da57acf6366045529e97eed7911056595 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::result::Result as RResult;

use curl::easy::Easy2;

use crate::v1::error::Result;
use crate::v1::error::RepologyError as Error;
use crate::v1::types::{Package, Problem};
use crate::v1::api::Api;

/// Private helper type for collecting data from the curl library
struct Collector(Vec<u8>);
impl curl::easy::Handler for Collector {
    fn write(&mut self, data: &[u8]) -> RResult<usize, curl::easy::WriteError> {
        self.0.extend_from_slice(data);
        Ok(data.len())
    }
}

/// Representational object for the REST Api of repology
pub struct RestApi {
    /// Base url
    repology: String,
}

impl RestApi {
    pub fn new(repology: String) -> Self {
        Self { repology }
    }

    /// Helper function for sending a request via the curl library
    fn send_request<U: AsRef<str>>(&self, request: U) -> Result<String> {
        let mut easy = Easy2::new(Collector(Vec::new()));
        easy.get(true)?;
        easy.url(request.as_ref())?;
        easy.perform()?;
        let content = easy.get_ref().0.clone(); // TODO: Ugh...
        String::from_utf8(content).map_err(Error::from)
    }
}

impl Api for RestApi {

    fn project<N: AsRef<str>>(&self, name: N) -> Result<Vec<Package>> {
        let url = format!("{}api/v1/project/{}", self.repology, name.as_ref());
        trace!("Request: {}", url);
        let response = self.send_request(url)?;
        serde_json::from_str(&response)
            .map_err(Error::from)
    }

    fn problems_for_repo<R: AsRef<str>>(&self, repo: R) -> Result<Vec<Problem>> {
        let url = format!("{}api/v1/repository/{}/problems", self.repology, repo.as_ref());
        trace!("Request: {}", url);
        let response = self.send_request(url)?;
        serde_json::from_str(&response).map_err(Error::from)
    }

    fn problems_for_maintainer<M: AsRef<str>>(&self, maintainer: M) -> Result<Vec<Problem>> {
        let url = format!("{}api/v1/maintainer/{}/problems", self.repology, maintainer.as_ref());
        trace!("Request: {}", url);
        let response = self.send_request(url)?;
        serde_json::from_str(&response).map_err(Error::from)
    }

}