use std::collections::BinaryHeap;
use crate::MeasuredPrefix;
#[cfg(feature = "fst")]
pub mod fst;
pub mod meta;
pub trait Autocompleter {
const NAME: &'static str;
type STATE: Default = ();
fn threshold_topk(
&self,
query: &str,
requested: usize,
max_threshold: usize,
state: &mut Self::STATE,
) -> Vec<MeasuredPrefix>;
fn autocomplete(
&self,
query: &str,
requested: usize,
state: &mut Self::STATE,
) -> Vec<MeasuredPrefix> {
self.threshold_topk(query, requested, 4, state)
}
}
pub trait FromStrings {
fn from_strings(strings: &[&str]) -> Self;
}
#[derive(PartialEq, Eq, Clone, Debug)]
struct PrefixRanking {
string: String,
prefix_distance: usize,
}
impl Ord for PrefixRanking {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.prefix_distance.cmp(&other.prefix_distance)
}
}
impl PartialOrd for PrefixRanking {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<PrefixRanking> for MeasuredPrefix {
fn from(value: PrefixRanking) -> Self {
let PrefixRanking {
string,
prefix_distance,
} = value;
MeasuredPrefix {
string,
prefix_distance,
}
}
}
#[derive(Clone, Default)]
pub struct PrefixRankings {
best: BinaryHeap<PrefixRanking>,
limit: usize,
max_ped: usize,
}
impl PrefixRankings {
fn threshold(&self) -> Option<usize> {
if self.best.len() < self.limit as usize {
Some(self.max_ped)
}
else {
let worst = self.best.peek().unwrap().prefix_distance;
if worst == 0 {
None
} else {
Some(worst - 1)
}
}
}
fn new(limit: usize, max_ped: usize) -> PrefixRankings {
PrefixRankings {
best: Default::default(),
limit,
max_ped,
}
}
fn consider(&mut self, measure: PrefixRanking) {
if measure.prefix_distance <= self.max_ped {
self.best.push(measure);
if self.best.len() > self.limit {
self.best.pop();
}
}
}
pub fn into_measures(self) -> Vec<MeasuredPrefix> {
let mut measures: Vec<MeasuredPrefix> = self
.best
.into_sorted_vec()
.into_iter()
.map(Into::into)
.collect();
measures.sort();
measures
}
pub fn into_strings(self) -> Vec<String> {
self.into_measures()
.into_iter()
.map(|measure| measure.string)
.collect()
}
}