lunar-lib 0.11.0

Common utilities for lunar applications
Documentation
use sled::{Tree, transaction::UnabortableTransactionError};

use crate::{
    database::{DatabaseEntry, Db, Entry, TransactionError, deserialize_from_ivec},
    id::Id,
};

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
    }
}