libsurfer/remote/
client.rs
1use super::HierarchyResponse;
2use bincode::Options;
3use color_eyre::eyre::{bail, eyre};
4use color_eyre::Result;
5use log::info;
6use wellen::CompressedTimeTable;
7
8use surver::{
9 Status, BINCODE_OPTIONS, HTTP_SERVER_KEY, HTTP_SERVER_VALUE_SURFER, SURFER_VERSION,
10 WELLEN_VERSION, X_SURFER_VERSION, X_WELLEN_VERSION,
11};
12
13fn check_response(server_url: &str, response: &reqwest::Response) -> Result<()> {
14 let server = response
15 .headers()
16 .get(HTTP_SERVER_KEY)
17 .ok_or(eyre!("no server header"))?
18 .to_str()?;
19 if server != HTTP_SERVER_VALUE_SURFER {
20 bail!("Unexpected server {server} from {server_url}");
21 }
22 let surfer_version = response
23 .headers()
24 .get(X_SURFER_VERSION)
25 .ok_or(eyre!("no surfer version header"))?
26 .to_str()?;
27 if surfer_version != SURFER_VERSION {
28 info!("Surfer version on the server: {surfer_version} does not match client version {SURFER_VERSION}");
30 }
31 let wellen_version = response
32 .headers()
33 .get(X_WELLEN_VERSION)
34 .ok_or(eyre!("no wellen version header"))?
35 .to_str()?;
36 if wellen_version != WELLEN_VERSION {
37 bail!("Version incompatibility! The server uses wellen {wellen_version}, our client uses wellen {WELLEN_VERSION}");
38 }
39 Ok(())
40}
41
42pub async fn get_status(server: String) -> Result<Status> {
43 let client = reqwest::Client::new();
44 let response = client.get(format!("{server}/get_status")).send().await?;
45 check_response(&server, &response)?;
46 let body = response.text().await?;
47 let status = serde_json::from_str::<Status>(&body)?;
48 Ok(status)
49}
50
51pub async fn get_hierarchy(server: String) -> Result<HierarchyResponse> {
52 let client = reqwest::Client::new();
53 let response = client.get(format!("{server}/get_hierarchy")).send().await?;
54 check_response(&server, &response)?;
55 let compressed = response.bytes().await?;
56 let raw = lz4_flex::decompress_size_prepended(&compressed)?;
57 let mut reader = std::io::Cursor::new(raw);
58 let opts = BINCODE_OPTIONS.allow_trailing_bytes();
60 let file_format: wellen::FileFormat = opts.deserialize_from(&mut reader)?;
61 let hierarchy: wellen::Hierarchy = BINCODE_OPTIONS.deserialize_from(&mut reader)?;
63 Ok(HierarchyResponse {
64 hierarchy,
65 file_format,
66 })
67}
68
69pub async fn get_time_table(server: String) -> Result<Vec<wellen::Time>> {
70 let client = reqwest::Client::new();
71 let response = client
72 .get(format!("{server}/get_time_table"))
73 .send()
74 .await?;
75 check_response(&server, &response)?;
76 let compressed_data = response.bytes().await?;
77 let compressed: CompressedTimeTable = BINCODE_OPTIONS.deserialize(&compressed_data)?;
78 let table = compressed.uncompress();
79 Ok(table)
80}
81
82pub async fn get_signals(
83 server: String,
84 signals: &[wellen::SignalRef],
85) -> Result<Vec<(wellen::SignalRef, wellen::Signal)>> {
86 let client = reqwest::Client::new();
87 let mut url = format!("{server}/get_signals");
88 for signal in signals.iter() {
89 url.push_str(&format!("/{}", signal.index()));
90 }
91
92 let response = client.get(url).send().await?;
93 check_response(&server, &response)?;
94 let data = response.bytes().await?;
95 let mut reader = std::io::Cursor::new(data);
96 let num_ids: u64 = leb128::read::unsigned(&mut reader)?;
97 if num_ids > signals.len() as u64 {
98 bail!(
99 "Too many signals in response: {num_ids}, expected {}",
100 signals.len()
101 );
102 }
103 if num_ids == 0 {
104 return Ok(vec![]);
105 }
106
107 let opts = BINCODE_OPTIONS.allow_trailing_bytes();
108 let mut out = Vec::with_capacity(num_ids as usize);
109 for _ in 0..(num_ids - 1) {
110 let compressed: wellen::CompressedSignal = opts.deserialize_from(&mut reader)?;
111 let signal = compressed.uncompress();
112 out.push((signal.signal_ref(), signal));
113 }
114 let compressed: wellen::CompressedSignal = BINCODE_OPTIONS.deserialize_from(&mut reader)?;
116 let signal = compressed.uncompress();
117 out.push((signal.signal_ref(), signal));
118 Ok(out)
119}