use crate::{embedded, err};
use async_trait::async_trait;
use std::collections::HashMap;
use tokio::sync::RwLock;
#[derive(Debug, Default)]
pub struct Storage {
values: RwLock<HashMap<String, String>>,
}
impl Storage {
pub fn new() -> Self {
Default::default()
}
}
#[async_trait]
impl super::Storage for Storage {
async fn set(&self, key: String, value: String) -> embedded::Result<()> {
self.values.write().await.insert(key, value);
Ok(())
}
async fn get(&self, key: String) -> embedded::Result<String> {
if let Some(value) = self.values.read().await.get(&key) {
Ok(value.to_owned())
} else {
Err(err!(embedded, GetKeyFail))
}
}
async fn delete(&self, key: String) -> embedded::Result<()> {
if self.values.write().await.remove(&key).is_some() {
Ok(())
} else {
Err(err!(embedded, DeleteKeyFail))
}
}
async fn exists(&self, key: String) -> embedded::Result<bool> {
Ok(self.values.read().await.get(&key).is_some())
}
async fn increment(&self, key: String, num: usize) -> embedded::Result<usize> {
let raw = self.get(key.clone()).await?;
let new = raw
.parse::<usize>()
.map_err(|_| err!(embedded, UIntParseFail))?
+ num;
self.set(key, new.to_string()).await?;
Ok(new)
}
async fn decrement(&self, key: String, num: usize) -> embedded::Result<usize> {
let raw = self.get(key.clone()).await?;
let new = raw
.parse::<usize>()
.map_err(|_| err!(embedded, UIntParseFail))?
- num;
self.set(key, new.to_string()).await?;
Ok(new)
}
async fn search(&self, key: String) -> embedded::Result<Vec<String>> {
Ok(self
.values
.read()
.await
.keys()
.filter(|&x| x.starts_with(&key))
.cloned()
.collect::<Vec<_>>())
}
async fn flush(&self) -> embedded::Result<()> {
self.values.write().await.clear();
Ok(())
}
}