use crate::meta_commands::{MetaCommand, MetaCommandExecuteResult, MetaCommandParseError}; use crate::statements::{Statement, StatementExecuteResult, StatementParseError}; #[derive(Debug)] pub enum Command { MetaCommand(MetaCommand), Statement(Statement), } #[derive(Debug)] pub struct CommandExecuteResult { pub should_exit: bool, msg: String, } impl CommandExecuteResult { pub fn display(&self) -> String { self.msg.to_string() } } impl From for CommandExecuteResult { fn from(value: MetaCommandExecuteResult) -> Self { Self { should_exit: value.should_exit, msg: String::new(), } } } impl From for CommandExecuteResult { fn from(value: StatementExecuteResult) -> Self { Self { should_exit: false, msg: value.msg, } } } impl Command { pub fn execute(&self) -> CommandExecuteResult { match self { Command::MetaCommand(cmd) => cmd.execute().into(), Command::Statement(stmt) => stmt.execute().into(), } } } #[derive(Debug)] pub enum CommandParseError { MetaCommand(MetaCommandParseError), Statement(StatementParseError), } impl std::fmt::Display for CommandParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { CommandParseError::MetaCommand(meta_command_parse_error) => { write!(f, "{meta_command_parse_error}") } CommandParseError::Statement(statement_parse_error) => { write!(f, "{statement_parse_error}") } } } } impl From for Command { fn from(value: MetaCommand) -> Self { Command::MetaCommand(value) } } impl From for CommandParseError { fn from(value: MetaCommandParseError) -> Self { CommandParseError::MetaCommand(value) } } impl From for Command { fn from(value: Statement) -> Self { Command::Statement(value) } } impl From for CommandParseError { fn from(value: StatementParseError) -> Self { CommandParseError::Statement(value) } } impl std::str::FromStr for Command { type Err = CommandParseError; fn from_str(s: &str) -> Result { if s.starts_with(".") { s.parse::() .map(|x| x.into()) .map_err(|x| x.into()) } else { s.parse::() .map(|x| x.into()) .map_err(|x| x.into()) } } } #[cfg(test)] mod tests { use crate::{command::Command, meta_commands::MetaCommand, statements::Statement}; use insta::{assert_debug_snapshot, assert_snapshot}; #[test] fn test_execute_insert_statement() { let statement: Command = Statement::Insert.into(); let result = statement.execute().display(); assert_snapshot!(result); } #[test] fn test_execute_select_statement() { let statement: Command = Statement::Select.into(); let result = statement.execute().display(); assert_snapshot!(result); } #[test] fn test_execute_exit_metacommand() { assert_debug_snapshot!(Into::::into(MetaCommand::Exit).execute()); } #[test] fn test_parse_wrong_statement() { assert_debug_snapshot!("salact".parse::()); } }