76 lines
2.1 KiB
Rust
76 lines
2.1 KiB
Rust
|
pub mod mtg;
|
||
|
pub mod yugioh;
|
||
|
|
||
|
use Link;
|
||
|
use std::any::Any;
|
||
|
use std::collections::BTreeMap;
|
||
|
|
||
|
pub trait Searcher<T: Link> {
|
||
|
fn fuzzy_search (&self, name: &str) -> Option<T> {
|
||
|
self.exact_search(name)
|
||
|
}
|
||
|
|
||
|
fn exact_search (&self, name: &str) -> Option<T>;
|
||
|
}
|
||
|
|
||
|
type SearchFn = Box<Fn(String, bool) -> Option<Box<Link>>>;
|
||
|
pub struct AggregateSearcher {
|
||
|
searchers: BTreeMap<String, SearchFn>
|
||
|
}
|
||
|
|
||
|
impl AggregateSearcher {
|
||
|
pub fn new () -> AggregateSearcher {
|
||
|
AggregateSearcher {
|
||
|
searchers: BTreeMap::new()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn add_searcher<T: Link + 'static> (&mut self, prefix: &str, searcher: Box<Searcher<T>>) {
|
||
|
let searcher_closure = move |name: String, fuzzy: bool| {
|
||
|
(if fuzzy {
|
||
|
searcher.fuzzy_search(&name[..])
|
||
|
} else {
|
||
|
searcher.exact_search(&name[..])
|
||
|
}).map(|value| Box::new(value) as Box<Link>)
|
||
|
};
|
||
|
|
||
|
self.searchers.insert(String::from(prefix), Box::new(searcher_closure));
|
||
|
}
|
||
|
|
||
|
fn run_all_searchers (&self, name: &str) -> Option<Box<Link>> {
|
||
|
for (_, searcher) in &self.searchers {
|
||
|
let possible_value = searcher(String::from(name), false);
|
||
|
if possible_value.is_some() {
|
||
|
return possible_value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Searcher<Box<Link>> for AggregateSearcher {
|
||
|
fn exact_search (&self, full_name: &str) -> Option<Box<Link>> {
|
||
|
match split_prefix(full_name, ":") {
|
||
|
Some((prefix, name)) => {
|
||
|
self.searchers.get(prefix).and_then(|searcher| searcher(String::from(name), true))
|
||
|
.or_else(|| self.run_all_searchers(full_name))
|
||
|
},
|
||
|
None => {
|
||
|
self.run_all_searchers(full_name)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn split_prefix<'a> (input: &'a str, separator: &str) -> Option<(&'a str, &'a str)> {
|
||
|
if input.contains(separator) {
|
||
|
match input.split(separator).into_iter().next() {
|
||
|
Some(prefix) => { Some((prefix, input[prefix.len() + separator.len() ..].trim())) },
|
||
|
None => None
|
||
|
}
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|