Skip to content

Commit

Permalink
fzf: add FzfParser
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Oct 27, 2023
1 parent 1af8890 commit 8c2b47a
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 50 deletions.
12 changes: 8 additions & 4 deletions benches/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ use criterion::{
use norm::CaseSensitivity;

pub trait Metric {
type Query<'a>: Copy + FromStr<'a>;
type Query<'a>: Copy;

type Parser: Parser<Self>;

fn dist(&mut self, query: Self::Query<'_>, candidate: &str);
fn with_case_sensitivity(self, case_sensitivity: CaseSensitivity) -> Self;
fn with_matched_ranges(self, matched_ranges: bool) -> Self;
}

pub trait FromStr<'a> {
fn from_str(s: &'a str) -> Self;
pub trait Parser<M: Metric + ?Sized>: Default {
fn parse<'a>(&'a mut self, s: &str) -> M::Query<'a>;
}

// TODO: docs
Expand Down Expand Up @@ -85,7 +87,9 @@ fn bench<'a, M, C>(
C: IntoIterator<Item = &'a str>,
C::IntoIter: ExactSizeIterator + Clone,
{
let query = M::Query::from_str(query);
let mut parser = M::Parser::default();

let query = parser.parse(query);

let candidates = candidates.into_iter();

Expand Down
10 changes: 6 additions & 4 deletions benches/fzf_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ use criterion::{
Criterion,
};
use norm::{
fzf::{FzfQuery, FzfV1},
fzf::{FzfParser, FzfQuery, FzfV1},
CaseSensitivity,
Metric,
};

impl<'a> bench::FromStr<'a> for FzfQuery<'a> {
fn from_str(s: &'a str) -> Self {
FzfQuery::new(s)
impl bench::Parser<FzfV1> for FzfParser {
fn parse<'a>(&'a mut self, s: &str) -> FzfQuery<'a> {
self.parse(s)
}
}

impl bench::Metric for FzfV1 {
type Query<'a> = FzfQuery<'a>;

type Parser = FzfParser;

#[inline]
fn dist(&mut self, query: FzfQuery, candidate: &str) {
self.distance(query, candidate);
Expand Down
10 changes: 6 additions & 4 deletions benches/fzf_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ use criterion::{
Criterion,
};
use norm::{
fzf::{FzfQuery, FzfV2},
fzf::{FzfParser, FzfQuery, FzfV2},
CaseSensitivity,
Metric,
};

impl<'a> bench::FromStr<'a> for FzfQuery<'a> {
fn from_str(s: &'a str) -> Self {
FzfQuery::new(s)
impl bench::Parser<FzfV2> for FzfParser {
fn parse<'a>(&'a mut self, s: &str) -> FzfQuery<'a> {
self.parse(s)
}
}

impl bench::Metric for FzfV2 {
type Query<'a> = FzfQuery<'a>;

type Parser = FzfParser;

#[inline]
fn dist(&mut self, query: FzfQuery, candidate: &str) {
self.distance(query, candidate);
Expand Down
2 changes: 2 additions & 0 deletions src/algos/fzf/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! TODO: docs
mod distance;
mod parser;
mod query;
mod scheme;
mod scoring;
Expand All @@ -11,6 +12,7 @@ mod v1;
mod v2;

pub use distance::FzfDistance;
pub use parser::FzfParser;
pub use query::FzfQuery;
pub use scheme::FzfScheme;
use scheme::Scheme;
Expand Down
32 changes: 32 additions & 0 deletions src/algos/fzf/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use super::FzfQuery;

/// TODO: docs
#[derive(Default, Clone)]
pub struct FzfParser {
vec: Vec<char>,
}

impl FzfParser {
/// TODO: docs
#[inline]
pub fn parse<'a>(&'a mut self, query: &str) -> FzfQuery<'a> {
if query.len() > self.vec.len() {
self.vec.resize(query.len(), '\0');
}

let mut char_len = 0;

for ch in query.chars() {
self.vec[char_len] = ch;
char_len += 1;
}

FzfQuery::new(&self.vec[..char_len])
}

/// TODO: docs
#[inline]
pub fn new() -> Self {
Self::default()
}
}
34 changes: 28 additions & 6 deletions src/algos/fzf/query.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
/// TODO: docs.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy)]
pub struct FzfQuery<'a> {
/// TODO: docs.
raw: &'a str,
chars: &'a [char],
}

impl core::fmt::Debug for FzfQuery<'_> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let s = self.chars.iter().collect::<String>();
f.debug_tuple("FzfQuery").field(&s).finish()
}
}

