2021-02-23 00:08:28 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
|
#[path = "./rest_api_test.rs"]
|
|
|
|
|
mod rest_api_test;
|
|
|
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
2021-02-28 22:22:15 +01:00
|
|
|
use std::sync::{Arc, Mutex};
|
2021-02-23 00:08:28 +01:00
|
|
|
use tide;
|
|
|
|
|
use tide::prelude::json;
|
|
|
|
|
|
2021-02-28 22:22:15 +01:00
|
|
|
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 {
|
2021-02-28 22:22:15 +01:00
|
|
|
pub timestamp_ns: u64,
|
2021-03-01 00:00:00 +01:00
|
|
|
pub channel_id: usize,
|
2021-02-28 22:22:15 +01:00
|
|
|
pub level: bool,
|
2021-02-23 00:08:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct RestApiConfig {
|
|
|
|
|
pub ip_and_port: String,
|
2021-02-28 22:22:15 +01:00
|
|
|
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 {
|
2021-02-28 22:22:15 +01:00
|
|
|
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) => {
|
2021-02-28 22:22:15 +01:00
|
|
|
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!({
|
2021-03-01 00:00:00 +01:00
|
|
|
"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)),
|
|
|
|
|
}
|
|
|
|
|
}
|