frond 0.1.1

dynamic lexicographic containers
Documentation
//! `frond` is an immutable, contiguous container for arbitrary keys and values. It can be split and merged.
//! It is initially created as [`sled`](https://github.com/spacejam/sled)'s new leaf structure,
//! but it can be used for any chunk of data that you may want to put on disk - like a LSM SST
//! etc...

mod composite;
mod naive;

pub use composite::Composite;
pub use naive::Petal as Naive;

type Key<'a> = &'a [u8];
type Value<'a> = &'a [u8];

pub trait Interface: Default {
    type Iter<'a>: DoubleEndedIterator<Item = (&'a [u8], &'a [u8])>
    where
        Self: 'a;

    fn get(&self, key: Key) -> Option<Value>;

    #[must_use]
    fn batch<'a, I: IntoIterator<Item = (&'a [u8], Option<&'a [u8]>)>>(&self, iter: I) -> Self;

    #[must_use]
    fn contains(&self, key: Key) -> bool;

    #[must_use]
    fn split(&self, split_key: Key) -> (Self, Self);

    #[must_use]
    fn len(&self) -> usize;

    #[must_use]
    fn merge(&self, rhs: &Self) -> Self;

    #[must_use]
    fn insert(&self, key: Key, value: Value) -> (Option<Value>, Self) {
        let last = self.get(key);
        let new = self.batch([(key, Some(value))]);
        (last, new)
    }

    #[must_use]
    fn remove(&self, key: Key) -> (Option<Value>, Self) {
        let last = self.get(key);
        let new = self.batch([(key, None)]);
        (last, new)
    }

    fn range<'a>(
        &'a self,
        start: std::ops::Bound<&[u8]>,
        end: std::ops::Bound<&[u8]>,
    ) -> Self::Iter<'a>;
}

impl Interface for Box<Naive> {
    type Iter<'a> = naive::Iter<'a> where Self: 'a;

    fn range<'a>(
        &'a self,
        start: std::ops::Bound<&[u8]>,
        end: std::ops::Bound<&[u8]>,
    ) -> Self::Iter<'a> {
        Naive::range(self, start, end)
    }

    fn get(&self, key: Key) -> Option<Value> {
        Naive::get(self, key)
    }

    fn batch<'a, I: IntoIterator<Item = (&'a [u8], Option<&'a [u8]>)>>(&self, iter: I) -> Self {
        Naive::batch(self, iter)
    }

    fn contains(&self, key: Key) -> bool {
        Naive::contains(self, key)
    }

    fn split(&self, split_key: Key) -> (Self, Self) {
        Naive::split(self, split_key)
    }

    fn len(&self) -> usize {
        Naive::len(self)
    }

    fn merge(&self, rhs: &Self) -> Self {
        Naive::merge(self, rhs)
    }
}

impl<A: Interface, B: Interface> Interface for Composite<A, B> {
    type Iter<'a> = composite::Iter<'a, A, B> where Self: 'a;

    fn get(&self, key: Key) -> Option<Value> {
        Composite::get(self, key)
    }

    fn range<'a>(
        &'a self,
        start: std::ops::Bound<&[u8]>,
        end: std::ops::Bound<&[u8]>,
    ) -> Self::Iter<'a> {
        Composite::range(self, start, end)
    }

    fn batch<'a, I: IntoIterator<Item = (&'a [u8], Option<&'a [u8]>)>>(&self, iter: I) -> Self {
        Composite::batch(self, iter)
    }

    fn contains(&self, key: Key) -> bool {
        Composite::contains(self, key)
    }

    fn split(&self, split_key: Key) -> (Self, Self) {
        Composite::split(self, split_key)
    }

    fn len(&self) -> usize {
        Composite::len(self)
    }

    fn merge(&self, rhs: &Self) -> Self {
        Composite::merge(self, rhs)
    }
}