rp_cli/
api.rs

1use crate::api_types::{compile, download, execute, fmt, share};
2use serde::{de::DeserializeOwned, Deserialize, Serialize};
3
4pub const BASE_URL: &str = "https://play.rust-lang.org/";
5const PATH_EXECUTE: &str = "execute";
6const PATH_COMPILE: &str = "compile";
7const PATH_FMT: &str = "format";
8const PATH_SHARE: &str = "meta/gist";
9const PATH_DL: &str = "meta/gist";
10
11pub trait API {
12    fn execute(
13        &self,
14        req: execute::Request,
15    ) -> Result<execute::Response, Box<dyn std::error::Error>>;
16    fn compile(
17        &self,
18        req: compile::Request,
19    ) -> Result<compile::Response, Box<dyn std::error::Error>>;
20
21    fn fmt(&self, req: fmt::Request) -> Result<fmt::Response, Box<dyn std::error::Error>>;
22
23    fn share(&self, req: share::Request) -> Result<share::Response, Box<dyn std::error::Error>>;
24
25    fn download(
26        &self,
27        req: download::Request,
28    ) -> Result<download::Response, Box<dyn std::error::Error>>;
29}
30
31pub struct APIClient {
32    base_url: String,
33}
34
35impl APIClient {
36    pub fn new() -> APIClient {
37        APIClient {
38            base_url: BASE_URL.to_string(),
39        }
40    }
41
42    fn get<D>(&self, path: &str) -> Result<D, Box<dyn std::error::Error>>
43    where
44        D: DeserializeOwned,
45    {
46        let url = self.base_url.clone() + path;
47        let res: D = reqwest::blocking::get(url)?.json()?;
48
49        Ok(res)
50    }
51
52    fn post<S, D>(&self, path: &str, body: S) -> Result<D, Box<dyn std::error::Error>>
53    where
54        S: Serialize,
55        D: DeserializeOwned,
56    {
57        let url = self.base_url.clone() + path;
58        let client = reqwest::blocking::Client::new();
59        let res: D = client.post(url).json(&body).send()?.json()?;
60
61        Ok(res)
62    }
63}
64
65impl API for APIClient {
66    fn execute(
67        &self,
68        req: execute::Request,
69    ) -> Result<execute::Response, Box<dyn std::error::Error>> {
70        let res: execute::Response = self.post(PATH_EXECUTE, req)?;
71        Ok(res)
72    }
73
74    fn compile(
75        &self,
76        req: compile::Request,
77    ) -> Result<compile::Response, Box<dyn std::error::Error>> {
78        let res: compile::Response = self.post(PATH_COMPILE, req)?;
79        Ok(res)
80    }
81
82    fn fmt(&self, req: fmt::Request) -> Result<fmt::Response, Box<dyn std::error::Error>> {
83        let res: fmt::Response = self.post(PATH_FMT, req)?;
84        Ok(res)
85    }
86
87    fn share(&self, req: share::Request) -> Result<share::Response, Box<dyn std::error::Error>> {
88        let res: share::Response = self.post(PATH_SHARE, req)?;
89        Ok(res)
90    }
91
92    fn download(
93        &self,
94        req: download::Request,
95    ) -> Result<download::Response, Box<dyn std::error::Error>> {
96        let path = format!("{}/{}", PATH_DL, req.id);
97        let res: download::Response = self.get(&path)?;
98
99        Ok(res)
100    }
101}