From a6ee8faf31f3d8885a12c10c0bb7a0f2b9a1a7d3 Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Thu, 25 Jul 2024 14:16:10 +1000 Subject: [PATCH] update errors --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 87 +++++++++++++++++++++++++++-------------------------- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 564f9be..e337d52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -662,6 +662,7 @@ dependencies = [ "pretty_env_logger", "serde", "swayipc-async", + "thiserror", "tokio", "toml", ] diff --git a/Cargo.toml b/Cargo.toml index 015e0ec..c911499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ lab = "0.11.0" directories = "5.0.1" toml = "0.8.15" serde = { version = "1.0.204", features = ["derive"] } +thiserror = "1.0.63" diff --git a/src/main.rs b/src/main.rs index 42aa718..4c5f317 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,27 +2,31 @@ use futures_util::StreamExt; use lab::Lab; use serde::{Deserialize, Serialize}; -#[derive(Debug)] -struct NoMatchingConfig; +#[derive(thiserror::Error, Debug)] +enum Error { + #[error("no matching config")] + NoMatchingConfig, + #[error("couldnt parse hex")] + HexParse, + #[error(transparent)] + Swayipc(#[from] swayipc_async::Error), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("couldn't set cell")] + SetCell, + #[error(transparent)] + TomlDe(#[from] toml::de::Error), + #[error(transparent)] + TomlSer(#[from] toml::ser::Error), +} -impl std::fmt::Display for NoMatchingConfig { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "no config for client.focused") +impl From> for Error { + fn from(_: tokio::sync::SetError) -> Self { + Self::SetCell } } -impl std::error::Error for NoMatchingConfig {} - -#[derive(Debug)] -struct HexParse; - -impl std::fmt::Display for HexParse { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "invalid hex colour") - } -} - -impl std::error::Error for HexParse {} +type Res = Result; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] struct Config { @@ -68,7 +72,7 @@ static DEFAULT_COLOURS_NO_INDICATOR: tokio::sync::OnceCell = static DEFAULT_BORDER: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Res<()> { if std::env::var_os("RUST_LOG").is_none() { std::env::set_var("RUST_LOG", "info"); } @@ -109,9 +113,9 @@ async fn main() -> Result<(), Box> { Ok(()) } -fn parse_config() -> Result<(), Box> { +fn parse_config() -> Res<()> { let dirs = directories::ProjectDirs::from("com", "alexjanka", "sway-flash-indicator") - .ok_or(NoMatchingConfig)?; + .ok_or(Error::NoMatchingConfig)?; let config_dir = dirs.config_dir(); if let Ok(false) = config_dir.try_exists() { @@ -137,21 +141,19 @@ fn parse_config() -> Result<(), Box> { Ok(()) } -async fn get_sway_config( - connection: &mut swayipc_async::Connection, -) -> Result<(), Box> { +async fn get_sway_config(connection: &mut swayipc_async::Connection) -> Res<()> { let config = connection.get_config().await?; let default_colours = config .config .split('\n') .find(|v| v.contains("client.focused")) - .ok_or(NoMatchingConfig)? + .ok_or(Error::NoMatchingConfig)? .trim(); let default_border = default_colours .split_whitespace() .nth(2) - .ok_or(NoMatchingConfig)?; + .ok_or(Error::NoMatchingConfig)?; DEFAULT_BORDER.set(parse_hex(default_border)?)?; DEFAULT_COLOURS.set(default_colours.to_string())?; @@ -162,19 +164,19 @@ async fn get_sway_config( Ok(()) } -fn parse_hex(hex: &str) -> Result { +fn parse_hex(hex: &str) -> Res { let hex = hex.strip_prefix('#').unwrap_or(hex); - let r = u8::from_str_radix(&hex[..2], 16).map_err(|_| HexParse)?; - let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| HexParse)?; - let b = u8::from_str_radix(&hex[4..], 16).map_err(|_| HexParse)?; + let r = u8::from_str_radix(&hex[..2], 16).map_err(|_| Error::HexParse)?; + let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| Error::HexParse)?; + let b = u8::from_str_radix(&hex[4..], 16).map_err(|_| Error::HexParse)?; Ok(Lab::from_rgb(&[r, g, b])) } -async fn interpolate_task() -> Result<(), Box> { +async fn interpolate_task() -> Res<()> { let mut connection = swayipc_async::Connection::new().await?; - let to = DEFAULT_BORDER.get().ok_or(NoMatchingConfig)?; - let config = CONFIG.get().ok_or(NoMatchingConfig)?; + let to = DEFAULT_BORDER.get().ok_or(Error::NoMatchingConfig)?; + let config = CONFIG.get().ok_or(Error::NoMatchingConfig)?; let per_frame = 1.0 / config.frames_anim as f32; let (d_l, d_a, d_b) = ( (to.l - config.flash_colour.l) * per_frame, @@ -183,10 +185,8 @@ async fn interpolate_task() -> Result<(), Box> { ); let mut c = config.flash_colour; - { - let command = set_command(&c)?; - connection.run_command(command).await?; - } + connection.run_command(set_command(&c)?).await?; + let dur_per_frame = std::time::Duration::from_secs_f64(1.0 / config.refresh_rate as f64); tokio::time::sleep(dur_per_frame * config.frames_delay).await; @@ -194,22 +194,23 @@ async fn interpolate_task() -> Result<(), Box> { c.l += d_l; c.a += d_a; c.b += d_b; - { - let command = set_command(&c)?; - connection.run_command(command).await?; - } + + connection.run_command(set_command(&c)?).await?; + tokio::time::sleep(dur_per_frame).await; } connection - .run_command(DEFAULT_COLOURS.get().ok_or(NoMatchingConfig)?) + .run_command(DEFAULT_COLOURS.get().ok_or(Error::NoMatchingConfig)?) .await?; Ok(()) } -fn set_command(colour: &Lab) -> Result> { +fn set_command(colour: &Lab) -> Res { let [r, g, b] = colour.to_rgb(); Ok(format!( "{} #{r:02x}{g:02x}{b:02x}", - DEFAULT_COLOURS_NO_INDICATOR.get().ok_or(NoMatchingConfig)? + DEFAULT_COLOURS_NO_INDICATOR + .get() + .ok_or(Error::NoMatchingConfig)? )) }