From 917ed77255ade0b51d4677f934d707870a3622ab Mon Sep 17 00:00:00 2001 From: RGBCube Date: Wed, 4 Jun 2025 21:33:32 +0300 Subject: [PATCH] config: fix serde --- config.toml | 1 + src/config.rs | 75 ++++++++++++++++++++++++++++++++++++++++++--------- src/main.rs | 4 +-- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/config.toml b/config.toml index 2f796b7..04159cd 100644 --- a/config.toml +++ b/config.toml @@ -1,2 +1,3 @@ [[rule]] priority = 0 +if = { value = "%cpu-usage", is-more-than = 0.7 } diff --git a/src/config.rs b/src/config.rs index c82169a..365970e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -155,33 +155,79 @@ impl PowerDelta { } } +macro_rules! named { + ($variant:ident => $value:literal) => { + pub mod $variant { + pub fn serialize(serializer: S) -> Result { + serializer.serialize_str($value) + } + + pub fn deserialize<'de, D: serde::Deserializer<'de>>( + deserializer: D, + ) -> Result<(), D::Error> { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = (); + + fn expecting(&self, writer: &mut std::fmt::Formatter) -> std::fmt::Result { + writer.write_str(concat!("\"", $value, "\"")) + } + + fn visit_str(self, value: &str) -> Result { + if value != $value { + return Err(E::invalid_value(serde::de::Unexpected::Str(value), &self)); + } + + Ok(()) + } + } + + deserializer.deserialize_str(Visitor) + } + } + }; +} + +mod expression { + named!(cpu_usage => "%cpu-usage"); + named!(cpu_usage_volatility => "$cpu-usage-volatility"); + named!(cpu_temperature => "$cpu-temperature"); + named!(cpu_temperature_volatility => "$cpu-temperature-volatility"); + named!(cpu_idle_seconds => "$cpu-idle-seconds"); + named!(power_supply_charge => "%power-supply-charge"); + named!(power_supply_discharge_rate => "%power-supply-discharge-rate"); + named!(charging => "?charging"); + named!(on_battery => "?on-battery"); +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] -#[serde(untagged, rename_all = "kebab-case")] +#[serde(untagged)] pub enum Expression { - #[serde(rename = "%cpu-usage")] + #[serde(with = "expression::cpu_usage")] CpuUsage, - #[serde(rename = "$cpu-usage-volatility")] + #[serde(with = "expression::cpu_usage_volatility")] CpuUsageVolatility, - #[serde(rename = "$cpu-temperature")] + #[serde(with = "expression::cpu_temperature")] CpuTemperature, - #[serde(rename = "$cpu-temperature-volatility")] + #[serde(with = "expression::cpu_temperature_volatility")] CpuTemperatureVolatility, - #[serde(rename = "$cpu-idle-seconds")] + #[serde(with = "expression::cpu_idle_seconds")] CpuIdleSeconds, - #[serde(rename = "%power-supply-charge")] + #[serde(with = "expression::power_supply_charge")] PowerSupplyCharge, - #[serde(rename = "%power-supply-discharge-rate")] + #[serde(with = "expression::power_supply_discharge_rate")] PowerSupplyDischargeRate, - #[serde(rename = "?charging")] + #[serde(with = "expression::charging")] Charging, - #[serde(rename = "?on-battery")] + #[serde(with = "expression::on_battery")] OnBattery, Boolean(bool), @@ -209,16 +255,18 @@ pub enum Expression { divide: Box, }, + #[serde(rename_all = "kebab-case")] LessThan { value: Box, is_less_than: Box, }, - + #[serde(rename_all = "kebab-case")] MoreThan { value: Box, is_more_than: Box, }, + #[serde(rename_all = "kebab-case")] Equal { value: Box, is_equal: Box, @@ -297,7 +345,8 @@ impl DaemonConfig { format!("failed to read config from '{path}'", path = path.display()) })?; - let mut config: Self = toml::from_str(&contents).context("failed to parse config file")?; + let mut config: Self = toml::from_str(&contents) + .with_context(|| format!("failed to parse file at '{path}'", path = path.display(),))?; { let mut priorities = Vec::with_capacity(config.rules.len()); @@ -313,6 +362,8 @@ impl DaemonConfig { config.rules.sort_by_key(|rule| rule.priority); + log::debug!("loaded config: {config:#?}"); + Ok(config) } } diff --git a/src/main.rs b/src/main.rs index 5b56d92..feed86a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,8 +86,8 @@ fn real_main() -> anyhow::Result<()> { match cli.command { Command::Watt { config, .. } => { - let config = config::DaemonConfig::load_from(&config) - .context("failed to load daemon config file")?; + let config = + config::DaemonConfig::load_from(&config).context("failed to load daemon config")?; daemon::run(config) }