impl<'a> FzfQuery<'a> {
/// TODO: docs
#[inline]
pub fn new(s: &'a str) -> Self {
Self { raw: s }
pub(super) fn char_len(&self) -> usize {
self.chars.len()
}

/// TODO: docs
#[inline]
pub(crate) fn chars(
&self,
) -> impl Iterator<Item = char> + DoubleEndedIterator + '_ {
self.chars.iter().copied()
}

/// TODO: docs
#[inline]
pub(super) fn is_empty(&self) -> bool {
self.chars.is_empty()
}

/// TODO: docs
#[inline]
pub(super) fn raw(&self) -> &'a str {
self.raw
pub(super) fn new(chars: &'a [char]) -> Self {
Self { chars }
}
}
14 changes: 7 additions & 7 deletions src/algos/fzf/slab.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::ops::{Index, IndexMut, Range};

use super::Score;
use super::{FzfQuery, Score};

/// TODO: docs
#[derive(Clone, Default)]
Expand Down Expand Up @@ -167,8 +167,8 @@ impl Default for MatchedIndicesSlab {
impl MatchedIndicesSlab {
#[inline]
/// TODO: docs
pub fn alloc<'a>(&'a mut self, query: &str) -> MatchedIndices<'a> {
let char_len = query.chars().count();
pub fn alloc<'a>(&'a mut self, query: FzfQuery) -> MatchedIndices<'a> {
let char_len = query.char_len();

