141 lines
3.7 KiB
Rust
141 lines
3.7 KiB
Rust
use crate::message::Command;
|
|
use sled::{Db, IVec, Tree};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub(crate) struct Store {
|
|
commands: Tree,
|
|
settings: Tree,
|
|
db: Db,
|
|
}
|
|
|
|
impl Store {
|
|
pub(crate) async fn build(db: Db) -> Result<Self, anyhow::Error> {
|
|
tokio::task::spawn_blocking(move || {
|
|
Ok(Store {
|
|
commands: db.open_tree("dog.asonix.git.asonix.streamdeck/commands")?,
|
|
settings: db.open_tree("dog.asonix.git.asonix.streamdeck/settings")?,
|
|
db,
|
|
}) as Result<Store, anyhow::Error>
|
|
})
|
|
.await?
|
|
}
|
|
|
|
pub(crate) async fn setting<T>(&self, key: &str) -> Result<Option<T>, anyhow::Error>
|
|
where
|
|
T: serde::de::DeserializeOwned,
|
|
{
|
|
let key = key.to_owned();
|
|
let settings = self.settings.clone();
|
|
|
|
let opt = tokio::task::spawn_blocking(move || settings.get(key)).await??;
|
|
|
|
if let Some(ivec) = opt {
|
|
return Ok(Some(serde_json::from_slice(&ivec)?));
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
|
|
pub(crate) async fn save_setting<T>(&self, key: &str, value: T) -> Result<(), anyhow::Error>
|
|
where
|
|
T: serde::Serialize,
|
|
{
|
|
let key = key.to_owned();
|
|
let value = serde_json::to_vec(&value)?;
|
|
let settings = self.settings.clone();
|
|
|
|
tokio::task::spawn_blocking(move || settings.insert(key, value)).await??;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) async fn unset(&self, deck: &str, input: u8) -> Result<(), anyhow::Error> {
|
|
let key = self.cmd_key(deck, input);
|
|
|
|
let commands = self.commands.clone();
|
|
tokio::task::spawn_blocking(move || commands.remove(key)).await??;
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) async fn store(
|
|
&self,
|
|
deck: &str,
|
|
input: u8,
|
|
command: &Command,
|
|
) -> Result<(), anyhow::Error> {
|
|
let key = self.cmd_key(deck, input);
|
|
let value = self.cmd_value(command)?;
|
|
|
|
let commands = self.commands.clone();
|
|
tokio::task::spawn_blocking(move || commands.insert(key, value)).await??;
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) async fn pressed(
|
|
&self,
|
|
deck: &str,
|
|
input: u8,
|
|
) -> Result<Option<Command>, anyhow::Error> {
|
|
let key = self.cmd_key(deck, input);
|
|
|
|
let commands = self.commands.clone();
|
|
let opt = tokio::task::spawn_blocking(move || commands.get(key)).await??;
|
|
|
|
if let Some(ivec) = opt {
|
|
return Ok(Some(serde_json::from_slice(&ivec)?));
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
|
|
pub(crate) async fn get_commands(
|
|
&self,
|
|
deck: &str,
|
|
) -> Result<Vec<(u8, Command)>, anyhow::Error> {
|
|
let prefix = self.cmd_prefix(deck);
|
|
|
|
let commands = self.commands.clone();
|
|
let vec = tokio::task::spawn_blocking(move || {
|
|
let prefix_len = prefix.len();
|
|
commands
|
|
.scan_prefix(prefix)
|
|
.filter_map(|res| {
|
|
let (key, value) = res.ok()?;
|
|
|
|
if key.len() != prefix_len + 1 {
|
|
return None;
|
|
}
|
|
|
|
let key = key[prefix_len];
|
|
|
|
let command = serde_json::from_slice(&value).ok()?;
|
|
|
|
Some((key, command))
|
|
})
|
|
.collect()
|
|
})
|
|
.await?;
|
|
|
|
Ok(vec)
|
|
}
|
|
|
|
fn cmd_prefix(&self, deck: &str) -> IVec {
|
|
let mut prefix = deck.as_bytes().to_vec();
|
|
prefix.push(b'/');
|
|
|
|
IVec::from(prefix)
|
|
}
|
|
|
|
fn cmd_key(&self, deck: &str, input: u8) -> IVec {
|
|
let mut key = deck.as_bytes().to_vec();
|
|
key.push(b'/');
|
|
key.push(input);
|
|
|
|
IVec::from(key)
|
|
}
|
|
|
|
fn cmd_value(&self, command: &Command) -> Result<IVec, anyhow::Error> {
|
|
Ok(IVec::from(serde_json::to_vec(&command)?))
|
|
}
|
|
}
|