use std::cmp::Ordering;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
mod r#const;
mod one_shot;
pub mod prefilter;
mod simd;
pub mod smith_waterman;
pub mod sort;
pub use one_shot::{
Matcher, match_list, match_list_indices, match_list_parallel, match_list_parallel_chunked,
match_list_parallel_resolved,
};
pub use r#const::SIMD_CHUNK_BYTES;
use r#const::*;
pub trait Matchable {
fn match_str(&self) -> Option<&str>;
}
impl<T: AsRef<str>> Matchable for T {
#[inline]
fn match_str(&self) -> Option<&str> {
Some(self.as_ref())
}
}
pub trait MatchableChunked {
type Ctx;
fn haystack_info(&self, ctx: &Self::Ctx) -> Option<(usize, u16)>;
fn load_chunk<'a>(&self, ctx: &'a Self::Ctx, index: usize) -> &'a [u8; SIMD_CHUNK_BYTES];
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Match {
pub score: u16,
pub index: u32,
pub exact: bool,
#[cfg(feature = "match_end_col")]
pub end_col: u16,
}
impl Match {
pub fn from_index(index: usize) -> Self {
Self {
score: 0,
index: index as u32,
exact: false,
#[cfg(feature = "match_end_col")]
end_col: 0,
}
}
}
impl PartialOrd for Match {
fn partial_cmp(&self, other: &Match) -> Option<Ordering> {
Some(std::cmp::Ord::cmp(self, other))
}
}
impl Ord for Match {
fn cmp(&self, other: &Self) -> Ordering {
(self.score as u64)
.cmp(&(other.score as u64))
.reverse()
.then_with(|| self.index.cmp(&other.index))
}
}
impl PartialEq for Match {
fn eq(&self, other: &Self) -> bool {
self.score == other.score && self.index == other.index
}
}
impl Eq for Match {}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MatchIndices {
pub score: u16,
pub index: u32,
pub exact: bool,
pub indices: Vec<usize>,
}
impl MatchIndices {
pub fn from_index(index: usize) -> Self {
Self {
score: 0,
index: index as u32,
exact: false,
indices: vec![],
}
}
}
impl PartialOrd for MatchIndices {
fn partial_cmp(&self, other: &MatchIndices) -> Option<Ordering> {
Some(std::cmp::Ord::cmp(self, other))
}
}
impl Ord for MatchIndices {
fn cmp(&self, other: &Self) -> Ordering {
(self.score as u64)
.cmp(&(other.score as u64))
.reverse()
.then_with(|| self.index.cmp(&other.index))
}
}
impl PartialEq for MatchIndices {
fn eq(&self, other: &Self) -> bool {
self.score == other.score && self.index == other.index
}
}
impl Eq for MatchIndices {}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Config {
pub max_typos: Option<u16>,
pub sort: bool,
pub scoring: Scoring,
}
impl Default for Config {
fn default() -> Self {
Config {
max_typos: Some(0),
sort: true,
scoring: Scoring::default(),
}
}
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Scoring {
pub match_score: u16,
pub mismatch_penalty: u16,
pub gap_open_penalty: u16,
pub gap_extend_penalty: u16,
pub prefix_bonus: u16,
pub capitalization_bonus: u16,
pub matching_case_bonus: u16,
pub exact_match_bonus: u16,
pub delimiter_bonus: u16,
}
impl Default for Scoring {
fn default() -> Self {
Scoring {
match_score: MATCH_SCORE,
mismatch_penalty: MISMATCH_PENALTY,
gap_open_penalty: GAP_OPEN_PENALTY,
gap_extend_penalty: GAP_EXTEND_PENALTY,
prefix_bonus: PREFIX_BONUS,
capitalization_bonus: CAPITALIZATION_BONUS,
matching_case_bonus: MATCHING_CASE_BONUS,
exact_match_bonus: EXACT_MATCH_BONUS,
delimiter_bonus: DELIMITER_BONUS,
}
}
}