use {
super::implementation::ColumnTrie,
crate::relation::Relation,
kermit_derive::IntoTrieIter,
kermit_iters::{LinearIterator, TrieIterable, TrieIterator, TrieIteratorWrapper},
};
#[derive(IntoTrieIter)]
pub struct ColumnTrieIter<'a> {
depth: usize,
interval_i: usize,
rel_data_i: usize,
rel_data: Option<&'a [usize]>,
trie: &'a ColumnTrie,
}
impl<'a> ColumnTrieIter<'a> {
pub fn new(trie: &'a ColumnTrie) -> Self {
ColumnTrieIter {
interval_i: 0,
rel_data: None,
rel_data_i: 0,
depth: 0,
trie,
}
}
}
impl LinearIterator for ColumnTrieIter<'_> {
fn key(&self) -> Option<usize> {
if let Some(data) = self.rel_data {
data.get(self.rel_data_i).copied()
} else {
None
}
}
fn next(&mut self) -> Option<usize> {
if let Some(data) = self.rel_data {
if self.rel_data_i >= data.len() {
return None;
}
self.rel_data_i += 1;
data.get(self.rel_data_i).copied()
} else {
None
}
}
fn seek(&mut self, seek_key: usize) -> bool {
if self.at_end() {
return false;
}
if let Some(data) = self.rel_data {
let remaining = &data[self.rel_data_i..];
let offset = remaining.partition_point(|&k| k < seek_key);
self.rel_data_i += offset;
!self.at_end()
} else {
false
}
}
fn at_end(&self) -> bool {
if let Some(data) = self.rel_data {
self.rel_data_i >= data.len()
} else {
true
}
}
}
impl TrieIterator for ColumnTrieIter<'_> {
fn open(&mut self) -> bool {
if self.depth == self.trie.header().arity() {
return false;
}
if self.depth == 0 {
let first_layer = self.trie.layer(0);
if first_layer.is_empty() {
return false;
}
self.depth = 1;
self.interval_i = 0;
self.rel_data_i = 0;
self.rel_data = Some(first_layer.child_data(0));
return true;
}
let parent_layer = self.trie.layer(self.depth - 1);
let parent_start = parent_layer.intervals()[self.interval_i];
self.interval_i = parent_start + self.rel_data_i;
self.depth += 1;
let child_layer = self.trie.layer(self.depth - 1);
self.rel_data = Some(child_layer.child_data(self.interval_i));
self.rel_data_i = 0;
true
}
fn up(&mut self) -> bool {
if self.depth == 0 {
return false;
}
if self.depth == 1 {
self.depth = 0;
self.interval_i = 0;
self.rel_data_i = 0;
self.rel_data = None;
return true;
}
self.depth -= 1;
let parent_layer = self.trie.layer(self.depth - 1);
let data_index = self.interval_i;
for (i, &start_index) in parent_layer.intervals().iter().enumerate() {
if data_index < start_index {
break;
}
self.interval_i = i;
}
let parent_start = parent_layer.intervals()[self.interval_i];
self.rel_data = Some(parent_layer.child_data(self.interval_i));
self.rel_data_i = data_index - parent_start;
true
}
}
impl TrieIterable for ColumnTrie {
fn trie_iter(&self) -> impl TrieIterator + IntoIterator<Item = Vec<usize>> {
ColumnTrieIter::new(self)
}
}