mod errors;
use std::sync::mpsc::channel;
use std::sync::{Arc, RwLock};
use rouille::input::json::json_input;
use rouille::{Request, Response};
use crate::{
constants::REQUEST_TIMEOUT,
init::TSLibrary,
init::Transmitters,
models::{Library, Model, Peripheral, Value},
plugins::{init as init_plugin, Message},
};
pub use errors::HandlerError;
use errors::ResourceNotFoundError;
type Result<T> = std::result::Result<T, HandlerError>;
pub fn get_libraries(libs: &[TSLibrary]) -> Result<Response> {
let mut result = Vec::new();
for lib in libs {
result.push(lib.lock()?.clone());
}
Ok(Response::json(&result))
}
pub fn get_library(id: usize, libs: &[TSLibrary]) -> Result<Response> {
let lib = libs
.get(id)
.ok_or(ResourceNotFoundError {
id,
name: String::from(Library::key()),
})?
.lock()?;
Ok(Response::json(&*lib))
}
pub fn get_peripheral(id: usize, txs: Arc<RwLock<Transmitters>>) -> Result<Response> {
let txs = txs.read()?;
let ptx = txs
.get(&id)
.ok_or(ResourceNotFoundError {
id,
name: String::from(Peripheral::key()),
})?
.lock()?;
let (tx, rx) = channel();
let msg = Message::GetPeripheral(tx);
ptx.send(msg)?;
rx.recv_timeout(REQUEST_TIMEOUT)?
.map(|attr| Response::json(&attr))
.map_err(HandlerError::from)
}
pub fn get_peripherals(txs: Arc<RwLock<Transmitters>>) -> Result<Response> {
let mut msg: Message;
let mut p: Peripheral;
let txs = txs.read()?;
let mut peripherals = Vec::new();
for (_, mutex) in txs.iter() {
let ptx = mutex.lock()?;
let (tx, rx) = channel();
msg = Message::GetPeripheral(tx);
ptx.send(msg)?;
p = rx.recv_timeout(REQUEST_TIMEOUT)??;
peripherals.push(p);
}
Ok(Response::json(&peripherals))
}
pub fn post_peripherals(
request: &Request,
libs: &[TSLibrary],
txs: Arc<RwLock<Transmitters>>,
) -> Result<Response> {
let mut periph: Peripheral = json_input(&request)?;
let lib = match libs.get(periph.library_id()) {
Some(lib) => lib.clone(),
None => {
let mut response = Response::text("Library does not exist.\n");
response.status_code = 400;
return Ok(response);
}
};
let id: usize = count_and_incr(txs.clone())?;
periph.set_id(id);
init_plugin(&mut periph, lib, txs)?;
let mut response = Response::text("The peripheral has been created.\n");
response.status_code = 201;
response.headers.push((
"Location".into(),
format!("/api/v0/peripherals/{}", &periph.id()).into(),
));
Ok(response)
}
pub fn get_peripheral_attribute(
id: usize,
attr_id: usize,
txs: Arc<RwLock<Transmitters>>,
) -> Result<Response> {
let txs = txs.read()?;
let ptx = txs
.get(&id)
.ok_or(ResourceNotFoundError {
id,
name: String::from(Peripheral::key()),
})?
.lock()?;
let (tx, rx) = channel();
let msg = Message::GetPeripheralAttribute(attr_id, tx);
ptx.send(msg)?;
rx.recv_timeout(REQUEST_TIMEOUT)?
.map(|attr| Response::json(&attr))
.map_err(HandlerError::from)
}
pub fn patch_peripheral_attribute(
request: &Request,
id: usize,
attr_id: usize,
txs: Arc<RwLock<Transmitters>>,
) -> Result<Response> {
let value: Value = json_input(&request)?;
let txs = txs.read()?;
let ptx = txs
.get(&id)
.ok_or(ResourceNotFoundError {
id,
name: String::from(Peripheral::key()),
})?
.lock()?;
let (tx, rx) = channel();
let msg = Message::PatchPeripheralAttribute(attr_id, value, tx);
ptx.send(msg)?;
rx.recv_timeout(REQUEST_TIMEOUT)?
.map(|attr| Response::json(&attr))
.map_err(HandlerError::from)
}
pub fn get_peripheral_attributes(id: usize, txs: Arc<RwLock<Transmitters>>) -> Result<Response> {
let txs = txs.read()?;
let ptx = txs
.get(&id)
.ok_or(ResourceNotFoundError {
id,
name: String::from(Peripheral::key()),
})?
.lock()?;
let (tx, rx) = channel();
let msg = Message::GetPeripheralAttributes(tx);
ptx.send(msg)?;
rx.recv_timeout(REQUEST_TIMEOUT)?
.map(|attr| Response::json(&attr))
.map_err(HandlerError::from)
}
fn count_and_incr(txs: Arc<RwLock<Transmitters>>) -> Result<usize> {
let txs = txs.read()?;
if txs.len() == 0 {
return Ok(0);
}
let mut largest_id: usize = 0;
for (id, _) in txs.iter() {
if *id > largest_id {
largest_id = *id
}
}
Ok(largest_id + 1)
}