diff --git a/src/branding.rs b/src/branding.rs new file mode 100644 index 0000000..e5583c2 --- /dev/null +++ b/src/branding.rs @@ -0,0 +1,8 @@ +pub fn startup_msg() { + let name = env!("CARGO_PKG_NAME"); + let version = env!("CARGO_PKG_VERSION"); + let authors = env!("CARGO_PKG_AUTHORS"); + + println!("{name} v{version} started.",); + println!("Copyright 2025 {authors}. All rights reserved.") +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..4c8ee91 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,18 @@ +pub fn read_input() -> Option { + use std::io::{BufRead, Write}; + + print!("osdb > "); + std::io::stdout().flush().expect("failed to flush stdout"); + + let mut input = String::new(); + let len = std::io::stdin() + .lock() + .read_line(&mut input) + .expect("failed to read input from stdin"); + + if len == 0 { + None + } else { + Some(input) + } +} diff --git a/src/command.rs b/src/command.rs new file mode 100644 index 0000000..8f291c6 --- /dev/null +++ b/src/command.rs @@ -0,0 +1,65 @@ +use crate::meta_commands::{MetaCommand, MetaCommandParseError}; +use crate::statements::{Statement, StatementParseError}; + +pub enum Command { + MetaCommand(MetaCommand), + Statement(Statement), +} + +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()) + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ae59f40 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +pub mod branding; +pub mod cli; +pub mod command; +pub mod meta_commands; +pub mod statements; diff --git a/src/main.rs b/src/main.rs index 69e14a3..92e577c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,133 +1,7 @@ -enum MetaCommand { - Exit, -} - -enum MetaCommandParseError { - Unrecognized { cmd: String }, -} - -impl std::fmt::Display for MetaCommandParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - MetaCommandParseError::Unrecognized { cmd } => { - write!(f, "unrecognized meta-command {cmd:?}") - } - } - } -} - -impl std::str::FromStr for MetaCommand { - type Err = MetaCommandParseError; - - fn from_str(s: &str) -> Result { - match s.trim() { - ".exit" => Ok(MetaCommand::Exit), - cmd => Err(MetaCommandParseError::Unrecognized { - cmd: cmd.to_string(), - }), - } - } -} - -enum Statement { - Insert, - Select, -} - -enum StatementParseError { - Unrecognized { stmt: String }, -} - -impl std::fmt::Display for StatementParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - StatementParseError::Unrecognized { stmt } => { - write!(f, "unrecognized statement {stmt:?}") - } - } - } -} - -impl std::str::FromStr for Statement { - type Err = StatementParseError; - - fn from_str(s: &str) -> Result { - let s = s.trim(); - let lower = s.to_lowercase(); - if lower.starts_with("insert") { - Ok(Statement::Insert) - } else if lower.starts_with("select") { - Ok(Statement::Select) - } else { - Err(StatementParseError::Unrecognized { - stmt: s.to_string(), - }) - } - } -} - -enum Command { - MetaCommand(MetaCommand), - Statement(Statement), -} - -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()) - } - } -} +use osdb::branding::startup_msg; +use osdb::cli::read_input; +use osdb::command::Command; +use osdb::meta_commands::MetaCommand; fn main() { startup_msg(); @@ -140,44 +14,9 @@ fn main() { break; } }, - Command::Statement(stmt) => execute_statment(stmt), + Command::Statement(stmt) => stmt.execute(), }, Err(err) => eprintln!("{err}"), } } } - -fn execute_statment(stmt: Statement) { - match stmt { - Statement::Insert => println!("insert"), - Statement::Select => println!("select"), - } -} - -fn startup_msg() { - let name = env!("CARGO_PKG_NAME"); - let version = env!("CARGO_PKG_VERSION"); - let authors = env!("CARGO_PKG_AUTHORS"); - - println!("{name} v{version} started.",); - println!("Copyright 2025 {authors}. All rights reserved.") -} - -fn read_input() -> Option { - use std::io::{BufRead, Write}; - - print!("osdb > "); - std::io::stdout().flush().expect("failed to flush stdout"); - - let mut input = String::new(); - let len = std::io::stdin() - .lock() - .read_line(&mut input) - .expect("failed to read input from stdin"); - - if len == 0 { - None - } else { - Some(input) - } -} diff --git a/src/meta_commands.rs b/src/meta_commands.rs new file mode 100644 index 0000000..827707b --- /dev/null +++ b/src/meta_commands.rs @@ -0,0 +1,30 @@ +pub enum MetaCommand { + Exit, +} + +pub enum MetaCommandParseError { + Unrecognized { cmd: String }, +} + +impl std::fmt::Display for MetaCommandParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MetaCommandParseError::Unrecognized { cmd } => { + write!(f, "unrecognized meta-command {cmd:?}") + } + } + } +} + +impl std::str::FromStr for MetaCommand { + type Err = MetaCommandParseError; + + fn from_str(s: &str) -> Result { + match s.trim() { + ".exit" => Ok(MetaCommand::Exit), + cmd => Err(MetaCommandParseError::Unrecognized { + cmd: cmd.to_string(), + }), + } + } +} diff --git a/src/statements.rs b/src/statements.rs new file mode 100644 index 0000000..a108fb6 --- /dev/null +++ b/src/statements.rs @@ -0,0 +1,45 @@ +pub enum Statement { + Insert, + Select, +} + +pub enum StatementParseError { + Unrecognized { stmt: String }, +} + +impl std::fmt::Display for StatementParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + StatementParseError::Unrecognized { stmt } => { + write!(f, "unrecognized statement {stmt:?}") + } + } + } +} + +impl std::str::FromStr for Statement { + type Err = StatementParseError; + + fn from_str(s: &str) -> Result { + let s = s.trim(); + let lower = s.to_lowercase(); + if lower.starts_with("insert") { + Ok(Statement::Insert) + } else if lower.starts_with("select") { + Ok(Statement::Select) + } else { + Err(StatementParseError::Unrecognized { + stmt: s.to_string(), + }) + } + } +} + +impl Statement { + pub fn execute(&self) { + match self { + Statement::Insert => println!("insert"), + Statement::Select => println!("select"), + } + } +}