1use crate::api::ForesterHttpApi;
2use reqwest::Response;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::time::Duration;
6
7pub struct ForesterHttpClient {
20 api: ForesterHttpApi,
21 timeout: Option<Duration>,
22}
23
24impl ForesterHttpClient {
25 pub fn new(base: String) -> Self {
26 let api = ForesterHttpApi::new(base);
27 Self { api, timeout: None }
28 }
29 pub async fn new_with(base: String, timeout: Duration) -> Self {
30 let api = ForesterHttpApi::new(base);
31 Self {
32 api,
33 timeout: Some(timeout),
34 }
35 }
36
37 pub async fn new_trace_event(&self, tick: usize, text: String) -> Result<Response, TickError> {
39 Ok(self
40 .client()?
41 .post(&self.api.trace_event())
42 .json(&CustomEvent { text, tick })
43 .send()
44 .await?)
45 }
46 pub async fn print_trace(&self) -> Result<Response, TickError> {
48 Ok(self.client()?.get(&self.api.print_trace()).send().await?)
49 }
50 pub async fn lock(&self, id: String) -> Result<Response, TickError> {
52 Ok(self.client()?.get(&self.api.lock(id)).send().await?)
53 }
54 pub async fn unlock(&self, id: String) -> Result<Response, TickError> {
56 Ok(self.client()?.get(&self.api.unlock(id)).send().await?)
57 }
58 pub async fn locked(&self, id: String) -> Result<Response, TickError> {
60 Ok(self.client()?.get(&self.api.locked(id)).send().await?)
61 }
62 pub async fn contains(&self, id: String) -> Result<Response, TickError> {
64 Ok(self.client()?.get(&self.api.contains(id)).send().await?)
65 }
66 pub async fn take(&self, id: String) -> Result<Response, TickError> {
68 Ok(self.client()?.get(&self.api.take(id)).send().await?)
69 }
70 pub async fn get(&self, id: String) -> Result<Response, TickError> {
72 Ok(self.client()?.get(&self.api.get(id)).send().await?)
73 }
74 pub async fn put(&self, id: String, value: Value) -> Result<Response, TickError> {
76 Ok(self
77 .client()?
78 .post(&self.api.put(id))
79 .json(&value)
80 .send()
81 .await?)
82 }
83
84 fn client(&self) -> Result<reqwest::Client, TickError> {
85 match self.timeout {
86 Some(timeout) => Ok(reqwest::Client::builder().timeout(timeout).build()?),
87 None => Ok(reqwest::Client::new()),
88 }
89 }
90}
91
92#[derive(Debug)]
94pub struct TickError {
95 pub message: String,
96}
97
98impl From<reqwest::Error> for TickError {
99 fn from(value: reqwest::Error) -> Self {
100 Self::new(format!("{:?}", value))
101 }
102}
103
104impl TickError {
105 pub fn new(message: String) -> Self {
106 Self { message }
107 }
108}
109
110#[derive(Debug, Deserialize, Serialize)]
112pub struct CustomEvent {
113 text: String,
114 tick: usize,
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::client::ForesterHttpClient;
121
122 #[test]
123 fn trace_event_then_print_event() {
124 let client = ForesterHttpClient::new("http://localhost:10000".to_string());
125 let resp = client.new_trace_event(1, "test".to_string()).unwrap();
126 assert_eq!(resp.status(), 200);
127 let resp = client.print_trace().unwrap();
128 assert_eq!(resp.status(), 200);
129 let text = resp.text().unwrap();
130 assert_eq!("[1]custom: test\r\n", text)
131 }
132}