frond 0.1.1

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

use super::{Interface, Key, Value};

// TODO open issues:
// *

pub struct Iter<'a, A: Interface, B: Interface> {
    inner: &'a Composite<A, B>,
}

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

    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

impl<'a, A: Interface, B: Interface> DoubleEndedIterator for Iter<'a, A, B> {
    fn next_back(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

#[derive(Default, Clone)]
pub struct Composite<A: Interface, B: Interface> {
    a: A,
    b: B,
    tombstones: HashSet<Vec<u8>>,
    merge_threshold: usize,
}

impl<A: Interface, B: Interface> Composite<A, B> {
    pub fn new(merge_threshold: usize) -> Composite<A, B> {
        Composite {
            a: A::default(),
            b: B::default(),
            tombstones: HashSet::default(),
            merge_threshold,
        }
    }

    pub fn len(&self) -> usize {
        self.a.len() + self.b.len() - self.tombstones.len()
    }

    pub fn contains(&self, key: Key) -> bool {
        self.a.contains(key) || (!self.tombstones.contains(key) && self.b.contains(key))
    }

    pub fn get(&self, key: Key) -> Option<Value> {
        if let Some(v) = self.a.get(key) {
            Some(v)
        } else if self.tombstones.contains(key) {
            None
        } else {
            self.b.get(key)
        }
    }

    #[must_use]
    pub fn batch<'a, I: IntoIterator<Item = (&'a [u8], Option<&'a [u8]>)>>(
        &self,
        iter: I,
    ) -> Composite<A, B> {
        let mut ret = todo!();

        for (key, value) in iter {
            self.assert_key_in_bounds(key);
            todo!()
        }

        ret
    }

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

        todo!()
    }

    #[must_use]
    pub fn merge(&self, rhs: &Composite<A, B>) -> Composite<A, B> {
        todo!()
    }

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

    fn assert_key_in_bounds(&self, key: Key) {
        todo!()
    }
}