From 409f1d65a510124ab64b4617f5bcfbe58e0c4fae Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Sat, 7 Aug 2021 00:29:40 -0400 Subject: [PATCH] Start work on errors --- src/errors.rs | 37 +++++++++++++++++++++++++++++++++++++ src/main.rs | 17 +++++++++++------ src/strip.rs | 15 ++++++++------- src/ui.rs | 16 ++++++++++------ 4 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 src/errors.rs diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..c5b2915 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,37 @@ +use core::any::Any; +use std::fmt; + +#[derive(Debug)] +pub enum ProgramError { + General(String), + UiError(String), + Boxed(Box), +} + +impl From for ProgramError { + fn from(e: String) -> Self { + Self::General(e) + } +} + +impl From<&str> for ProgramError { + fn from(e: &str) -> Self { + Self::General(e.to_string()) + } +} + +impl From> for ProgramError { + fn from(e: Box) -> Self { + Self::Boxed(e) + } +} + +impl fmt::Display for ProgramError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + Self::General(s) => write!(f, "{}", s), + Self::UiError(s) => write!(f, "Critial UI error: {}", s), + Self::Boxed(s) => write!(f, "{:?}", s), + } + } +} diff --git a/src/main.rs b/src/main.rs index f953262..dc23fcf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,24 +21,25 @@ clippy::indexing_slicing, clippy::integer_arithmetic, clippy::integer_division, - // Expect prints a message when there is a critical error, so this is valid clippy::expect_used, clippy::unwrap_used, )] // See https://rust-lang.github.io/rust-clippy/master/index.html for more lints mod color; +mod errors; mod pattern; mod strip; mod ui; +use errors::ProgramError; use std::sync::mpsc::channel; use std::thread; use strip::{LEDStrip, Message}; use ui::console_ui_loop; -fn main() { +fn main() -> Result<(), ProgramError> { let (tx, rx) = channel::(); - thread::spawn(move || { + let handle = thread::spawn(move || -> Result<(), ProgramError> { let mut strip = LEDStrip::new(strip::Config { // I have 89 right now, but start off with 20 num_lights: 20, @@ -47,10 +48,14 @@ fn main() { // Scaling factor (scale 0..255) global_brightness_max: 20, tick_time_ms: strip::DEFAULT_TICK_TIME_MS, - }); + })?; strip.strip_loop(&rx); - panic!("Dead strip thread. Terminating"); + Err(ProgramError::General(String::from( + "Dead strip thread. Terminating", + ))) }); - console_ui_loop(&tx); + console_ui_loop(&tx)?; + + handle.join()? } diff --git a/src/strip.rs b/src/strip.rs index a66d39f..55750c9 100644 --- a/src/strip.rs +++ b/src/strip.rs @@ -1,4 +1,5 @@ use crate::color; +use crate::errors::ProgramError; use crate::pattern::{self, Pattern}; use std::cmp; use std::ops::Add; @@ -43,9 +44,10 @@ pub struct LEDStrip { } impl LEDStrip { - pub fn new(config: Config) -> Self { + pub fn new(config: Config) -> Result { let adapter = Box::new( - Ws28xxSpiAdapter::new("/dev/spidev0.0").expect("Cannot locate device /dev/spidev0.0!"), + Ws28xxSpiAdapter::new("/dev/spidev0.0") + .map_err(|_| "Cannot start device /dev/spidev0.0!")?, ); let pattern = Box::new(pattern::Solid::new(color::BLACK)); let num_lights = config.num_lights; @@ -55,10 +57,10 @@ impl LEDStrip { config, }; ret.set_num_lights(num_lights); - ret + Ok(ret) } - fn write_buf_from_pattern(&mut self) { + fn write_buf_from_pattern(&mut self) -> Result<(), ProgramError> { let global_brightness_max = self.config.global_brightness_max; let data = vec![color::BLACK] .iter() @@ -81,9 +83,8 @@ impl LEDStrip { }) // TODO: Do not re-collect as u8s .collect::>(); - self.adapter - .write_rgb(data.as_slice()) - .expect("TODO: Critical data write error!"); + self.adapter.write_rgb(data.as_slice())?; + Ok(()) } fn set_num_lights(&mut self, num_lights: u16) { diff --git a/src/ui.rs b/src/ui.rs index eec884f..1f1106d 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,13 +1,15 @@ use crate::color::Rgb; +use crate::errors::ProgramError; use crate::pattern::{self, Pattern}; use crate::strip; use std::io; use std::io::Write; use std::sync::mpsc::Sender; -pub fn console_ui_loop(tx: &Sender) { +pub fn console_ui_loop(tx: &Sender) -> Result<(), ProgramError> { loop { - if let Err(msg) = parse_cmd(tx, &get_line("Command (cfqs)")) { + let line = get_line("Command (cfqs)")?; + if let Err(msg) = parse_cmd(tx, &line) { println!("Command error: {}", msg); } } @@ -105,12 +107,14 @@ fn change_pattern(tx: &Sender, pat: Box) -> .map_err(|e| e.to_string()) } -fn get_line(prompt: &str) -> String { +fn get_line(prompt: &str) -> Result { print!("{}: ", prompt); - std::io::stdout().flush().expect("Could not flush stdout"); + std::io::stdout() + .flush() + .map_err(|_| ProgramError::UiError(String::from("Could not flush stdout")))?; let mut input_text = String::new(); io::stdin() .read_line(&mut input_text) - .expect("Could not read from stdin"); - input_text.trim().to_string() + .map_err(|_| ProgramError::UiError(String::from("Could not read from stdin")))?; + Ok(input_text.trim().to_string()) }