use std::{any::type_name, collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}}; use log::debug; use rayon::{iter::{IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, slice::ParallelSliceMut}; use super::matcher::PrefixMatcher; pub type SourceRef = Box; pub type MatcherRef = Box; #[derive(Clone, Debug)] pub struct Entry { pub source: &'static str, pub name: String, pub description: String, pub identifier: u64, } #[derive(Debug)] pub enum Action { Primary, } pub trait Source: Send + Sync { fn name(&self) -> &'static str; fn entries(&mut self) -> Vec; fn action(&self, entry: &Entry, action: Action); } pub trait Matcher: Send + Sync { fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec)>; } pub struct Roftl { sources: Vec, matcher: MatcherRef, entries: Vec, narrow_map: Mutex> } impl Roftl { pub fn new() -> Self { Roftl { sources: vec![], matcher: PrefixMatcher::new(), entries: vec![], narrow_map: Mutex::default() } } pub fn add_source(mut self, source: SourceRef) -> Self { if self.sources.par_iter().any(|s| s.name().eq(source.name())) { panic! {"Source with name '{}' already exists", source.name()} } self.sources.push(source); self } pub fn with_matcher(mut self, matcher: MatcherRef) -> Self { self.matcher = matcher; self } pub fn source(&mut self) { self.entries = self .sources .par_iter_mut() .flat_map(|s| s.entries()) .collect(); println!("Entries {:?}", self.entries); } pub fn narrow(&self, input: &str) -> Vec<&Entry> { let count = Arc::new(AtomicUsize::new(0)); self.narrow_map.lock().unwrap().clear(); let mut scored_entries: Vec<(f64, usize, &Entry, Vec)> = self.entries .par_iter() .enumerate() .filter_map(|(idx, entry)| { let match_result = self.matcher.try_match(&entry.name, input); return match_result.map(|(score, indices)| (score, idx, entry, indices) ) }) .collect(); scored_entries .par_sort_by(|e1, e2| e1.0.partial_cmp(&e2.0).unwrap()); scored_entries .par_iter() .for_each(|se| { self.narrow_map.lock().unwrap().insert(count.fetch_add(1, Ordering::Relaxed), se.1); }); scored_entries .par_iter() .map(|se| se.2) .collect() } pub fn action(&self, entry_id: i32, action: Action) { println!("NarrowMap {:?}", self.narrow_map.lock().unwrap()); let real_id = *self.narrow_map.lock().unwrap().get(&((entry_id-1) as usize)).unwrap(); let entry = self.entries.get(real_id).unwrap(); let source = self .sources .iter() .find(|&s| s.name().eq(entry.source)) .unwrap(); source.action(entry, action); } }