use std::{env::temp_dir, ops::Range};
use sled::{transaction::ConflictableTransactionError, Config, Db};
use uuid::Uuid;
use crate::{
storage::{Item, ItemIterator, Storage},
StorageError, ID,
};
impl From<sled::Error> for StorageError {
fn from(e: sled::Error) -> Self {
Self::Miscellaneous(Box::new(e))
}
}
impl From<sled::transaction::TransactionError> for StorageError {
fn from(e: sled::transaction::TransactionError) -> Self {
Self::Miscellaneous(Box::new(e))
}
}
pub struct SledStorage {
db: Db,
id: ID,
}
impl Storage for SledStorage {
fn range(&self, r: Range<&[u8]>) -> Result<ItemIterator<'_>, StorageError> {
Ok(Box::new(
self.db
.range(r)
.map(|r| r.map_err(|e| e.into()).map(|(k, _)| k.to_vec())),
))
}
fn insert(&self, is: &[Item]) -> Result<(), StorageError> {
self.db.transaction(|t| {
for i in is {
t.insert(i.as_slice(), vec![])?;
}
Ok::<(), ConflictableTransactionError>(())
})?;
Ok(())
}
fn id(&self) -> ID {
self.id
}
}
impl SledStorage {
pub fn connect_temp() -> Result<Self, sled::Error> {
let mut path = temp_dir();
path.push(Uuid::new_v4().to_string());
path.set_extension("db");
let cfg = Config::new().path(path).temporary(true);
let db = cfg.open()?;
Ok(Self { db, id: ID::new() })
}
pub fn connect(uri: &str) -> Result<Self, sled::Error> {
let cfg = Config::new().path(uri);
let db = cfg.open()?;
Ok(Self { db, id: ID::new() })
}
}