use sled::{Tree, transaction::UnabortableTransactionError};
use crate::database::{DatabaseEntry, Db, Entry, Id, TransactionError, deserialize_from_ivec};
pub struct Index<'a, T: DatabaseEntry> {
pub(crate) db: &'a Db<T::DbInner>,
pub(crate) tree: Tree,
pub(crate) name: &'static str,
}
impl<T: DatabaseEntry> Index<'_, T> {
pub fn rebuild(
&self,
f: impl Fn(&Tree, &Entry<T>) -> Result<(), UnabortableTransactionError>,
) -> Result<(), TransactionError> {
let entry_tree = self.db.entry_tree::<T>();
self.tree.clear()?;
for entry in &entry_tree {
let (k, v) = match entry {
Ok(v) => v,
Err(err) => {
self.tree.clear()?;
return Err(err.into());
}
};
let value = match deserialize_from_ivec::<T>(v) {
Ok(v) => v,
Err(err) => {
self.tree.clear()?;
return Err(err);
}
};
let id = Id::try_from(k).expect("All keys should be 32 bytes");
let entry = value.to_entry(id);
if let Err(err) = f(&self.tree, &entry) {
self.tree.clear()?;
return Err(err.into());
}
}
Ok(())
}
pub fn delete(self) -> Result<(), TransactionError> {
self.db.drop_tree(format!("index_{}", self.name))?;
Ok(())
}
}
impl<T: DatabaseEntry> std::ops::Deref for Index<'_, T> {
type Target = sled::Tree;
fn deref(&self) -> &Self::Target {
&self.tree
}
}