use crate::error::Result;
use crate::format::CharValue;
use crate::tree::Accessory;
use crate::{
build_read_request, build_subscribe_request, build_write_request, parse_accessories,
parse_read_response,
};
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum Request {
Get {
path: String,
},
Put {
path: String,
body: Vec<u8>,
},
}
pub trait RequestExecutor {
fn execute(&mut self, req: Request) -> Result<Vec<u8>>;
}
pub struct AccessoryDatabase<E: RequestExecutor> {
executor: E,
accessories: Vec<Accessory>,
}
impl<E: RequestExecutor> AccessoryDatabase<E> {
pub fn fetch(mut executor: E) -> Result<Self> {
let body = executor.execute(Request::Get {
path: "/accessories".to_string(),
})?;
let accessories = parse_accessories(&body)?;
Ok(Self {
executor,
accessories,
})
}
pub fn accessories(&self) -> &[Accessory] {
&self.accessories
}
pub fn read(&mut self, ids: &[(u64, u64)]) -> Result<Vec<((u64, u64), CharValue)>> {
let path = build_read_request(ids);
let body = self.executor.execute(Request::Get { path })?;
parse_read_response(&body)
}
pub fn write(&mut self, writes: &[((u64, u64), CharValue)]) -> Result<()> {
let body = build_write_request(writes);
self.executor.execute(Request::Put {
path: "/characteristics".to_string(),
body,
})?;
Ok(())
}
pub fn subscribe(&mut self, ids: &[(u64, u64)], enable: bool) -> Result<()> {
let body = build_subscribe_request(ids, enable);
self.executor.execute(Request::Put {
path: "/characteristics".to_string(),
body,
})?;
Ok(())
}
}