From 47ea7901b73085ead704ec2bd45402ae0c4ce5a2 Mon Sep 17 00:00:00 2001 From: Kevin Hoerr Date: Thu, 26 Feb 2026 21:57:41 +0000 Subject: Use SQLite to store counter --- src/main/rust/main.rs | 102 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 26 deletions(-) (limited to 'src/main/rust/main.rs') diff --git a/src/main/rust/main.rs b/src/main/rust/main.rs index 0805796..2b77a18 100644 --- a/src/main/rust/main.rs +++ b/src/main/rust/main.rs @@ -17,7 +17,6 @@ use thiserror::Error; #[derive(Default)] pub struct App { context: Context, - counter: u8, exit: bool, } @@ -35,17 +34,15 @@ fn main() -> Result<()> { } impl App { - // Initializes context + /// Build context in App and pass it forward pub fn init_context(&mut self) -> Result<&mut Self> { - match &mut self.context { - Context::SQLite(s) => { - s.init()?; - } - } + let store = self.context.unwrap_store(); + + store.init()?; Ok(self) } - /// runs the application's main loop until the user quits + /// Run the app's main loop until the user quits #[cfg(not(tarpaulin_include))] pub fn run(&mut self, terminal: &mut DefaultTerminal) -> Result<()> { while !self.exit { @@ -55,10 +52,12 @@ impl App { Ok(()) } + /// Render app to frame fn draw(&self, frame: &mut Frame) { frame.render_widget(self, frame.area()); } + /// Use crossterm to read user input events fn handle_events(&mut self) -> Result<()> { match event::read().into_diagnostic()? { // it's important to check that the event is a key press event as @@ -70,6 +69,7 @@ impl App { } } + /// Process user input and run associated app functions fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> { match key_event.code { KeyCode::Char('q') => self.exit()?, @@ -85,27 +85,43 @@ impl App { Ok(()) } - fn decrement_counter(&mut self) -> Result<(), OverflowError> { - if self.counter == 0 { + 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 { - self.counter -= 1; + store.set_counter(count - 1)?; Ok(()) } } - fn increment_counter(&mut self) -> Result<(), OverflowError> { - if self.counter == u8::MAX { + 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 { - self.counter += 1; + store.set_counter(count + 1)?; Ok(()) } } + + fn display_counter(&self) -> String { + self.context + .get_store() + .get_counter() + .map(|u| u.to_string()) + .unwrap_or("Error".into()) + } } impl Widget for &App { @@ -126,7 +142,7 @@ impl Widget for &App { let counter_text = Text::from(vec![Line::from(vec![ "Value: ".into(), - self.counter.to_string().yellow(), + self.display_counter().yellow(), ])]); Paragraph::new(counter_text) @@ -138,12 +154,39 @@ impl Widget for &App { #[cfg(test)] mod tests { + use crate::store::ContextError; + use super::*; use ratatui::style::Style; + fn get_count(app: &App) -> Result { + app.context.get_store().get_counter() + } + #[test] - fn render() { + 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 render() { + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let mut buf = Buffer::empty(Rect::new(0, 0, 50, 4)); app.render(buf.area, &mut buf); @@ -170,48 +213,53 @@ mod tests { #[test] fn handle_key_event_inc_dec() { let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = app.handle_key_event(KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(app.counter, 1); + assert_eq!(get_count(&app).unwrap(), 1); let res = app.handle_key_event(KeyCode::Left.into()); assert!(res.is_ok()); - assert_eq!(app.counter, 0); + assert_eq!(get_count(&app).unwrap(), 0); } #[test] fn handle_key_event_inc_n() { let mut app = App::default(); + assert!(app.init_context().is_ok()); let n = 8; for i in 1..=n { let res = app.handle_key_event(KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(app.counter, i); + assert_eq!(get_count(&app).unwrap(), i); } - assert_eq!(app.counter, n); + assert_eq!(get_count(&app).unwrap(), n); } #[test] fn handle_key_event_inc_n_dec() { let mut app = App::default(); + assert!(app.init_context().is_ok()); let n = 8; for i in 1..=n { let res = app.handle_key_event(KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(app.counter, i); + assert_eq!(get_count(&app).unwrap(), i); } - assert_eq!(app.counter, n); + assert_eq!(get_count(&app).unwrap(), n); let res = app.handle_key_event(KeyCode::Left.into()); assert!(res.is_ok()); - assert_eq!(app.counter, n - 1); + assert_eq!(get_count(&app).unwrap(), n - 1); } #[test] fn handle_key_event_exit() { let mut app = App::default(); + assert!(app.init_context().is_ok()); let res = app.handle_key_event(KeyCode::Char('q').into()); assert!(res.is_ok()); assert!(app.exit); @@ -220,6 +268,7 @@ mod tests { #[test] fn handle_key_event_dec_error() { let mut app = App::default(); + assert!(app.init_context().is_ok()); let res = app.handle_key_event(KeyCode::Left.into()); assert!(res.is_err()); @@ -241,7 +290,8 @@ mod tests { #[test] fn handle_key_event_inc_error() { let mut app = App::default(); - app.counter = u8::MAX; + assert!(app.init_context().is_ok()); + assert!(app.context.unwrap_store().set_counter(u8::MAX).is_ok()); let res = app.handle_key_event(KeyCode::Right.into()); assert!(res.is_err()); -- cgit v1.3