dartlib 0.3.0

Disk backed concurrent Adaptive Radix Tree implementation, with optional generations.
Documentation
use crate::errors::Errors;
use crate::node::*;
use crate::tree::Dart;
use bincode::{Decode, Encode};
use crossbeam::atomic::AtomicCell;

struct RangeState {
    current_node: AtomicCell<NodePtr>,
    unseen: Vec<NodePtr>,
    stop: bool,
}

#[derive(Clone)]
pub struct ScanResult<T> {
    pub matches: Vec<(Vec<u8>, T)>,
}

pub struct Range<'a> {
    start: &'a [u8],
    end: &'a [u8],
    state: Option<RangeState>,
}

impl<'a> Range<'a> {
    pub fn new(start: &'a [u8], end: &'a [u8]) -> Self {
        Self {
            start,
            end,
            state: None,
        }
    }

    pub fn scan<T>(&mut self, tree: &Dart<T>) -> Result<ScanResult<T>, Errors>
    where
        T: Encode + Decode + Clone + Send,
    {
        let root = tree.root.load();
        let state = RangeState {
            current_node: AtomicCell::new(root),
            unseen: Vec::new(),
            stop: false,
        };

        self.state = Some(state);

        let mut result = ScanResult {
            matches: Vec::new(),
        };

        loop {
            if self.state.as_ref().unwrap().stop {
                break;
            }

            let node_ptr = self.state.as_mut().unwrap().current_node.load();
            let node_wrapper_opt = tree.cache.lock().unwrap().get(&node_ptr.id);
            if node_wrapper_opt.is_none() {
                return Err(Errors::NonExistantError);
            }
            let node_wrapper = node_wrapper_opt.unwrap();

            let node = node_wrapper.data.read()?;

            if node.is_leaf() {
                let leaf_data_ref = node.leaf_data_ref();
                if leaf_data_ref.key.as_slice() > self.start
                    && leaf_data_ref.key.as_slice() < self.end
                {
                    result
                        .matches
                        .push((leaf_data_ref.key.to_vec(), leaf_data_ref.value.clone()))
                }
            }

            if self.start <= node.internal_data_ref().prefix.as_slice()
                && node.internal_data_ref().prefix.as_slice() <= self.end
            {
                for child in node.internal_data_ref().children.iter() {
                    if child.id != EMPTY_POINTER_ID {
                        self.state.as_mut().unwrap().unseen.push(child.clone())
                    }
                }
            }

            if node.internal_data_ref().prefix.as_slice() > self.end {
                self.state.as_mut().unwrap().stop = true;
            }
        }

        Ok(result)
    }
}