diff options
| author | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-02-27 18:21:12 +0000 |
|---|---|---|
| committer | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-02-27 18:21:12 +0000 |
| commit | 2e314caed41f53997d18e49c28b8d76e7aa5af5d (patch) | |
| tree | 7c1d83f9d537bee6b9b0b036655b6c2710409d68 /src/main/rust/app.rs | |
| parent | d3f8e0ccc65a6cfd3acf67f32ae86fddb49ea930 (diff) | |
| download | equity-tracker-2e314caed41f53997d18e49c28b8d76e7aa5af5d.tar.gz equity-tracker-2e314caed41f53997d18e49c28b8d76e7aa5af5d.tar.bz2 equity-tracker-2e314caed41f53997d18e49c28b8d76e7aa5af5d.zip | |
Separate app logic from UI and IO
Diffstat (limited to 'src/main/rust/app.rs')
| -rw-r--r-- | src/main/rust/app.rs | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/main/rust/app.rs b/src/main/rust/app.rs new file mode 100644 index 0000000..d6e84e1 --- /dev/null +++ b/src/main/rust/app.rs @@ -0,0 +1,205 @@ +use crate::store::{Context, Store}; +use miette::{Diagnostic, Result}; +use thiserror::Error; + +#[derive(Default)] +pub struct App { + context: Context, + exit: bool, +} + +#[derive(Diagnostic, Debug, Error, PartialEq)] +#[error("An overflow error occurred")] +#[diagnostic()] +pub struct OverflowError { + #[help] + pub _msg: String, +} + +impl App { + /// Build context in App and pass it forward + pub fn init_context(&mut self) -> Result<&mut Self> { + let store = self.context.unwrap_store(); + + store.init()?; + Ok(self) + } + + pub fn get_exit_status(&self) -> bool { + self.exit + } + + pub fn exit(&mut self) -> Result<()> { + self.exit = true; + Ok(()) + } + + pub fn decrement_counter(&mut self) -> Result<()> { + let store = self.context.unwrap_store(); + let count = store.get_counter()?; + + if count == 0 { + Err(OverflowError { + _msg: "Cannot count below 0".into(), + } + .into()) + } else { + store.set_counter(count - 1)?; + Ok(()) + } + } + + pub fn increment_counter(&mut self) -> Result<()> { + let store = self.context.unwrap_store(); + let count = store.get_counter()?; + + if count == u8::MAX { + Err(OverflowError { + _msg: "Cannot count above u8::MAX".into(), + } + .into()) + } else { + store.set_counter(count + 1)?; + Ok(()) + } + } + + pub fn display_counter(&self) -> String { + self.context + .get_store() + .get_counter() + .map(|u| u.to_string()) + .unwrap_or("Error".into()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::store::ContextError; + + fn get_count(app: &App) -> Result<u8, ContextError> { + app.context.get_store().get_counter() + } + + #[test] + fn display_counter_inited() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let count = app.display_counter(); + + assert_eq!(count, "0"); + } + + #[test] + fn display_counter_noninited() { + let app = App::default(); + + let count = app.display_counter(); + + assert_eq!(count, "Error"); + } + + #[test] + fn increment_decrement() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), 1); + + let res = app.decrement_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), 0); + } + + #[test] + fn increment_n() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let n = 8; + + for i in 1..=n { + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), i); + } + assert_eq!(get_count(&app).unwrap(), n); + } + + #[test] + fn increment_n_decrement() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let n = 8; + + for i in 1..=n { + let res = app.increment_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), i); + } + assert_eq!(get_count(&app).unwrap(), n); + + let res = app.decrement_counter(); + assert!(res.is_ok()); + assert_eq!(get_count(&app).unwrap(), n - 1); + } + + #[test] + fn exit() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + + let res = app.exit(); + + assert!(res.is_ok()); + assert!(app.exit); + } + + #[test] + fn decrement_counter_error() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = app.decrement_counter(); + + assert!(res.is_err()); + let res_err = res.unwrap_err(); + let casted_val = res_err + .downcast_ref::<OverflowError>() + .expect("something bad occurred"); + + let expected_err_msg: String = "Cannot count below 0".into(); + assert_eq!(casted_val._msg, expected_err_msg); + assert_eq!( + *casted_val, + OverflowError { + _msg: expected_err_msg, + }, + ); + } + + #[test] + fn increment_counter_error() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + assert!(app.context.unwrap_store().set_counter(u8::MAX).is_ok()); + let res = app.increment_counter(); + + assert!(res.is_err()); + let res_err = res.unwrap_err(); + let casted_val = res_err + .downcast_ref::<OverflowError>() + .expect("something bad occurred"); + + let expected_err_msg: String = "Cannot count above u8::MAX".into(); + assert_eq!(casted_val._msg, expected_err_msg); + assert_eq!( + *casted_val, + OverflowError { + _msg: expected_err_msg, + }, + ); + } +} |
