use std::fs; use std::path::Path; use serde::Deserialize; #[derive(Deserialize)] pub struct Config { pub influxdb: InfluxDbConfig, pub mqtt: MQTTConfig, } impl Config { pub fn load>(path: P) -> Result { let file = fs::read(path)?; let config = toml::from_slice::(&file)?; config.validate()?; Ok(config) } fn validate(&self) -> Result<(), ConfigError> { self.influxdb.validate()?; self.mqtt.validate()?; Ok(()) } } #[derive(Deserialize)] pub struct InfluxDbConfig { #[serde(default)] pub enabled: bool, #[serde(default)] pub address: String, #[serde(default)] pub user: String, #[serde(default)] pub password: String, } impl InfluxDbConfig { fn validate(&self) -> Result<(), ConfigError> { if (self.user != "") != (self.password != "") { return Err(ConfigError::Settings( "need to specify both InfluxDB user and password".to_owned(), )); } Ok(()) } } impl Default for InfluxDbConfig { fn default() -> InfluxDbConfig { InfluxDbConfig { enabled: false, address: "http://localhost:8086".to_owned(), user: "".to_owned(), password: "".to_owned(), } } } #[derive(Clone, Deserialize)] pub struct MQTTConfig { #[serde(default)] pub enabled: bool, #[serde(default)] pub address: String, } impl MQTTConfig { fn validate(&self) -> Result<(), ConfigError> { Ok(()) } } impl Default for MQTTConfig { fn default() -> MQTTConfig { MQTTConfig { enabled: false, address: "http://localhost:1883".to_owned(), } } } #[derive(thiserror::Error, Debug)] pub enum ConfigError { #[error("I/O error")] Io(#[from] std::io::Error), #[error("Parser error")] Parser(#[from] toml::de::Error), #[error("Invalid settings")] Settings(String), }