use std::iter::FusedIterator;
use crate::common::types::PointOffsetType;
use crate::posting_list::PostingElement;
use crate::posting_list::value_handler::PostingValue;
use crate::posting_list::visitor::PostingVisitor;
pub struct PostingIterator<'a, V: PostingValue> {
visitor: PostingVisitor<'a, V>,
current_elem: Option<PostingElement<V>>,
offset: usize,
}
impl<'a, V: PostingValue> PostingIterator<'a, V> {
pub fn new(visitor: PostingVisitor<'a, V>) -> Self {
Self {
visitor,
current_elem: None,
offset: 0,
}
}
pub fn advance_until_greater_or_equal(
&mut self,
target_id: PointOffsetType,
) -> Option<PostingElement<V>> {
if let Some(current) = &self.current_elem
&& current.id >= target_id
{
return Some(current.clone());
}
if self.offset >= self.visitor.len() {
return None;
}
let Some(offset) = self
.visitor
.search_greater_or_equal(target_id, Some(self.offset))
else {
self.current_elem = None;
self.offset = self.visitor.len();
return None;
};
debug_assert!(offset >= self.offset);
let greater_or_equal = self.visitor.get_by_offset(offset);
self.current_elem = greater_or_equal.clone();
self.offset = offset;
greater_or_equal
}
}
impl<V: PostingValue> Iterator for PostingIterator<'_, V> {
type Item = PostingElement<V>;
fn next(&mut self) -> Option<Self::Item> {
let next_opt = self.visitor.get_by_offset(self.offset).inspect(|_| {
self.offset += 1;
});
self.current_elem = next_opt.clone();
next_opt
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining_len = self.len();
(remaining_len, Some(remaining_len))
}
fn count(self) -> usize {
self.size_hint().0
}
}
impl<V: PostingValue> ExactSizeIterator for PostingIterator<'_, V> {
fn len(&self) -> usize {
self.visitor.list.len().saturating_sub(self.offset)
}
}
impl<V: PostingValue> FusedIterator for PostingIterator<'_, V> {}