use crate::agent::error::AgentResult;
use async_trait::async_trait;
#[async_trait]
pub trait Storage<K, V>: Send + Sync {
async fn load(&self, key: &K) -> AgentResult<Option<V>>;
async fn save(&self, key: &K, value: &V) -> AgentResult<()>;
async fn delete(&self, key: &K) -> AgentResult<bool>;
async fn list(&self) -> AgentResult<Vec<K>>;
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
struct InMemoryStorage {
data: Arc<RwLock<HashMap<String, Vec<u8>>>>,
}
impl InMemoryStorage {
fn new() -> Self {
Self {
data: Arc::new(RwLock::new(HashMap::new())),
}
}
}
#[async_trait]
impl Storage<String, Vec<u8>> for InMemoryStorage {
async fn load(&self, key: &String) -> AgentResult<Option<Vec<u8>>> {
let data = self.data.read().await;
Ok(data.get(key).cloned())
}
async fn save(&self, key: &String, value: &Vec<u8>) -> AgentResult<()> {
let mut data = self.data.write().await;
data.insert(key.clone(), value.clone());
Ok(())
}
async fn delete(&self, key: &String) -> AgentResult<bool> {
let mut data = self.data.write().await;
Ok(data.remove(key).is_some())
}
async fn list(&self) -> AgentResult<Vec<String>> {
let data = self.data.read().await;
Ok(data.keys().cloned().collect())
}
}
#[tokio::test]
async fn test_storage_basic_operations() {
let storage = InMemoryStorage::new();
storage
.save(&"key1".to_string(), &vec![1, 2, 3])
.await
.unwrap();
let value = storage.load(&"key1".to_string()).await.unwrap();
assert_eq!(value, Some(vec![1, 2, 3]));
let keys = storage.list().await.unwrap();
assert_eq!(keys, vec!["key1".to_string()]);
let deleted = storage.delete(&"key1".to_string()).await.unwrap();
assert!(deleted);
let value = storage.load(&"key1".to_string()).await.unwrap();
assert_eq!(value, None);
}
}