From 70ace076f8722c985614907ea5cb0d7ec9d5a0bf Mon Sep 17 00:00:00 2001 From: Fl1tzi Date: Mon, 22 May 2023 01:41:53 +0200 Subject: [PATCH] move config into its own mod --- src/config.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/device.rs | 3 +- src/main.rs | 69 +++++--------------------------------- 3 files changed, 103 insertions(+), 62 deletions(-) create mode 100644 src/config.rs diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..19225c8 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,93 @@ +use crate::Config; +use dirs::config_dir; +use tracing::debug; +use std::{ + fmt::{self, Display}, + env, + fs, + io::ErrorKind, + path::PathBuf +}; + +/// The name of the folder which holds the config +pub const CONFIG_FOLDER_NAME: &'static str = "virtual-deck"; + +#[tracing::instrument] +pub fn load_config() -> Result { + let config_file: PathBuf = match env::var_os("DACH_DECKER_CONFIG") { + Some(path) => { + debug!("Using env variable: {:?}", path); + PathBuf::from(path) + }, + None => { + // try to get the system config dir; env var required if not available + if let Some(mut path) = config_dir() { + path.push(CONFIG_FOLDER_NAME); + path.push("config.toml"); + debug!("Using system path: {:?}", path); + path + } else { + return Err(ConfigError::PathNotAvailable()) + } + } + }; + + let path = config_file.display().to_string().clone(); + + match fs::read_to_string(config_file) { + Ok(content) => toml::from_str(&content).map_err(|e| ConfigError::SyntaxError(e.to_string())), + Err(file_error) => { + if file_error.kind() == ErrorKind::NotFound { + return Err(ConfigError::FilePathDoesNotExist(path)) + } else { + return Err(ConfigError::ReadError(file_error.to_string())) + } + } + } +} + +#[derive(Debug)] +pub enum ConfigError { + ButtonDoesNotExist(u8), + ModuleDoesNotExist(u8, String), + PathNotAvailable(), + SyntaxError(String), + FilePathDoesNotExist(String), + ReadError(String) +} + + +impl Display for ConfigError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { + ConfigError::ButtonDoesNotExist(index) => { + write!(formatter, "Button {}: does not exist.", index) + } + ConfigError::ModuleDoesNotExist(index, module) => write!( + formatter, + "Button {}: The module \"{}\" does not exist.", + index, module + ), + ConfigError::PathNotAvailable() => write!( + formatter, + "Config directory not available. Please use the environment variable \"DACH_DECKER_CONFIG\" to specify the location of the config." + ), + ConfigError::SyntaxError(text) => write!( + formatter, + "Syntax error in configuration:\n{}", + text + ), + ConfigError::FilePathDoesNotExist(path) => write!( + formatter, + "The configuration file does not exist in {}", + path + ), + ConfigError::ReadError(error) => write!( + formatter, + "Could not read the configuration file: {}", + error + ) + } + } +} + diff --git a/src/device.rs b/src/device.rs index 5715aa8..a69aad7 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,6 +1,7 @@ use crate::{ modules::{retrieve_module_from_name, start_module, HostEvent}, - skip_if_none, unwrap_or_error, Button, ConfigError, DeviceConfig, + config::ConfigError, + skip_if_none, unwrap_or_error, Button, DeviceConfig, }; use deck_driver as streamdeck; use hidapi::HidApi; diff --git a/src/main.rs b/src/main.rs index d910186..5a02090 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,27 +4,20 @@ use hidapi::HidApi; use serde::Deserialize; use std::{ collections::HashMap, - env, - fmt::{self, Display}, - fs, - io::ErrorKind, - path::PathBuf, - process::exit, sync::Arc, - time::Duration, + time::Duration, process::exit, }; use tracing::{debug, error, info, warn}; use tracing_subscriber::{ self, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter, }; -use dirs::config_dir; +use config::load_config; mod device; mod modules; +mod config; -/// The name of the folder which holds the config -pub const CONFIG_FOLDER_NAME: &'static str = "virtual-deck"; #[macro_export] macro_rules! skip_if_none { @@ -67,41 +60,14 @@ fn main() { .with(fmt_layer) .init(); - // ------ LOAD CONFIG - - let config_file: PathBuf = match env::var_os("DACH_DECKER_CONFIG") { - Some(path) => PathBuf::from(path), - None => { - if let Some(mut path) = config_dir() { - path.push(CONFIG_FOLDER_NAME); - path.push("config.toml"); - path - } else { - error!("Please use the \"DACH_DECKER_CONFIG\" environment variable to provide a path to your config"); - exit(1); - } + let config = match load_config() { + Ok(config) => config, + Err(e) => { + error!("{}", e); + exit(1) } }; - info!("Loading configuration from \"{}\"", config_file.display()); - - let config: Config = match fs::read_to_string(config_file) { - Ok(content) => match toml::from_str(&content) { - Ok(c) => c, - Err(e) => { - error!("Error detected in configuration:\n{}", e); - exit(1); - } - }, - Err(file_error) => { - if file_error.kind() == ErrorKind::NotFound { - error!("Unable to load configuration because the file does not exist. Please create the configuration file."); - } else { - error!("Cannot open the configuration file: {}", file_error); - } - exit(1); - } - }; debug!("{:#?}", config); let hid = streamdeck::new_hidapi().expect("Could not create HidApi"); @@ -190,25 +156,6 @@ pub async fn start_device( } } -pub enum ConfigError { - ButtonDoesNotExist(u8), - ModuleDoesNotExist(u8, String), -} - -impl Display for ConfigError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - ConfigError::ButtonDoesNotExist(index) => { - write!(formatter, "Button {}: does not exist.", index) - } - ConfigError::ModuleDoesNotExist(index, module) => write!( - formatter, - "Button {}: The module \"{}\" does not exist.", - index, module - ), - } - } -} #[derive(Deserialize, Debug, Clone)] pub struct DeviceConfig {