use crate::core::DocId;
pub trait Scorer: Send {
fn doc_id(&self) -> DocId;
fn next(&mut self) -> DocId;
fn advance(&mut self, target: DocId) -> DocId;
fn score(&mut self) -> f32;
fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator>;
fn max_score(&self) -> f32 {
f32::MAX
}
fn block_max_score(&mut self, _doc: DocId) -> f32 {
self.max_score()
}
fn set_min_competitive_score(&mut self, _min_score: f32) {}
}
pub trait TwoPhaseIterator: Send {
fn matches(&mut self) -> bool;
fn match_cost(&self) -> f32;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::NO_MORE_DOCS;
struct EmptyScorer;
impl Scorer for EmptyScorer {
fn doc_id(&self) -> DocId {
NO_MORE_DOCS
}
fn next(&mut self) -> DocId {
NO_MORE_DOCS
}
fn advance(&mut self, _target: DocId) -> DocId {
NO_MORE_DOCS
}
fn score(&mut self) -> f32 {
0.0
}
fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
None
}
}
struct VecScorer {
docs: Vec<DocId>,
pos: usize,
}
impl VecScorer {
fn new(docs: Vec<DocId>) -> Self {
Self { docs, pos: 0 }
}
fn current(&self) -> DocId {
if self.pos < self.docs.len() {
self.docs[self.pos]
} else {
NO_MORE_DOCS
}
}
}
impl Scorer for VecScorer {
fn doc_id(&self) -> DocId {
self.current()
}
fn next(&mut self) -> DocId {
if self.pos < self.docs.len() {
self.pos += 1;
}
self.current()
}
fn advance(&mut self, target: DocId) -> DocId {
while self.pos < self.docs.len() && self.docs[self.pos] < target {
self.pos += 1;
}
self.current()
}
fn score(&mut self) -> f32 {
1.0
}
fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
None
}
}
#[test]
fn empty_scorer_is_object_safe() {
let scorer: Box<dyn Scorer> = Box::new(EmptyScorer);
assert_eq!(scorer.doc_id(), NO_MORE_DOCS);
}
#[test]
fn empty_scorer_returns_no_more_docs() {
let mut scorer = EmptyScorer;
assert_eq!(scorer.next(), NO_MORE_DOCS);
assert_eq!(scorer.advance(DocId(0)), NO_MORE_DOCS);
}
#[test]
fn vec_scorer_iterates_in_order() {
let mut scorer = VecScorer::new(vec![DocId(1), DocId(5), DocId(10)]);
assert_eq!(scorer.doc_id(), DocId(1));
assert_eq!(scorer.next(), DocId(5));
assert_eq!(scorer.next(), DocId(10));
assert_eq!(scorer.next(), NO_MORE_DOCS);
}
#[test]
fn vec_scorer_advance_skips() {
let mut scorer = VecScorer::new(vec![DocId(1), DocId(5), DocId(10), DocId(20)]);
assert_eq!(scorer.advance(DocId(5)), DocId(5));
assert_eq!(scorer.advance(DocId(15)), DocId(20));
assert_eq!(scorer.advance(DocId(21)), NO_MORE_DOCS);
}
#[test]
fn vec_scorer_advance_past_end() {
let mut scorer = VecScorer::new(vec![DocId(1), DocId(2)]);
assert_eq!(scorer.advance(DocId(100)), NO_MORE_DOCS);
}
#[test]
fn vec_scorer_default_max_score() {
let scorer = VecScorer::new(vec![]);
assert_eq!(scorer.max_score(), f32::MAX);
}
}