pub trait Command {
type Output;
type Error;
fn execute(&self) -> Result<Self::Output, Self::Error>;
}
pub struct AddCommand {
pub left: u64,
pub right: u64,
}
impl AddCommand {
pub fn new(left: u64, right: u64) -> Self {
Self { left, right }
}
}
impl Command for AddCommand {
type Output = u64;
type Error = std::convert::Infallible;
fn execute(&self) -> Result<Self::Output, Self::Error> {
Ok(self.left + self.right)
}
}
pub struct MultiplyCommand {
pub left: u64,
pub right: u64,
}
impl MultiplyCommand {
pub fn new(left: u64, right: u64) -> Self {
Self { left, right }
}
}
impl Command for MultiplyCommand {
type Output = u64;
type Error = std::convert::Infallible;
fn execute(&self) -> Result<Self::Output, Self::Error> {
Ok(self.left * self.right)
}
}
pub struct CommandInvoker;
impl CommandInvoker {
pub fn invoke<C: Command>(command: C) -> Result<C::Output, C::Error> {
command.execute()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_command() {
let cmd = AddCommand::new(2, 2);
let result = cmd.execute().unwrap();
assert_eq!(result, 4);
}
#[test]
fn test_multiply_command() {
let cmd = MultiplyCommand::new(3, 4);
let result = cmd.execute().unwrap();
assert_eq!(result, 12);
}
#[test]
fn test_command_invoker() {
let add_cmd = AddCommand::new(5, 3);
let result = CommandInvoker::invoke(add_cmd).unwrap();
assert_eq!(result, 8);
let multiply_cmd = MultiplyCommand::new(5, 3);
let result = CommandInvoker::invoke(multiply_cmd).unwrap();
assert_eq!(result, 15);
}
}