use std::fmt::Display; use crate::{ChainProcess, Program, asset::node::Node}; /// Dispatches user input commands to specific [ChainProcess](./enum.ChainProcess.html) /// /// Note: If you are using [mingling_macros](https://crates.io/crates/mingling_macros), /// you can use the `dispatcher!("node.subnode", CommandType => Entry)` macro to declare a `Dispatcher` pub trait Dispatcher where G: Display, { /// Returns a command node for matching user input fn node(&self) -> Node; /// Returns a [ChainProcess](./enum.ChainProcess.html) based on user input arguments, /// to be sent to the specific invocation fn begin(&self, args: Vec) -> ChainProcess; /// Clones the current dispatcher for implementing the `Clone` trait fn clone_dispatcher(&self) -> Box>; } impl Clone for Box> where G: Display, { fn clone(&self) -> Self { self.clone_dispatcher() } } impl Program { /// Adds a dispatcher to the program. pub fn with_dispatcher(&mut self, dispatcher: Disp) where Disp: Dispatcher + 'static, { self.dispatcher.push(Box::new(dispatcher)); } /// Add some dispatchers to the program. pub fn with_dispatchers(&mut self, dispatchers: D) where D: Into>, { let dispatchers = dispatchers.into(); self.dispatcher.extend(dispatchers.dispatcher); } } /// A collection of dispatchers. /// /// This struct holds a vector of boxed `Dispatcher` trait objects, /// allowing multiple dispatchers to be grouped together and passed /// to the program via `Program::with_dispatchers`. /// A collection of dispatchers. /// /// This struct holds a vector of boxed `Dispatcher` trait objects, /// allowing multiple dispatchers to be grouped together and passed /// to the program via `Program::with_dispatchers`. pub struct Dispatchers { dispatcher: Vec + 'static>>, } impl From>>> for Dispatchers { fn from(dispatcher: Vec>>) -> Self { Self { dispatcher } } } impl From>> for Dispatchers { fn from(dispatcher: Box>) -> Self { Self { dispatcher: vec![dispatcher], } } } impl From<(D,)> for Dispatchers where D: Dispatcher + 'static, G: Display, { fn from(dispatcher: (D,)) -> Self { Self { dispatcher: vec![Box::new(dispatcher.0)], } } } impl From<(D1, D2)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2)) -> Self { Self { dispatcher: vec![Box::new(dispatchers.0), Box::new(dispatchers.1)], } } } impl From<(D1, D2, D3)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, D3: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3)) -> Self { Self { dispatcher: vec![ Box::new(dispatchers.0), Box::new(dispatchers.1), Box::new(dispatchers.2), ], } } } impl From<(D1, D2, D3, D4)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, D3: Dispatcher + 'static, D4: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4)) -> Self { Self { dispatcher: vec![ Box::new(dispatchers.0), Box::new(dispatchers.1), Box::new(dispatchers.2), Box::new(dispatchers.3), ], } } } impl From<(D1, D2, D3, D4, D5)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, D3: Dispatcher + 'static, D4: Dispatcher + 'static, D5: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5)) -> Self { Self { dispatcher: vec![ Box::new(dispatchers.0), Box::new(dispatchers.1), Box::new(dispatchers.2), Box::new(dispatchers.3), Box::new(dispatchers.4), ], } } } impl From<(D1, D2, D3, D4, D5, D6)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, D3: Dispatcher + 'static, D4: Dispatcher + 'static, D5: Dispatcher + 'static, D6: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5, D6)) -> Self { Self { dispatcher: vec![ Box::new(dispatchers.0), Box::new(dispatchers.1), Box::new(dispatchers.2), Box::new(dispatchers.3), Box::new(dispatchers.4), Box::new(dispatchers.5), ], } } } impl From<(D1, D2, D3, D4, D5, D6, D7)> for Dispatchers where D1: Dispatcher + 'static, D2: Dispatcher + 'static, D3: Dispatcher + 'static, D4: Dispatcher + 'static, D5: Dispatcher + 'static, D6: Dispatcher + 'static, D7: Dispatcher + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5, D6, D7)) -> Self { Self { dispatcher: vec![ Box::new(dispatchers.0), Box::new(dispatchers.1), Box::new(dispatchers.2), Box::new(dispatchers.3), Box::new(dispatchers.4), Box::new(dispatchers.5), Box::new(dispatchers.6), ], } } } impl std::ops::Deref for Dispatchers { type Target = Vec + 'static>>; fn deref(&self) -> &Self::Target { &self.dispatcher } } impl From> for Vec + 'static>> { fn from(val: Dispatchers) -> Self { val.dispatcher } }