From a4ae7531a359afd7f6e840c552fec0d006ddaea0 Mon Sep 17 00:00:00 2001 From: Adrian Heine Date: Wed, 10 May 2017 10:54:29 +0200 Subject: [PATCH] More Repos and Runners --- src/repository.rs | 33 ++++++++++++++++++++++++++++++--- src/schema.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/repository.rs b/src/repository.rs index 25a01a2..c980ee0 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -1,4 +1,5 @@ -use std::collections::HashMap; +use std::cell::RefCell; +use std::collections::{HashMap, HashSet}; use symbols::Symbol; use resources::Resource; @@ -14,11 +15,11 @@ impl<'a, C> SymbolRepository<'a> for C where C: Fn(&Resource) -> Option { - repositories: HashMap<&'a str, Box + 'a>> + repositories: HashMap<&'static str, Box>> } impl<'a> DispatchingSymbolRepository<'a> { - pub fn new(repositories: HashMap<&'a str, Box + 'a>>) -> DispatchingSymbolRepository<'a> { + pub fn new(repositories: HashMap<&'static str, Box>>) -> DispatchingSymbolRepository<'a> { DispatchingSymbolRepository { repositories: repositories } } } @@ -28,3 +29,29 @@ impl<'a> SymbolRepository<'a> for DispatchingSymbolRepository<'a> { 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) + } + } +} diff --git a/src/schema.rs b/src/schema.rs index 560e6e1..894e3ef 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -2,6 +2,7 @@ use std::error::Error; use std::fmt; use loggers::Logger; +use repository::SymbolRepository; use symbols::Symbol; #[derive(Debug)] @@ -74,6 +75,51 @@ impl SymbolRunner for DrySymbolRunner { } } +pub struct ReportingSymbolRunner<'a, R: 'a + SymbolRunner>(&'a R); + +impl<'a, R> ReportingSymbolRunner<'a, R> where R: SymbolRunner { + pub fn new(symbol_runner: &'a R) -> Self { + ReportingSymbolRunner(symbol_runner) + } +} + +impl<'a, R> SymbolRunner for ReportingSymbolRunner<'a, R> where R: SymbolRunner { + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> + { + logger.debug(format!("Running symbol {}", symbol).as_str()); + let res = self.0.run_symbol(logger, symbol); + match &res { + &Err(ref e) => { + logger.write(format!("Failed on {} with {}, aborting.", symbol, e).as_str()); + }, + &Ok(_) => { + logger.debug(format!("Successfully finished {}", symbol).as_str()); + } + } + res + } +} + +pub struct RequirementsResolvingSymbolRunner<'s, R: 's + SymbolRunner, G: 's + SymbolRepository<'s>>(&'s R, &'s G); + +impl<'s, R, G> RequirementsResolvingSymbolRunner<'s, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { + pub fn new(symbol_runner: &'s R, symbol_repo: &'s G) -> Self { + RequirementsResolvingSymbolRunner(symbol_runner, symbol_repo) + } +} + +impl<'s, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'s, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> + { + for resource in symbol.get_prerequisites() { + if let Some(dep) = self.1.get_symbol(&resource) { + try!(self.run_symbol(logger, &*dep)); + } + } + self.0.run_symbol(logger, &*symbol) + } +} + // FIXME: Add ExpectingSymbolRunner #[cfg(test)]