use fixedbitset::FixedBitSet;
use std::io;
pub const NO_MORE_DOCS: i32 = i32::MAX;
pub trait DocIdSetIterator {
fn doc_id(&self) -> i32;
fn next_doc(&mut self) -> io::Result<i32>;
fn advance(&mut self, target: i32) -> io::Result<i32>;
fn cost(&self) -> i64;
fn doc_id_run_end(&self) -> io::Result<i32> {
Ok(self.doc_id() + 1)
}
fn fill_bit_set(
&mut self,
up_to: i32,
bit_set: &mut FixedBitSet,
offset: i32,
) -> io::Result<()> {
debug_assert!(offset <= self.doc_id());
let mut doc = self.doc_id();
while doc < up_to {
bit_set.insert((doc - offset) as usize);
doc = self.next_doc()?;
}
Ok(())
}
}
pub fn slow_advance(iter: &mut dyn DocIdSetIterator, target: i32) -> io::Result<i32> {
debug_assert!(iter.doc_id() < target);
let mut doc;
loop {
doc = iter.next_doc()?;
if doc >= target {
break;
}
}
Ok(doc)
}
pub fn empty() -> RangeDocIdSetIterator {
RangeDocIdSetIterator::new(0, 0)
}
pub fn all(max_doc: i32) -> RangeDocIdSetIterator {
assert!(
max_doc >= 0,
"maxDoc must be >= 0, but got maxDoc={}",
max_doc
);
RangeDocIdSetIterator::new(0, max_doc)
}
pub fn range(min_doc: i32, max_doc: i32) -> RangeDocIdSetIterator {
assert!(
min_doc < max_doc,
"minDoc must be < maxDoc but got minDoc={} maxDoc={}",
min_doc,
max_doc
);
assert!(
min_doc >= 0,
"minDoc must be >= 0 but got minDoc={}",
min_doc
);
RangeDocIdSetIterator::new(min_doc, max_doc)
}
#[derive(Debug)]
pub struct RangeDocIdSetIterator {
min_doc: i32,
max_doc: i32,
doc: i32,
}
impl RangeDocIdSetIterator {
fn new(min_doc: i32, max_doc: i32) -> Self {
debug_assert!(min_doc <= max_doc);
Self {
min_doc,
max_doc,
doc: -1,
}
}
}
impl DocIdSetIterator for RangeDocIdSetIterator {
fn doc_id(&self) -> i32 {
self.doc
}
fn next_doc(&mut self) -> io::Result<i32> {
self.advance(self.doc + 1)
}
fn advance(&mut self, target: i32) -> io::Result<i32> {
if target >= self.max_doc {
self.doc = NO_MORE_DOCS;
} else if target < self.min_doc {
self.doc = self.min_doc;
} else {
self.doc = target;
}
Ok(self.doc)
}
fn cost(&self) -> i64 {
(self.max_doc - self.min_doc) as i64
}
fn doc_id_run_end(&self) -> io::Result<i32> {
Ok(self.max_doc)
}
fn fill_bit_set(
&mut self,
up_to: i32,
bit_set: &mut FixedBitSet,
offset: i32,
) -> io::Result<()> {
debug_assert!(offset <= self.doc);
let up_to = up_to.min(self.max_doc);
if up_to > self.doc {
let from = (self.doc - offset) as usize;
let to = (up_to - offset) as usize;
bit_set.insert_range(from..to);
self.advance(up_to)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty() {
let mut disi = empty();
assert_eq!(disi.doc_id(), -1);
assert_eq!(disi.next_doc().unwrap(), NO_MORE_DOCS);
assert_eq!(disi.doc_id(), NO_MORE_DOCS);
let mut disi = empty();
assert_eq!(disi.doc_id(), -1);
assert_eq!(disi.advance(42).unwrap(), NO_MORE_DOCS);
assert_eq!(disi.doc_id(), NO_MORE_DOCS);
}
#[test]
fn test_range_basic() {
let mut disi = range(5, 8);
assert_eq!(disi.doc_id(), -1);
assert_eq!(disi.next_doc().unwrap(), 5);
assert_eq!(disi.next_doc().unwrap(), 6);
assert_eq!(disi.next_doc().unwrap(), 7);
assert_eq!(disi.next_doc().unwrap(), NO_MORE_DOCS);
}
#[test]
#[should_panic(expected = "minDoc must be < maxDoc")]
fn test_invalid_range() {
range(5, 4);
}
#[test]
#[should_panic(expected = "minDoc must be >= 0")]
fn test_invalid_range_min() {
range(-1, 4);
}
#[test]
#[should_panic(expected = "minDoc must be < maxDoc")]
fn test_empty_range() {
range(7, 7);
}
#[test]
fn test_range_advance() {
let mut disi = range(5, 20);
assert_eq!(disi.doc_id(), -1);
assert_eq!(disi.next_doc().unwrap(), 5);
assert_eq!(disi.advance(17).unwrap(), 17);
assert_eq!(disi.next_doc().unwrap(), 18);
assert_eq!(disi.next_doc().unwrap(), 19);
assert_eq!(disi.next_doc().unwrap(), NO_MORE_DOCS);
}
#[test]
fn test_all_basic() {
let mut disi = all(3);
assert_eq!(disi.doc_id(), -1);
assert_eq!(disi.next_doc().unwrap(), 0);
assert_eq!(disi.next_doc().unwrap(), 1);
assert_eq!(disi.next_doc().unwrap(), 2);
assert_eq!(disi.next_doc().unwrap(), NO_MORE_DOCS);
}
#[test]
fn test_all_cost() {
let disi = all(100);
assert_eq!(disi.cost(), 100);
}
#[test]
fn test_range_cost() {
let disi = range(5, 20);
assert_eq!(disi.cost(), 15);
}
#[test]
fn test_doc_id_run_end_all() {
let mut it = all(13);
assert_eq!(it.next_doc().unwrap(), 0);
assert_eq!(it.doc_id_run_end().unwrap(), 13);
assert_eq!(it.advance(10).unwrap(), 10);
assert_eq!(it.doc_id_run_end().unwrap(), 13);
assert_eq!(it.advance(13).unwrap(), NO_MORE_DOCS);
}
#[test]
fn test_doc_id_run_end_range() {
let mut it = range(4, 13);
assert_eq!(it.next_doc().unwrap(), 4);
assert_eq!(it.doc_id_run_end().unwrap(), 13);
assert_eq!(it.advance(10).unwrap(), 10);
assert_eq!(it.doc_id_run_end().unwrap(), 13);
assert_eq!(it.advance(13).unwrap(), NO_MORE_DOCS);
}
#[test]
fn test_slow_advance() {
let mut disi = range(0, 100);
disi.next_doc().unwrap(); let result = slow_advance(&mut disi, 50).unwrap();
assert_eq!(result, 50);
assert_eq!(disi.doc_id(), 50);
}
#[test]
fn test_advance_before_range() {
let mut disi = range(10, 20);
assert_eq!(disi.advance(5).unwrap(), 10);
assert_eq!(disi.doc_id(), 10);
}
#[test]
fn test_advance_past_range() {
let mut disi = range(10, 20);
assert_eq!(disi.advance(25).unwrap(), NO_MORE_DOCS);
assert_eq!(disi.doc_id(), NO_MORE_DOCS);
}
#[test]
#[should_panic(expected = "maxDoc must be >= 0")]
fn test_all_negative_max_doc() {
all(-1);
}
#[test]
fn test_empty_cost() {
let disi = empty();
assert_eq!(disi.cost(), 0);
}
}