if char_len > self.vec.len() {
self.vec.resize(char_len, CandidateCharIdx(0));
Expand Down Expand Up @@ -325,10 +325,10 @@ impl ConsecutiveMatrixSlab {
#[inline]
pub fn alloc<'a>(
&'a mut self,
query: &str,
query: FzfQuery,
candidate: Candidate,
) -> Matrix<'a, usize> {
let height = query.chars().count();
let height = query.char_len();
let width = candidate.char_len();
self.slab.alloc(width, height)
}
Expand All @@ -345,10 +345,10 @@ impl ScoringMatrixSlab {
#[inline]
pub fn alloc<'a>(
&'a mut self,
query: &str,
query: FzfQuery,
candidate: Candidate,
) -> Matrix<'a, Score> {
let height = query.chars().count();
let height = query.char_len();
let width = candidate.char_len();
self.slab.alloc(width, height)
}
Expand Down
12 changes: 5 additions & 7 deletions src/algos/fzf/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,9 @@ impl Metric for FzfV1 {
#[inline]
fn distance(
&mut self,
query: FzfQuery<'_>, // helwo
candidate: &str, // Hello World!
query: FzfQuery<'_>,
candidate: &str,
) -> Option<Match<Self::Distance>> {
let query = query.raw();

if query.is_empty() {
return None;
}
Expand Down Expand Up @@ -96,7 +94,7 @@ impl Metric for FzfV1 {
/// TODO: docs
#[inline]
fn forward_pass(
query: &str,
query: FzfQuery,
candidate: &str,
case_matcher: &CaseMatcher,
) -> Option<Range<usize>> {
Expand Down Expand Up @@ -135,7 +133,7 @@ fn forward_pass(
/// TODO: docs
#[inline]
fn backward_pass(
query: &str,
query: FzfQuery,
candidate: &str,
case_matcher: &CaseMatcher,
) -> usize {
Expand Down Expand Up @@ -174,7 +172,7 @@ fn backward_pass(
/// TODO: docs
#[inline]
fn calculate_score(
query: &str,
query: FzfQuery,
candidate: &str,
range: Range<usize>,
scheme: &Scheme,
Expand Down
11 changes: 4 additions & 7 deletions src/algos/fzf/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ impl Metric for FzfV2 {
query: FzfQuery<'_>,
candidate: &str,
) -> Option<Match<Self::Distance>> {
let query = query.raw();

if query.is_empty() {
return None;
}
Expand Down Expand Up @@ -105,8 +103,8 @@ impl Metric for FzfV2 {
fn matched_indices<'idx, 'bonus>(
indices_slab: &'idx mut MatchedIndicesSlab,
bonuses_slab: &'bonus mut BonusVectorSlab,
query: &str,
candidate: Candidate<'_>,
query: FzfQuery,
candidate: Candidate,
case_matcher: &CaseMatcher,
scheme: &Scheme,
) -> Option<(MatchedIndices<'idx>, BonusVector<'bonus>)> {
Expand Down Expand Up @@ -136,8 +134,7 @@ fn matched_indices<'idx, 'bonus>(
}
}

// TODO: use query.char_len()
if matched_idxs.len() == query.chars().count() {
if matched_idxs.len() == query.char_len() {
Some((matched_idxs, bonuses))
} else {
None
Expand All @@ -149,7 +146,7 @@ fn matched_indices<'idx, 'bonus>(
fn score<'scoring>(
scoring_slab: &'scoring mut ScoringMatrixSlab,
consecutive_slab: &mut ConsecutiveMatrixSlab,
query: &str,
query: FzfQuery,
candidate: Candidate,
matched_indices: MatchedIndices,
bonus_vector: BonusVector,
Expand Down
4 changes: 3 additions & 1 deletion src/case_sensitivity.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::fzf::FzfQuery;

/// TODO: docs
#[derive(Copy, Clone, Debug, Default)]
pub enum CaseSensitivity {
Expand All @@ -15,7 +17,7 @@ pub enum CaseSensitivity {
impl CaseSensitivity {
/// TODO: docs
#[inline]
pub(crate) fn matcher(self, query: &str) -> CaseMatcher {
pub(crate) fn matcher(self, query: FzfQuery) -> CaseMatcher {
let matcher = match self {
Self::Sensitive => case_sensitive_eq,

Expand Down
10 changes: 5 additions & 5 deletions tests/fzf_v1.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use norm::fzf::{bonus, penalty, FzfQuery, FzfV1};
use norm::fzf::{bonus, penalty, FzfParser, FzfV1};
use norm::{CaseSensitivity, Metric};

#[test]
fn fzf_v1_empty_query() {
let mut fzf = FzfV1::new();
let empty = FzfQuery::new("");
assert!(fzf.distance(empty, "foo").is_none());
let mut parser = FzfParser::new();
assert!(fzf.distance(parser.parse(""), "foo").is_none());
}

#[test]
Expand All @@ -14,9 +14,9 @@ fn fzf_v1_score_1() {
.with_case_sensitivity(CaseSensitivity::Insensitive)
.with_matched_ranges(true);

let query = FzfQuery::new("oBZ");
let mut parser = FzfParser::new();

let mach = fzf.distance(query, "fooBarbaz").unwrap();
let mach = fzf.distance(parser.parse("oBZ"), "fooBarbaz").unwrap();

assert_eq!(
mach.distance().into_score(),
Expand Down
10 changes: 5 additions & 5 deletions tests/fzf_v2.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use norm::fzf::{bonus, penalty, FzfQuery, FzfV2};
use norm::fzf::{bonus, penalty, FzfParser, FzfV2};
use norm::{CaseSensitivity, Metric};

#[test]
fn fzf_v2_empty_query() {
let mut fzf = FzfV2::new();
let empty = FzfQuery::new("");
assert!(fzf.distance(empty, "foo").is_none());
let mut parser = FzfParser::new();
assert!(fzf.distance(parser.parse(""), "foo").is_none());
}

#[test]
Expand All @@ -14,9 +14,9 @@ fn fzf_v2_score_1() {
.with_case_sensitivity(CaseSensitivity::Insensitive)
.with_matched_ranges(true);

let query = FzfQuery::new("oBZ");
let mut parser = FzfParser::new();

let mach = fzf.distance(query, "fooBarbaz").unwrap();
let mach = fzf.distance(parser.parse("oBZ"), "fooBarbaz").unwrap();

assert_eq!(
mach.distance().into_score(),
Expand Down

0 comments on commit 8c2b47a

Please sign in to comment.