#[cfg(test)] #[path = "./rest_api_test.rs"] mod rest_api_test; use serde::{Deserialize, Serialize}; use std::sync::{Arc, Mutex}; use tide; use tide::prelude::json; pub trait DataProvider { fn get_channels(&self) -> Vec; fn get_pulses_by_channel(&mut self, channel: usize) -> Result, std::io::Error>; } #[derive(Serialize, Deserialize, Debug)] pub struct PulseInfo { pub timestamp_ns: u64, pub pin_id: usize, pub level: bool, } #[derive(Clone)] pub struct RestApiConfig { pub ip_and_port: String, pub data_provider: Arc>>, } pub async fn start<'a>(config: &'a RestApiConfig) -> std::io::Result<()> { let mut app = tide::with_state(config.clone()); app.at("/api_versions").get(api_versions_get); app.at("/v1/channels").get(v1_channels_get); app.at("/v1/channel/:channel_id/pulses") .get(v1_channel_pulses_get); let ip_and_port = String::from(&config.ip_and_port); match app.listen(ip_and_port).await { Ok(_) => Ok(()), Err(e) => Err(e), } } async fn api_versions_get(_: tide::Request) -> tide::Result { #[derive(Serialize)] struct ApiVersionInfo { version: String, path: String, } let mut version_list = Vec::::new(); version_list.push(ApiVersionInfo { version: String::from("1.0"), path: String::from("v1"), }); Ok(tide::Response::builder(200) .content_type(tide::http::mime::JSON) .body(json!({ "api_versions": &version_list })) .build()) } async fn v1_channels_get(req: tide::Request) -> tide::Result { let data_provider = &(*req.state().data_provider).lock().unwrap(); // let data_provider = data_provider_mut.lock().unwrap(); let channel_list = data_provider.get_channels(); Ok(tide::Response::builder(200) .content_type(tide::http::mime::JSON) .body(json!({ "channels": channel_list })) .build()) } async fn v1_channel_pulses_get(req: tide::Request) -> tide::Result { match req.param("channel_id") { Ok(channel_id) => match usize::from_str_radix(channel_id, 10) { Ok(channel_id) => { let data_provider = &mut (*req.state().data_provider).lock().unwrap(); let channel_pulses_res = data_provider.get_pulses_by_channel(channel_id); match channel_pulses_res { Ok(channel_pulses) => Ok(tide::Response::builder(200) .content_type(tide::http::mime::JSON) .body(json!({ "channel": channel_id, "pulses": channel_pulses, })) .build()), Err(_) => Ok(tide::Response::new(404)), } } Err(_) => Ok(tide::Response::new(405)), }, Err(_e) => Ok(tide::Response::new(404)), } }