use crate::*; pub trait Command: Send + Sync + Sized { fn execute (self, state: &mut S) -> Perhaps; fn delegate (self, state: &mut S, wrap: impl Fn(Self)->T) -> Perhaps { Ok(self.execute(state)?.map(wrap)) } } #[macro_export] macro_rules! input_to_command { (<$($l:lifetime),+> $Command:ty: |$state:ident:$State:ty, $input:ident:$Input:ty| $handler:expr) => { impl<$($l),+> InputToCommand<$Input, $State> for $Command { fn input_to_command ($state: &$State, $input: &$Input) -> Option { Some($handler) } } }; ($Command:ty: |$state:ident:$State:ty, $input:ident:$Input:ty| $handler:expr) => { impl InputToCommand<$Input, $State> for $Command { fn input_to_command ($state: &$State, $input: &$Input) -> Option { Some($handler) } } } } pub trait InputToCommand: Command + Sized { fn input_to_command (state: &S, input: &I) -> Option; fn execute_with_state (state: &mut S, input: &I) -> Perhaps { Ok(if let Some(command) = Self::input_to_command(state, input) { let _undo = command.execute(state)?; Some(true) } else { None }) } } #[macro_export] macro_rules! command { ($(<$($l:lifetime),+>)?|$self:ident:$Command:ty,$state:ident:$State:ty|$handler:expr) => { impl$(<$($l),+>)? Command<$State> for $Command { fn execute ($self, $state: &mut $State) -> Perhaps { Ok($handler) } } }; }