aboutsummaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
authorTomasz Kramkowski <tomasz@kramkow.ski>2025-07-19 21:25:35 +0100
committerTomasz Kramkowski <tomasz@kramkow.ski>2025-07-19 21:25:35 +0100
commite6ac7b1643e01764c5fccddee985d25bf53494e2 (patch)
treedf999692c1bd8428c4719e165a8af3955f958444 /src/config
parent36cccea315e6ac0898210cf4fcc365cc10027ef3 (diff)
downloadmqttr-e6ac7b1643e01764c5fccddee985d25bf53494e2.tar.gz
mqttr-e6ac7b1643e01764c5fccddee985d25bf53494e2.tar.xz
mqttr-e6ac7b1643e01764c5fccddee985d25bf53494e2.zip
Shorter helpers
Diffstat (limited to 'src/config')
-rw-r--r--src/config/helpers.rs163
1 files changed, 56 insertions, 107 deletions
diff --git a/src/config/helpers.rs b/src/config/helpers.rs
index 17dbe35..ddf29ad 100644
--- a/src/config/helpers.rs
+++ b/src/config/helpers.rs
@@ -1,13 +1,10 @@
// SPDX-FileCopyrightText: 2025 Tomasz Kramkowski <tomasz@kramkow.ski>
// SPDX-License-Identifier: GPL-3.0-or-later
-use std::{fmt, time::Duration};
+use std::time::Duration;
use rumqttc::QoS;
-use serde::{
- de::{self, Visitor},
- Deserialize, Deserializer,
-};
+use serde::{de, Deserialize, Deserializer};
#[allow(clippy::enum_variant_names)]
#[derive(Deserialize, Debug)]
@@ -34,19 +31,15 @@ pub fn deserialize_timeout<'de, D>(deserializer: D) -> Result<Duration, D::Error
where
D: Deserializer<'de>,
{
- struct DurationVisitor;
-
- impl<'de> de::Visitor<'de> for DurationVisitor {
- type Value = Duration;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("a positive number")
- }
+ #[derive(Deserialize)]
+ #[serde(untagged)]
+ enum Untagged {
+ Int(i64),
+ Float(f64),
+ }
- fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
+ Ok(match Untagged::deserialize(deserializer)? {
+ Untagged::Int(v) => {
if v < 0 {
return Err(de::Error::invalid_value(
de::Unexpected::Signed(v),
@@ -54,16 +47,12 @@ where
));
}
if v == 0 {
- Ok(Duration::MAX)
+ Duration::MAX
} else {
- Ok(Duration::from_secs(v as u64))
+ Duration::from_secs(v as u64)
}
}
-
- fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
+ Untagged::Float(v) => {
if v < 0.0 {
return Err(de::Error::invalid_value(
de::Unexpected::Float(v),
@@ -71,14 +60,12 @@ where
));
}
if v == 0.0 {
- Ok(Duration::MAX)
+ Duration::MAX
} else {
- Ok(Duration::from_secs_f64(v))
+ Duration::from_secs_f64(v)
}
}
- }
-
- deserializer.deserialize_any(DurationVisitor)
+ })
}
pub fn deserialize_timeout_opt<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
@@ -94,94 +81,56 @@ where
impl<'de> Deserialize<'de> for super::Program {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
- struct VecOrProgram;
-
- impl<'de> Visitor<'de> for VecOrProgram {
- type Value = super::Program;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("map or seq")
- }
-
- fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
- where
- A: serde::de::SeqAccess<'de>,
- {
- let vec: Box<[String]> =
- Deserialize::deserialize(de::value::SeqAccessDeserializer::new(seq))?;
- Ok(super::Program {
- command: vec,
- timeout: None,
- })
- }
-
- fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
- where
- A: serde::de::MapAccess<'de>,
- {
- #[derive(Deserialize)]
- struct Helper {
- command: Box<[String]>,
- #[serde(default, deserialize_with = "deserialize_timeout_opt")]
- timeout: Option<Duration>,
- }
+ #[derive(Deserialize)]
+ #[serde(remote = "super::Program")]
+ struct Helper {
+ command: Box<[String]>,
+ #[serde(default, deserialize_with = "deserialize_timeout_opt")]
+ timeout: Option<Duration>,
+ }
- let helper: Helper =
- Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?;
- Ok(super::Program {
- command: helper.command,
- timeout: helper.timeout,
- })
- }
+ #[derive(Deserialize)]
+ #[serde(untagged)]
+ enum Untagged {
+ Short(Box<[String]>),
+ #[serde(with = "Helper")]
+ Full(super::Program),
}
- deserializer.deserialize_any(VecOrProgram)
+ Ok(match Untagged::deserialize(deserializer)? {
+ Untagged::Short(command) => super::Program {
+ command,
+ timeout: None,
+ },
+ Untagged::Full(program) => program,
+ })
}
}
impl<'de> Deserialize<'de> for super::Route {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
- struct VecOrRoute;
-
- impl<'de> Visitor<'de> for VecOrRoute {
- type Value = super::Route;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("map or seq")
- }
-
- fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
- where
- A: serde::de::SeqAccess<'de>,
- {
- let vec: Box<[super::Program]> =
- Deserialize::deserialize(de::value::SeqAccessDeserializer::new(seq))?;
- Ok(super::Route {
- programs: vec,
- qos: None,
- })
- }
-
- fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
- where
- A: serde::de::MapAccess<'de>,
- {
- #[derive(Deserialize)]
- struct Helper {
- programs: Box<[super::Program]>,
- #[serde(default, deserialize_with = "deserialize_qos_opt")]
- qos: Option<QoS>,
- }
+ #[derive(Deserialize)]
+ #[serde(remote = "super::Route")]
+ struct Helper {
+ programs: Box<[super::Program]>,
+ #[serde(default, deserialize_with = "deserialize_qos_opt")]
+ qos: Option<QoS>,
+ }
- let helper: Helper =
- Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?;
- Ok(super::Route {
- programs: helper.programs,
- qos: helper.qos,
- })
- }
+ #[derive(Deserialize)]
+ #[serde(untagged)]
+ enum Untagged {
+ Short(Box<[super::Program]>),
+ #[serde(with = "Helper")]
+ Full(super::Route),
}
- deserializer.deserialize_any(VecOrRoute)
+ Ok(match Untagged::deserialize(deserializer)? {
+ Untagged::Short(programs) => super::Route {
+ programs,
+ qos: None,
+ },
+ Untagged::Full(route) => route,
+ })
}
}