diff --git a/rust/lib.rs b/rust/lib.rs index a0f0faf..7baaad6 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -1,71 +1,71 @@ mod matcher; mod finder; mod sorter; mod thread_pool; use std::sync::Mutex; use std::collections::HashMap; use std::os::raw::{c_int, c_char}; use std::ffi::CString; use std::ffi::CStr; #[macro_use] extern crate lazy_static; lazy_static! { static ref GLOBAL_FILE_CACHE: Mutex>> = return Mutex::new(HashMap::new()) ; } fn to_string(input: *const c_char) -> String { return unsafe { CStr::from_ptr(input) }.to_str().unwrap().to_string(); } fn get_files(directory: &String) -> Vec { let mut cache = GLOBAL_FILE_CACHE.lock().unwrap(); if !cache.contains_key(directory) { let finder_options = finder::Options{ directory: directory.clone() }; cache.insert( directory.clone(), finder::find_files(finder_options)); } return cache.get(directory).unwrap().to_vec(); } #[no_mangle] pub extern "C" fn ivy_init(c_base_dir: *const c_char) { let directory = to_string(c_base_dir); get_files(&directory); } #[no_mangle] pub extern "C" fn ivy_match(c_pattern: *const c_char, c_text: *const c_char) -> c_int { let pattern = to_string(c_pattern); let text = to_string(c_text); - let m = matcher::Matcher{ pattern }; + let m = matcher::Matcher::new( pattern ); return m.score(text) as i32; } #[no_mangle] pub extern "C" fn ivy_files(c_pattern: *const c_char, c_base_dir: *const c_char) -> *const c_char { let pattern = to_string(c_pattern); let directory = to_string(c_base_dir); // Bail out early if the pattern is empty its never going to find anything if pattern.is_empty() { return CString::new("").unwrap().into_raw() } let files = get_files(&directory); let mut output = String::new(); let sorter_options = sorter::Options::new(pattern); let files = sorter::sort_strings(sorter_options, files); for file in files.lock().unwrap().iter() { output.push_str(&file.content); output.push('\n'); } return CString::new(output).unwrap().into_raw() } diff --git a/rust/matcher.rs b/rust/matcher.rs index 43d364d..28eac59 100644 --- a/rust/matcher.rs +++ b/rust/matcher.rs @@ -1,18 +1,25 @@ use fuzzy_matcher::FuzzyMatcher; use fuzzy_matcher::skim::SkimMatcherV2; pub struct Matcher { /// The search pattern that we want to match against some text pub pattern: String, + matcher: SkimMatcherV2, } impl Matcher { + pub fn new(pattern: String) -> Self { + return Self { + pattern, + matcher: SkimMatcherV2::default(), + } + } + pub fn score(self: &Self, text: String) -> i64 { - let matcher = SkimMatcherV2::default(); - if let Some((score, _indices)) = matcher.fuzzy_indices(&text, &self.pattern) { + if let Some((score, _indices)) = self.matcher.fuzzy_indices(&text, &self.pattern) { return score; } return 0; } } diff --git a/rust/sorter.rs b/rust/sorter.rs index 3bb5c47..eccb179 100644 --- a/rust/sorter.rs +++ b/rust/sorter.rs @@ -1,48 +1,48 @@ use super::matcher; use super::thread_pool; use std::sync::Mutex; use std::sync::Arc; pub struct Match { pub score: i64, pub content: String, } pub struct Options { pub pattern: String, pub minimun_score: i64, } impl Options { pub fn new(pattern: String) -> Self { return Self { pattern, minimun_score: 20 }; } } pub fn sort_strings(options: Options, strings: Vec) -> Arc>> { let matches: Arc>> = Arc::new(Mutex::new(Vec::new())); - let matcher = Arc::new(Mutex::new(matcher::Matcher{ pattern: options.pattern })); + let matcher = Arc::new(Mutex::new(matcher::Matcher::new(options.pattern))); let pool = thread_pool::ThreadPool::new(std::thread::available_parallelism().unwrap().get()); for string in strings { let thread_matcher = Arc::clone(&matcher); let thread_matches = Arc::clone(&matches); pool.execute(move || { let score = thread_matcher.lock().unwrap().score(string.to_string()); if score > 25 { let mut tmp = thread_matches.lock().unwrap(); let content = string.clone(); tmp.push(Match{ score, content }); } }) } drop(pool); matches.lock().unwrap().sort_by(|a, b| a.score.cmp(&b.score)); return matches; }