use std::error::Error; use std::fmt; use resources::Resource; use symbols::{Action, Symbol, SymbolRunner}; pub struct List<'a> { symbols: Vec>, } impl<'a> List<'a> { pub fn new(symbols: Vec>) -> Self { List { symbols } } } impl<'a> Symbol for List<'a> { fn target_reached(&self) -> Result> { for symbol in &self.symbols { if !symbol.target_reached()? { return Ok(false); } } Ok(true) } fn execute(&self) -> Result<(), Box> { for symbol in &self.symbols { symbol.execute()?; } Ok(()) } fn get_prerequisites(&self) -> Vec { let mut r = vec![]; for symbol in &self.symbols { for req in symbol.get_prerequisites() { if self.provides().map_or(true, |p| !p.contains(&req)) { r.push(req) } } } r } fn provides(&self) -> Option> { let mut r = vec![]; for symbol in &self.symbols { if let Some(provides) = symbol.provides() { r.extend(provides.into_iter()); } } if r.is_empty() { None } else { Some(r) } } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolListAction::new(runner, &self.symbols)) } fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b, { Box::new(ListAction::new( self .symbols .into_iter() .map(|s| s.into_action(runner)) .collect(), )) } } impl<'a, A: 'a + Symbol, B: 'a + Symbol> From<(A, B)> for List<'a> { fn from((a, b): (A, B)) -> Self { Self::new(vec![Box::new(a), Box::new(b)]) } } impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol> From<(A, B, C)> for List<'a> { fn from((a, b, c): (A, B, C)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol> From<(A, B, C, D)> for List<'a> { fn from((a, b, c, d): (A, B, C, D)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol> From<(A, B, C, D, E)> for List<'a> { fn from((a, b, c, d, e): (A, B, C, D, E)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol> From<(A, B, C, D, E, F)> for List<'a> { fn from((a, b, c, d, e, f): (A, B, C, D, E, F)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol> From<(A, B, C, D, E, F, G)> for List<'a> { fn from((a, b, c, d, e, f, g): (A, B, C, D, E, F, G)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol, H: 'a + Symbol> From<(A, B, C, D, E, F, G, H)> for List<'a> { fn from((a, b, c, d, e, f, g, h): (A, B, C, D, E, F, G, H)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g), Box::new(h)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol, H: 'a + Symbol, I: 'a + Symbol, J: 'a + Symbol, K: 'a + Symbol> From<(A, B, C, D, E, F, G, H, I, J, K)> for List<'a> { fn from((a, b, c, d, e, f, g, h, i, j, k): (A, B, C, D, E, F, G, H, I, J, K)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g), Box::new(h), Box::new(i), Box::new(j), Box::new(k)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol, H: 'a + Symbol, I: 'a + Symbol, J: 'a + Symbol, K: 'a + Symbol, L: 'a + Symbol> From<(A, B, C, D, E, F, G, H, I, J, K, L)> for List<'a> { fn from((a, b, c, d, e, f, g, h, i, j, k, l): (A, B, C, D, E, F, G, H, I, J, K, L)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g), Box::new(h), Box::new(i), Box::new(j), Box::new(k), Box::new(l)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol, H: 'a + Symbol, I: 'a + Symbol, J: 'a + Symbol, K: 'a + Symbol, L: 'a + Symbol, M: 'a + Symbol> From<(A, B, C, D, E, F, G, H, I, J, K, L, M)> for List<'a> { fn from((a, b, c, d, e, f, g, h, i, j, k, l, m): (A, B, C, D, E, F, G, H, I, J, K, L, M)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g), Box::new(h), Box::new(i), Box::new(j), Box::new(k), Box::new(l), Box::new(m)]) } } #[rustfmt::skip] impl<'a, A: 'a + Symbol, B: 'a + Symbol, C: 'a + Symbol, D: 'a + Symbol, E: 'a + Symbol, F: 'a + Symbol, G: 'a + Symbol, H: 'a + Symbol, I: 'a + Symbol, J: 'a + Symbol, K: 'a + Symbol, L: 'a + Symbol, M: 'a + Symbol, N: 'a + Symbol> From<(A, B, C, D, E, F, G, H, I, J, K, L, M, N)> for List<'a> { fn from((a, b, c, d, e, f, g, h, i, j, k, l, m, n): (A, B, C, D, E, F, G, H, I, J, K, L, M, N)) -> Self { Self::new(vec![Box::new(a), Box::new(b), Box::new(c), Box::new(d), Box::new(e), Box::new(f), Box::new(g), Box::new(h), Box::new(i), Box::new(j), Box::new(k), Box::new(l), Box::new(m), Box::new(n)]) } } struct SymbolListAction<'a> { runner: &'a dyn SymbolRunner, symbols: &'a [Box], } impl<'a> SymbolListAction<'a> { fn new(runner: &'a dyn SymbolRunner, symbols: &'a [Box]) -> Self { Self { runner, symbols } } } impl<'a> Action for SymbolListAction<'a> { fn run(&self) -> Result<(), Box> { for symbol in self.symbols { symbol.as_action(self.runner).run()?; } Ok(()) } } pub struct ListAction<'a> { actions: Vec>, } impl<'a> ListAction<'a> { pub fn new(actions: Vec>) -> Self { Self { actions } } } impl<'a> Action for ListAction<'a> { fn run(&self) -> Result<(), Box> { for action in &self.actions { action.run()?; } Ok(()) } } impl<'a> fmt::Display for List<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "List [ ")?; for symbol in &self.symbols { write!(f, "{} ", symbol)?; } write!(f, "]") } } /* #[cfg(test)] mod test { use std::error::Error; use std::fmt; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use symbols::hook::List; struct ErrSymbol(String); impl Symbol for ErrSymbol { fn target_reached(&self) -> Result> { Err(self.0.clone().into()) } fn execute(&self) -> Result<(), Box> { Err(self.0.clone().into()) } } impl fmt::Display for ErrSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } } struct OkSymbol(bool); impl Symbol for OkSymbol { fn target_reached(&self) -> Result> { Ok(self.0) } fn execute(&self) -> Result<(), Box> { Ok(()) } } impl fmt::Display for OkSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } } #[test] fn first_target_reached_fails() { let res = List::new(ErrSymbol("first".into()), ErrSymbol("second".into())).target_reached(); assert_eq!(res.unwrap_err().description(), "first"); } #[test] fn first_target_not_reached() { let res = List::new(OkSymbol(false), ErrSymbol("second".into())).target_reached(); assert_eq!(res.unwrap(), false); } #[test] fn second_target_reached_fails() { let res = List::new(OkSymbol(true), ErrSymbol("second".into())).target_reached(); assert_eq!(res.unwrap_err().description(), "second"); } #[test] fn second_target_not_reached() { let res = List::new(OkSymbol(true), OkSymbol(false)).target_reached(); assert_eq!(res.unwrap(), false); } #[test] fn everything_reached() { let res = List::new(OkSymbol(true), OkSymbol(true)).target_reached(); assert_eq!(res.unwrap(), true); } #[test] fn first_execute_fails() { let res = List::new(ErrSymbol("first".into()), ErrSymbol("second".into())).execute(); assert_eq!(res.unwrap_err().description(), "first"); } #[test] fn second_execute_fails() { let res = List::new(OkSymbol(true), ErrSymbol("second".into())).execute(); assert_eq!(res.unwrap_err().description(), "second"); } #[test] fn everything_executes() { let res = List::new(OkSymbol(true), OkSymbol(true)).execute(); assert_eq!(res.unwrap(), ()); } } */