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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
extern crate hyper;
extern crate hyper_native_tls;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

static URL: &'static str = "http://api.openaq.org";

pub mod json {
    use hyper::Client;
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use std::io::Read;

    use super::*;

    pub mod requests {
        pub const CITIES: &str = "/v1/cities";
    }

    pub struct GetOpts {
        pub query: Option<String>,
    }

    pub fn get_cities_query(opts: GetCitiesQueryOpts) -> String {
        return String::from("page=") + &opts.page.to_string() + "&limit=" +
               &opts.limit.to_string() + "&country=" + opts.country;
    }

    pub fn get(req: &str, opts: Option<GetOpts>) -> String {
        let ssl = NativeTlsClient::new().unwrap();
        let connector = HttpsConnector::new(ssl);
        let client = Client::with_connector(connector);

        let full_url = match &opts {
            &None => String::from(URL) + req,
            &Some(ref o) => {
                match &o.query {
                    &None => String::from(URL) + req,
                    &Some(ref q) => String::from(URL) + req + "?" + q,
                }
            }
        };

        let mut res = client.get(&full_url).send().unwrap();

        assert_eq!(res.status, hyper::Ok);
        let mut s = String::new();
        res.read_to_string(&mut s).unwrap();

        return s;
    }
}

pub struct GetCitiesQueryOpts<'a> {
    pub page: u32,
    pub limit: u32,
    pub country: &'a str,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct City {
    #[serde(rename = "city")]
    name: String,
    count: u32,
    country: String,
    locations: u32,
}

#[derive(Debug, Serialize, Deserialize)]
struct RequestResult {
    results: Vec<City>,
}

pub fn get_cities(cities_query_opts: Option<GetCitiesQueryOpts>) -> Vec<City> {
    let get_opts = match cities_query_opts {
        None => None,
        Some(o) => {
            let cities_query = json::get_cities_query(o);
            let opts = json::GetOpts { query: Some(cities_query) };
            Some(opts)
        }
    };
    let result = json::get(json::requests::CITIES, get_opts);


    let v: RequestResult = serde_json::from_str(&result).unwrap();

    return v.results;
}