frond 0.1.1

dynamic lexicographic containers
Documentation
use std::collections::BTreeMap;

use super::{Key, Value};

pub struct Iter<'a> {
    inner: std::collections::btree_map::Range<'a, Vec<u8>, Vec<u8>>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = (&'a [u8], &'a [u8]);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|(k, v)| (&**k, &**v))
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.inner.next_back().map(|(k, v)| (&**k, &**v))
    }
}

/// `Petal` is a dynamically-sized type (DST) that succinctly stores keys and values, accessible
/// lexicographically.
#[derive(Default, Clone)]
pub struct Petal {
    lo: Vec<u8>,
    hi: Option<Vec<u8>>,
    storage: BTreeMap<Vec<u8>, Vec<u8>>,
}

impl Petal {
    pub fn new() -> Box<Petal> {
        Box::default()
    }

    pub fn len(&self) -> usize {
        self.storage.len()
    }

    pub fn contains(&self, key: Key) -> bool {
        self.storage.contains_key(key)
    }

    pub fn get(&self, key: Key) -> Option<Value> {
        self.storage.get(key).map(|v| &**v)
    }

    pub fn range<'a>(
        &'a self,
        start: std::ops::Bound<&[u8]>,
        end: std::ops::Bound<&[u8]>,
    ) -> Iter<'a> {
        Iter {
            inner: self.storage.range::<[u8], _>((start, end)),
        }
    }

    #[must_use]
    pub fn batch<'a, I: IntoIterator<Item = (&'a [u8], Option<&'a [u8]>)>>(
        &self,
        iter: I,
    ) -> Box<Petal> {
        let mut ret = Box::new(Petal {
            hi: self.hi.clone(),
            lo: self.lo.clone(),
            storage: self.storage.clone(),
        });

        for (key, value_opt) in iter {
            self.assert_key_in_bounds(key);
            if let Some(value) = value_opt {
                ret.storage.insert(key.to_vec(), value.to_vec());
            }
        }

        ret
    }

    #[must_use]
    pub fn split(&self, split_key: Key) -> (Box<Petal>, Box<Petal>) {
        self.assert_key_in_bounds(split_key);

        let mut lhs_storage = BTreeMap::default();
        let mut rhs_storage = BTreeMap::default();

        for (k, v) in &self.storage {
            if &**k < split_key {
                lhs_storage.insert(k.clone(), v.clone());
            } else {
                rhs_storage.insert(k.clone(), v.clone());
            }
        }

        let lhs = Box::new(Petal {
            lo: self.lo.clone(),
            hi: Some(split_key.to_vec()),
            storage: lhs_storage,
        });

        let rhs = Box::new(Petal {
            lo: split_key.to_vec(),
            hi: self.hi.clone(),
            storage: rhs_storage,
        });

        (lhs, rhs)
    }

    #[must_use]
    pub fn merge(&self, rhs: &Petal) -> Box<Petal> {
        assert_eq!(self.hi.as_ref().unwrap(), &*rhs.lo);

        let storage = self
            .storage
            .iter()
            .chain(rhs.storage.iter())
            .map(|(k, v)| (k.clone(), v.clone()))
            .collect();

        Box::new(Petal {
            lo: self.lo.clone(),
            hi: rhs.hi.clone(),
            storage,
        })
    }

    fn assert_key_in_bounds(&self, key: Key) {
        assert!(key >= &self.lo);
        if let Some(hi) = &self.hi {
            assert!(key < &hi);
        }
    }
}