neek-core 1.0.0

Core fuzzy matching and scoring engine
Documentation
//! Per-position bonus lookup tables.
use crate::config::{
  SCORE_MATCH_CAPITAL,
  SCORE_MATCH_DOT,
  SCORE_MATCH_SLASH,
  SCORE_MATCH_WORD,
};

/// Look up the "state" index for a character.
///
/// - `0`: non-alphanumeric (punctuation, NUL, high bytes)
/// - `1`: lowercase letter or digit
/// - `2`: uppercase letter
const fn build_bonus_index() -> [u8; 256] {
  let mut t = [0u8; 256];
  let mut c = b'a';
  while c <= b'z' {
    t[c as usize] = 1;
    c += 1;
  }
  let mut c = b'0';
  while c <= b'9' {
    t[c as usize] = 1;
    c += 1;
  }
  let mut c = b'A';
  while c <= b'Z' {
    t[c as usize] = 2;
    c += 1;
  }
  t
}

pub(crate) const BONUS_INDEX: [u8; 256] = build_bonus_index();

const fn build_bonus_states() -> [[f64; 256]; 3] {
  let mut t = [[0f64; 256]; 3];

  t[1][b'/' as usize] = SCORE_MATCH_SLASH;
  t[1][b'-' as usize] = SCORE_MATCH_WORD;
  t[1][b'_' as usize] = SCORE_MATCH_WORD;
  t[1][b' ' as usize] = SCORE_MATCH_WORD;
  t[1][b'.' as usize] = SCORE_MATCH_DOT;

  t[2][b'/' as usize] = SCORE_MATCH_SLASH;
  t[2][b'-' as usize] = SCORE_MATCH_WORD;
  t[2][b'_' as usize] = SCORE_MATCH_WORD;
  t[2][b' ' as usize] = SCORE_MATCH_WORD;
  t[2][b'.' as usize] = SCORE_MATCH_DOT;

  let mut c = b'a';
  while c <= b'z' {
    t[2][c as usize] = SCORE_MATCH_CAPITAL;
    c += 1;
  }

  t
}

pub(crate) const BONUS_STATES: [[f64; 256]; 3] = build_bonus_states();

/// Compute the positional bonus for a match at `ch`, given that the preceding
/// haystack character was `prev`.
#[inline(always)]
pub(crate) fn compute_bonus(prev: u8, ch: u8) -> f64 {
  BONUS_STATES[BONUS_INDEX[ch as usize] as usize][prev as usize]
}