kivis 0.5.1

Type-safe database schema generation for Rust with support for custom storage backends, automatic indexing, and layered cache architectures
Documentation
use core::ops::Range;
use core::{error::Error, fmt::Debug};

use crate::{BatchOp, BufferOverflowError, UnifierData};

/// A trait defining a repository backend decoupled from serialization.
///
/// The repository is responsible for storing and retrieving key-value pairs
/// without knowledge of how they are serialized. This allows for better
/// separation of concerns between data storage and serialization logic.
pub trait Repository {
    /// Key type for the repository (the buffer type, e.g., Vec<u8> or String).
    type K: UnifierData;

    /// Value type for the repository (the buffer type, e.g., Vec<u8> or String).
    type V: UnifierData;

    /// Error type returned by repository operations.
    type Error: Debug + Error + From<BufferOverflowError>;

    /// Insert a key-value pair into the repository.
    ///
    /// # Errors
    ///
    /// Returns an error if the underlying storage fails to insert the key-value pair.
    fn insert_entry(
        &mut self,
        key: <Self::K as UnifierData>::View<'_>,
        value: <Self::V as UnifierData>::View<'_>,
    ) -> Result<(), Self::Error>;

    /// Retrieve the value associated with the given key from the repository.
    ///
    /// # Errors
    ///
    /// Returns an error if the underlying storage fails while retrieving the value.
    fn get_entry(
        &self,
        key: <Self::K as UnifierData>::View<'_>,
    ) -> Result<Option<Self::V>, Self::Error>;

    /// Remove the value associated with the given key from the repository.
    ///
    /// # Errors
    ///
    /// Returns an error if the underlying storage fails while removing the value.
    fn remove_entry(
        &mut self,
        key: <Self::K as UnifierData>::View<'_>,
    ) -> Result<Option<Self::V>, Self::Error>;
    /// Iterate over the keys in the repository that are in range.
    ///
    /// # Errors
    ///
    /// Returns an error if the underlying storage fails during iteration.
    fn scan_range(
        &self,
        range: Range<Self::K>,
    ) -> Result<impl Iterator<Item = IterationItem<Self::K, Self::Error>>, Self::Error>;

    /// Execute mixed insert and delete operations.
    ///
    /// # Errors
    ///
    /// Returns an error if any of the insert or remove operations fail.
    fn apply<'a>(
        &mut self,
        operations: impl Iterator<Item = BatchOp<'a, Self::K, Self::V>>,
    ) -> Result<(), Self::Error> {
        for op in operations {
            match op {
                BatchOp::Insert { key, value } => {
                    self.insert_entry(key, value)?;
                }
                BatchOp::Delete { key } => {
                    self.remove_entry(key)?;
                }
            }
        }

        Ok(())
    }
}

type IterationItem<K, E> = Result<K, E>;