Start work on errors

This commit is contained in:
Austen Adler 2021-08-07 00:29:40 -04:00
parent 2859a23b1e
commit 409f1d65a5
4 changed files with 66 additions and 19 deletions

37
src/errors.rs Normal file
View File

@ -0,0 +1,37 @@
use core::any::Any;
use std::fmt;
#[derive(Debug)]
pub enum ProgramError {
General(String),
UiError(String),
Boxed(Box<dyn Any + Send>),
}
impl From<String> 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<Box<dyn Any + Send>> for ProgramError {
fn from(e: Box<dyn Any + Send>) -> 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),
}
}
}

View File

@ -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::<Message>();
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()?
}

View File

@ -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<Self, ProgramError> {
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::<Vec<(u8, u8, u8)>>();
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) {

View File

@ -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<strip::Message>) {
pub fn console_ui_loop(tx: &Sender<strip::Message>) -> 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<strip::Message>, pat: Box<dyn Pattern + Send>) ->
.map_err(|e| e.to_string())
}
fn get_line(prompt: &str) -> String {
fn get_line(prompt: &str) -> Result<String, ProgramError> {
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())
}