Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat.] Implement cache #3

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flx-rs"
version = "0.1.4"
version = "0.1.5"
authors = ["Jen-Chieh Shen <[email protected]>"]
description = "Rewrite emacs-flx in Rust for dynamic modules"
repository = "https://github.com/jcs090218/flx-rs"
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
mod search;

pub use search::{
get_heatmap_str, find_best_match, score, Score
get_heatmap_str, find_best_match, score, Score, StrInfo
};
65 changes: 51 additions & 14 deletions src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ pub const WORD_SEPARATORS: [u32; 7] = [

const DEFAULT_SCORE: i32 = -35;

#[derive(Clone)]
pub struct StrInfo {
// Generated through get_hash_for_string
hash_for_string: HashMap<Option<u32>, VecDeque<Option<u32>>>,

// Something that get_heatmap_str would return.
heatmap: Vec<i32>,
}

impl StrInfo {
fn new() -> StrInfo {
StrInfo {
hash_for_string: HashMap::new(),
heatmap: Vec::new(),
}
}
}

fn word(char: Option<u32>) -> bool {
if char.is_none() {
return false;
Expand Down Expand Up @@ -85,6 +103,29 @@ fn get_hash_for_string(result: &mut HashMap<Option<u32>, VecDeque<Option<u32>>>,
}
}

fn process_cache(str_info: &mut StrInfo, str: &str, cache: &mut Option<HashMap<String, StrInfo>>) {
if cache.is_none() {
println!("no cache passed in");
get_hash_for_string(&mut str_info.hash_for_string, str);
get_heatmap_str(&mut str_info.heatmap, str, None);
return;
}

let _cache = cache.as_mut().unwrap();

if _cache.contains_key(str) {
println!("found cache");
let data: StrInfo = _cache.get(str).unwrap().clone();
str_info.hash_for_string = data.hash_for_string;
str_info.heatmap = data.heatmap;
} else {
println!("no cache found");
get_hash_for_string(&mut str_info.hash_for_string, str);
get_heatmap_str(&mut str_info.heatmap, str, None);
_cache.insert(str.to_string(), str_info.clone());
}
}

pub fn get_heatmap_str(scores: &mut Vec<i32>, str: &str, group_separator: Option<char>) {
let str_len: usize = str.len();
let str_last_index: usize = str_len - 1;
Expand Down Expand Up @@ -247,8 +288,7 @@ impl Score {
}

pub fn find_best_match(imatch: &mut Vec<Score>,
str_info: HashMap<Option<u32>, VecDeque<Option<u32>>>,
heatmap: Vec<i32>,
str_info: StrInfo,
greater_than: Option<u32>,
query: &str, query_length: i32,
q_index: i32,
Expand All @@ -264,7 +304,7 @@ pub fn find_best_match(imatch: &mut Vec<Score>,
}
} else {
let uchar: Option<u32> = Some(query.chars().nth(q_index as usize).unwrap() as u32);
let sorted_list: Option<&VecDeque<Option<u32>>> = str_info.get(&uchar);
let sorted_list: Option<&VecDeque<Option<u32>>> = str_info.hash_for_string.get(&uchar);
let mut indexes: VecDeque<Option<u32>> = VecDeque::new();
bigger_sublist(&mut indexes, sorted_list, greater_than);
let mut temp_score: i32;
Expand All @@ -277,25 +317,25 @@ pub fn find_best_match(imatch: &mut Vec<Score>,
let mut indices: Vec<i32> = Vec::new();
let _index: i32 = index.unwrap() as i32;
indices.push(_index);
imatch.push(Score::new(indices, heatmap[_index as usize], 0));
imatch.push(Score::new(indices, str_info.heatmap[_index as usize], 0));
}
} else {
for index in indexes {
let _index: i32 = index.unwrap() as i32;
let mut elem_group: Vec<Score> = Vec::new();
find_best_match(&mut elem_group, str_info.clone(), heatmap.clone(), Some(_index as u32), query, query_length, q_index + 1, match_cache);
find_best_match(&mut elem_group, str_info.clone(), Some(_index as u32), query, query_length, q_index + 1, match_cache);

for elem in elem_group {
let caar: i32 = elem.indices[0];
let cadr: i32 = elem.score;
let cddr: i32 = elem.tail;

if (caar - 1) == _index {
temp_score = cadr + heatmap[_index as usize] +
temp_score = cadr + str_info.heatmap[_index as usize] +
(min(cddr, 3) * 15) + // boost contiguous matches
60;
} else {
temp_score = cadr + heatmap[_index as usize];
temp_score = cadr + str_info.heatmap[_index as usize];
}

// We only care about the optimal match, so only forward the match
Expand All @@ -321,21 +361,18 @@ pub fn find_best_match(imatch: &mut Vec<Score>,
}
}

pub fn score(str: &str, query: &str) -> Option<Score> {
pub fn score(str: &str, query: &str , cache: &mut Option<HashMap<String, StrInfo>>) -> Option<Score> {
if str.is_empty() || query.is_empty() {
return None;
}
let mut str_info: HashMap<Option<u32>, VecDeque<Option<u32>>> = HashMap::new();
get_hash_for_string(&mut str_info, str);

let mut heatmap: Vec<i32> = Vec::new();
get_heatmap_str(&mut heatmap, str, None);
let mut str_info: StrInfo = StrInfo::new();
process_cache(&mut str_info, str, cache);

let query_length: i32 = query.len() as i32;
let full_match_boost: bool = (1 < query_length) && (query_length < 5);
let mut match_cache: HashMap<u32, Vec<Score>> = HashMap::new();
let mut optimal_match: Vec<Score> = Vec::new();
find_best_match(&mut optimal_match, str_info, heatmap, None, query, query_length, 0, &mut match_cache);
find_best_match(&mut optimal_match, str_info, None, query, query_length, 0, &mut match_cache);

if optimal_match.is_empty() {
return None;
Expand Down