s0-meter/src/rest_api.rs

90 lines
3 KiB
Rust
Raw Permalink Normal View History

2021-02-23 00:08:28 +01:00
#[cfg(test)]
#[path = "./rest_api_test.rs"]
mod rest_api_test;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
2021-02-23 00:08:28 +01:00
use tide;
use tide::prelude::json;
pub trait DataProvider {
fn get_channels(&self) -> Vec<usize>;
fn get_pulses_by_channel(&mut self, channel: usize) -> Result<Vec<PulseInfo>, std::io::Error>;
}
2021-02-23 00:08:28 +01:00
#[derive(Serialize, Deserialize, Debug)]
pub struct PulseInfo {
pub timestamp_ns: u64,
pub channel_id: usize,
pub level: bool,
2021-02-23 00:08:28 +01:00
}
#[derive(Clone)]
pub struct RestApiConfig {
pub ip_and_port: String,
pub data_provider: Arc<Mutex<Box<dyn DataProvider + Send>>>,
2021-02-23 00:08:28 +01:00
}
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<RestApiConfig>) -> tide::Result {
#[derive(Serialize)]
struct ApiVersionInfo {
version: String,
path: String,
}
let mut version_list = Vec::<ApiVersionInfo>::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<RestApiConfig>) -> 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();
2021-02-23 00:08:28 +01:00
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<RestApiConfig>) -> 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);
2021-02-23 00:08:28 +01:00
match channel_pulses_res {
Ok(channel_pulses) => Ok(tide::Response::builder(200)
.content_type(tide::http::mime::JSON)
.body(json!({
"channel_id": channel_id,
2021-02-23 00:08:28 +01:00
"pulses": channel_pulses,
}))
.build()),
Err(_) => Ok(tide::Response::new(404)),
}
}
Err(_) => Ok(tide::Response::new(405)),
},
Err(_e) => Ok(tide::Response::new(404)),
}
}