persy 1.8.0

Transactional Persistence Engine
Documentation
use crate::{
    PersyImpl,
    id::IndexId,
    index::{
        config::{IndexTypeInternal, ValueMode},
        raw_iter::IndexRawIter,
        tree::nodes::Value,
    },
    transaction::tx_impl::TransactionImpl,
};

use std::{cmp::Ordering, sync::Arc, vec::IntoIter};

/// Index Iterator implementation for iterating on a range of keys considering in transaction
/// changes
pub struct TxIndexRawIter<K, V> {
    index_id: IndexId,
    index_name: String,
    in_tx: Option<IntoIter<K>>,
    persistent: Option<IndexRawIter<K, V>>,
    in_tx_front: Option<Option<K>>,
    persistent_front: Option<Option<(K, Value<V>)>>,
    in_tx_back: Option<Option<K>>,
    persistent_back: Option<Option<(K, Value<V>)>>,
    value_mode: ValueMode,
}

impl<K, V> TxIndexRawIter<K, V>
where
    K: IndexTypeInternal,
    V: IndexTypeInternal,
{
    pub fn new(
        index_id: IndexId,
        index_name: String,
        in_tx: Option<IntoIter<K>>,
        persistent: Option<IndexRawIter<K, V>>,
        value_mode: ValueMode,
    ) -> TxIndexRawIter<K, V> {
        TxIndexRawIter {
            index_id,
            index_name,
            in_tx,
            persistent,
            in_tx_front: None,
            persistent_front: None,
            in_tx_back: None,
            persistent_back: None,
            value_mode,
        }
    }

    fn apply_changes(
        tx: &mut TransactionImpl,
        vm: ValueMode,
        index: IndexId,
        index_name: &str,
        k: K,
        pers: Option<Value<V>>,
    ) -> Option<(K, Value<V>)> {
        tx.apply_changes(vm, index, index_name, &k, pers)
            .unwrap_or(None)
            .map(|v| (k, v))
    }

    pub fn next(&mut self, persy_impl: &Arc<PersyImpl>, tx: &mut TransactionImpl) -> Option<(K, Value<V>)> {
        loop {
            let vm = self.value_mode.clone();
            let index = self.index_id.clone();
            let index_name = &self.index_name;
            let apply_changes = |k, o| Self::apply_changes(tx, vm, index, index_name, k, o);
            match (&mut self.in_tx, &mut self.persistent) {
                (Some(it), Some(pers)) => {
                    match (
                        self.in_tx_front.get_or_insert_with(|| it.next()).clone(),
                        self.persistent_front
                            .get_or_insert_with(|| pers.next(persy_impl))
                            .clone(),
                    ) {
                        (Some(tx_k), Some((pers_k, vals))) => match tx_k.cmp(&pers_k) {
                            Ordering::Less => {
                                self.in_tx_front = None;
                                let res = apply_changes(tx_k, None);
                                if res.is_some() {
                                    break res;
                                }
                            }
                            Ordering::Equal => {
                                self.in_tx_front = None;
                                self.persistent_front = None;
                                let res = apply_changes(tx_k, Some(vals));

                                if res.is_some() {
                                    break res;
                                }
                            }
                            Ordering::Greater => {
                                self.persistent_front = None;
                                break Some((pers_k, vals));
                            }
                        },
                        (Some(tx_k), None) => {
                            self.in_tx_front = None;
                            let res = apply_changes(tx_k, None);
                            if res.is_some() {
                                break res;
                            }
                        }
                        (None, Some((pers_k, vals))) => {
                            self.persistent_front = None;
                            break Some((pers_k, vals));
                        }
                        (None, None) => break None,
                    }
                }
                (Some(it), None) => {
                    break it.next().and_then(|v| apply_changes(v, None));
                }
                (None, Some(pers)) => break pers.next(persy_impl),
                (None, None) => break None,
            }
        }
    }

    pub fn next_back(&mut self, persy_impl: &Arc<PersyImpl>, tx: &mut TransactionImpl) -> Option<(K, Value<V>)> {
        loop {
            let vm = self.value_mode.clone();
            let index = self.index_id.clone();
            let index_name = &self.index_name;
            let apply_changes = |k, o| Self::apply_changes(tx, vm, index, index_name, k, o);
            match (&mut self.in_tx, &mut self.persistent) {
                (Some(it), Some(pers)) => {
                    match (
                        self.in_tx_back.get_or_insert_with(|| it.next_back()).clone(),
                        self.persistent_back
                            .get_or_insert_with(|| pers.next_back(persy_impl))
                            .clone(),
                    ) {
                        (Some(tx_k), Some((pers_k, vals))) => match tx_k.cmp(&pers_k) {
                            Ordering::Less => {
                                self.persistent_back = None;
                                break Some((pers_k, vals));
                            }
                            Ordering::Equal => {
                                self.in_tx_back = None;
                                self.persistent_back = None;
                                let res = apply_changes(tx_k, Some(vals));

                                if res.is_some() {
                                    break res;
                                }
                            }
                            Ordering::Greater => {
                                self.in_tx_back = None;
                                let res = apply_changes(tx_k, None);

                                if res.is_some() {
                                    break res;
                                }
                            }
                        },
                        (Some(tx_k), None) => {
                            self.in_tx_back = None;
                            let res = apply_changes(tx_k, None);
                            if res.is_some() {
                                break res;
                            }
                        }
                        (None, Some((pers_k, vals))) => {
                            self.persistent_back = None;
                            break Some((pers_k, vals));
                        }
                        (None, None) => break None,
                    }
                }
                (Some(it), None) => {
                    break it.next_back().and_then(|v| apply_changes(v, None));
                }
                (None, Some(pers)) => break pers.next_back(persy_impl),
                (None, None) => break None,
            }
        }
    }
}