orga 0.1.10

State machine engine
Documentation
use crate::error::Result;
use crate::state::State;
use std::ops::{Deref, DerefMut};

mod bufstore;
mod iter;
mod nullstore;
mod prefix;
mod rwlog;
mod share;
mod split;

pub use bufstore::Map as BufStoreMap;
pub use bufstore::{BufStore, MapStore};
pub use iter::{Entry, Iter};
pub use nullstore::NullStore;
pub use prefix::Prefixed;
pub use rwlog::RWLog;
pub use share::Shared;
pub use split::Splitter;

// TODO: Key type (for cheaper concat, enum over ref or owned slice, etc)

/// Trait for read access to key/value stores.
pub trait Read: Sized {
    /// Gets a value by key.
    ///
    /// Implementations of `get` should return `None` when there is no value for
    /// the key rather than erroring.
    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;

    /// Wraps self with a given [`state::State`](../state/trait.State.html)
    /// implementation, provided for convenience.
    fn wrap<T: State<Self>>(self) -> Result<T> {
        T::wrap_store(self)
    }

    /// Wraps self with [`Shared`](struct.Shared.html), allowing it to be cloned
    /// so that multiple callers can share the reference to the underlying
    /// store.
    fn into_shared(self) -> Shared<Self> {
        Shared::new(self)
    }

    /// Wraps self with [`Prefixed`](struct.Prefixed.html) using the given
    /// prefix byte, so that all operations have the prefix prepended to their
    /// keys.
    fn prefix(self, prefix: u8) -> Prefixed<Self> {
        Prefixed::new(self, prefix)
    }

    /// Wraps self with [`Splitter`](struct.Splitter.html) so that prefixed
    /// substores may be created by calling `.split()`.
    fn into_splitter(self) -> Splitter<Self> {
        Splitter::new(self)
    }

    /// Returns an immutable reference to the store.
    fn as_ref<'a>(&'a self) -> &'a Self {
        self
    }
}

/// Trait for write access to key/value stores.
pub trait Write {
    /// Writes a key and value to the store.
    ///
    /// If a value already exists for the given key, implementations should
    /// overwrite the value.
    fn put(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<()>;

    /// Deletes the value with the given key.
    ///
    /// If no value exists for the given key, implementations should treat the
    /// operation as a no-op (but may still issue a call to `delete` to an
    /// underlying store).
    fn delete(&mut self, key: &[u8]) -> Result<()>;

    /// Returns a mutable reference to the store.
    fn as_mut<'a>(&'a mut self) -> &'a mut Self {
        self
    }
}

/// Trait for key/value stores, automatically implemented for any type which has
/// both `Read` and `Write`.
pub trait Store: Read + Write {}

impl<S: Read + Write + Sized> Store for S {}

impl<S: Read, T: Deref<Target = S>> Read for T {
    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
        self.deref().get(key)
    }
}

impl<S: Write, T: DerefMut<Target = S>> Write for T {
    fn put(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<()> {
        self.deref_mut().put(key, value)
    }

    fn delete(&mut self, key: &[u8]) -> Result<()> {
        self.deref_mut().delete(key)
    }
}

/// A trait for types which contain data that can be flushed to an underlying
/// store.
pub trait Flush {
    // TODO: should this consume the store? or will we want it like this so we
    // can persist the same wrapper store and flush it multiple times?
    fn flush(&mut self) -> Result<()>;
}

#[cfg(test)]
mod tests {
    use super::{NullStore, Read};
    use crate::state::Value;

    #[test]
    fn fixed_length_slice_key() {
        let key = b"0123";
        NullStore.get(key).unwrap();
    }

    #[test]
    fn slice_key() {
        let key = vec![1, 2, 3, 4];
        NullStore.get(key.as_slice()).unwrap();
    }

    #[test]
    fn wrap() {
        let _: Value<_, u64> = NullStore.wrap().unwrap();
    }
}