use crate::error::Error;
pub type CollectionEntry = (String, Vec<u8>);
pub type CollectionEntryResult = Result<CollectionEntry, Error>;
pub type CollectionIter<'a> =
Box<dyn Iterator<Item = CollectionEntryResult> + 'a>;
pub trait DbManager<C, S>: Sync + Send + Clone
where
C: Collection + 'static,
S: State + 'static,
{
fn create_collection(&self, name: &str, prefix: &str) -> Result<C, Error>;
fn create_state(&self, name: &str, prefix: &str) -> Result<S, Error>;
fn stop(&mut self) -> Result<(), Error> {
Ok(())
}
}
pub trait State: Sync + Send + 'static {
fn name(&self) -> &str;
fn get(&self) -> Result<Vec<u8>, Error>;
fn put(&mut self, data: &[u8]) -> Result<(), Error>;
fn del(&mut self) -> Result<(), Error>;
fn purge(&mut self) -> Result<(), Error>;
}
pub trait Collection: Sync + Send + 'static {
fn name(&self) -> &str;
fn get(&self, key: &str) -> Result<Vec<u8>, Error>;
fn put(&mut self, key: &str, data: &[u8]) -> Result<(), Error>;
fn del(&mut self, key: &str) -> Result<(), Error>;
fn last(&self) -> Result<Option<(String, Vec<u8>)>, Error>;
fn purge(&mut self) -> Result<(), Error>;
fn iter<'a>(&'a self, reverse: bool) -> Result<CollectionIter<'a>, Error>;
fn get_by_range(
&self,
from: Option<String>,
quantity: isize,
) -> Result<Vec<Vec<u8>>, Error> {
fn convert<'a>(
iter: impl Iterator<Item = CollectionEntryResult> + 'a,
) -> CollectionIter<'a> {
Box::new(iter)
}
let (mut iter, quantity) = match from {
Some(key) => {
let iter = if quantity >= 0 {
self.iter(false)?
} else {
self.iter(true)?
};
let mut iter = iter.peekable();
loop {
let Some(next_item) = iter.peek() else {
return Err(Error::EntryNotFound { key });
};
let (current_key, _) = match next_item {
Ok((current_key, event)) => (current_key, event),
Err(error) => return Err(error.clone()),
};
if current_key == &key {
break;
}
iter.next();
}
iter.next(); (convert(iter), quantity.abs())
}
None => {
if quantity >= 0 {
(self.iter(false)?, quantity)
} else {
(self.iter(true)?, quantity.abs())
}
}
};
let mut result = Vec::new();
let mut counter = 0;
while counter < quantity {
let Some(item) = iter.next() else {
break;
};
let (_, event) = item?;
result.push(event);
counter += 1;
}
Ok(result)
}
}
#[macro_export]
macro_rules! test_store_trait {
($name:ident: $type:ty: $type2:ty) => {
#[cfg(test)]
mod $name {
use super::*;
use $crate::error::Error;
#[test]
fn test_create_collection() {
let mut manager = <$type>::default();
let store: $type2 =
manager.create_collection("test", "test").unwrap();
assert_eq!(Collection::name(&store), "test");
assert!(manager.stop().is_ok())
}
#[test]
fn test_create_state() {
let mut manager = <$type>::default();
let store: $type2 =
manager.create_state("test", "test").unwrap();
assert_eq!(State::name(&store), "test");
assert!(manager.stop().is_ok())
}
#[test]
fn test_put_get_collection() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key", b"value").unwrap();
assert_eq!(Collection::get(&store, "key").unwrap(), b"value");
assert!(manager.stop().is_ok())
}
#[test]
fn test_put_get_state() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_state("test", "test").unwrap();
State::put(&mut store, b"value").unwrap();
assert_eq!(State::get(&store).unwrap(), b"value");
assert!(manager.stop().is_ok())
}
#[test]
fn test_del_collection() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key", b"value").unwrap();
Collection::del(&mut store, "key").unwrap();
assert_eq!(
Collection::get(&store, "key"),
Err(Error::EntryNotFound {
key: "test.key".to_owned()
})
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_del_state() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_state("test", "test").unwrap();
State::put(&mut store, b"value").unwrap();
State::del(&mut store).unwrap();
assert_eq!(
State::get(&store),
Err(Error::EntryNotFound {
key: "test".to_owned()
})
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_iter() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key1", b"value1").unwrap();
Collection::put(&mut store, "key2", b"value2").unwrap();
Collection::put(&mut store, "key3", b"value3").unwrap();
let items: Vec<_> = store
.iter(false)
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(
items,
vec![
("key1".to_string(), b"value1".to_vec()),
("key2".to_string(), b"value2".to_vec()),
("key3".to_string(), b"value3".to_vec()),
]
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_iter_reverse() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key1", b"value1").unwrap();
Collection::put(&mut store, "key2", b"value2").unwrap();
Collection::put(&mut store, "key3", b"value3").unwrap();
let items: Vec<_> = store
.iter(true)
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(
items,
vec![
("key3".to_string(), b"value3".to_vec()),
("key2".to_string(), b"value2".to_vec()),
("key1".to_string(), b"value1".to_vec()),
]
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_last() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key1", b"value1").unwrap();
Collection::put(&mut store, "key2", b"value2").unwrap();
Collection::put(&mut store, "key3", b"value3").unwrap();
let last = store.last().unwrap();
assert_eq!(
last,
Some(("key3".to_string(), b"value3".to_vec()))
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_get_by_range() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key1", b"value1").unwrap();
Collection::put(&mut store, "key2", b"value2").unwrap();
Collection::put(&mut store, "key3", b"value3").unwrap();
let result = store.get_by_range(None, 2).unwrap();
assert_eq!(
result,
vec![b"value1".to_vec(), b"value2".to_vec()]
);
let result =
store.get_by_range(Some("key3".to_string()), -2).unwrap();
assert_eq!(
result,
vec![b"value2".to_vec(), b"value1".to_vec()]
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_purge_collection() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_collection("test", "test").unwrap();
Collection::put(&mut store, "key1", b"value1").unwrap();
Collection::put(&mut store, "key2", b"value2").unwrap();
Collection::put(&mut store, "key3", b"value3").unwrap();
assert_eq!(
Collection::get(&store, "key1"),
Ok(b"value1".to_vec())
);
assert_eq!(
Collection::get(&store, "key2"),
Ok(b"value2".to_vec())
);
assert_eq!(
Collection::get(&store, "key3"),
Ok(b"value3".to_vec())
);
Collection::purge(&mut store).unwrap();
assert_eq!(
Collection::get(&store, "key1"),
Err(Error::EntryNotFound {
key: "test.key1".to_owned()
})
);
assert_eq!(
Collection::get(&store, "key2"),
Err(Error::EntryNotFound {
key: "test.key2".to_owned()
})
);
assert_eq!(
Collection::get(&store, "key3"),
Err(Error::EntryNotFound {
key: "test.key3".to_owned()
})
);
assert!(manager.stop().is_ok())
}
#[test]
fn test_purge_state() {
let mut manager = <$type>::default();
let mut store: $type2 =
manager.create_state("test", "test").unwrap();
State::put(&mut store, b"value1").unwrap();
assert_eq!(State::get(&store), Ok(b"value1".to_vec()));
State::purge(&mut store).unwrap();
assert_eq!(
State::get(&store),
Err(Error::EntryNotFound {
key: "test".to_owned()
})
);
State::put(&mut store, b"value2").unwrap();
assert_eq!(State::get(&store), Ok(b"value2".to_vec()));
State::purge(&mut store).unwrap();
assert_eq!(
State::get(&store),
Err(Error::EntryNotFound {
key: "test".to_owned()
})
);
assert!(manager.stop().is_ok())
}
}
};
}