use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use symbols::Symbol; use resources::Resource; pub trait SymbolRepository<'a> { fn get_symbol(&self, resource: &Resource) -> Option>; } impl<'a, C> SymbolRepository<'a> for C where C: Fn(&Resource) -> Option> { fn get_symbol(&self, resource: &Resource) -> Option> { self(resource) } } pub struct DispatchingSymbolRepository<'a> { repositories: HashMap<&'static str, Box>> } impl<'a> DispatchingSymbolRepository<'a> { pub fn new(repositories: HashMap<&'static str, Box>>) -> DispatchingSymbolRepository<'a> { DispatchingSymbolRepository { repositories: repositories } } } impl<'a> SymbolRepository<'a> for DispatchingSymbolRepository<'a> { fn get_symbol(&self, resource: &Resource) -> Option> { self.repositories.get(resource.get_type()).and_then(|repo| repo.get_symbol(resource)) } } use std::marker::PhantomData; pub struct NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { upstream: R, done: RefCell>, d: PhantomData> } impl<'a, R> NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { pub fn new(repository: R) -> Self { NonRepeatingSymbolRepository { upstream: repository, done: RefCell::new(HashSet::new()), d: PhantomData } } } impl<'a, R> SymbolRepository<'a> for NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { fn get_symbol(&self, resource: &Resource) -> Option> { let mut done = self.done.borrow_mut(); if done.contains(&resource) { None } else { done.insert(resource.clone()); self.upstream.get_symbol(resource) } } }