use crate::{
id::IndexId,
index::{
config::{IndexTypeInternal, ValueMode},
raw_iter::IndexRawIter,
tree::nodes::Value,
},
transaction::tx_impl::TransactionImpl,
PersyImpl,
};
use std::{cmp::Ordering, sync::Arc, vec::IntoIter};
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) => {
let res = apply_changes(it.next().unwrap(), None);
if res.is_some() {
break res;
}
}
(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) => {
let res = apply_changes(it.next_back().unwrap(), None);
if res.is_some() {
break res;
}
}
(None, Some(pers)) => break pers.next_back(persy_impl),
(None, None) => break None,
}
}
}
}