diff options
Diffstat (limited to 'src/config')
| -rw-r--r-- | src/config/helpers.rs | 44 | 
1 files changed, 41 insertions, 3 deletions
| diff --git a/src/config/helpers.rs b/src/config/helpers.rs index ddf29ad..edf4bd5 100644 --- a/src/config/helpers.rs +++ b/src/config/helpers.rs @@ -1,8 +1,13 @@  // SPDX-FileCopyrightText: 2025 Tomasz Kramkowski <tomasz@kramkow.ski>  // SPDX-License-Identifier: GPL-3.0-or-later -use std::time::Duration; +use std::{ +    ffi::{OsStr, OsString}, +    os::unix::ffi::OsStrExt, +    time::Duration, +}; +use base64::{engine::general_purpose::STANDARD, Engine as _};  use rumqttc::QoS;  use serde::{de, Deserialize, Deserializer}; @@ -79,12 +84,44 @@ where      Ok(helper.map(|Helper(external)| external))  } +pub fn deserialize_box_slice_os_string<'de, D>(deserializer: D) -> Result<Box<[OsString]>, D::Error> +where +    D: Deserializer<'de>, +{ +    #[derive(Deserialize)] +    #[serde(untagged)] +    enum Untagged { +        String(String), +        Base64 { b64: String }, +    } + +    impl TryInto<OsString> for Untagged { +        type Error = String; +        fn try_into(self) -> Result<OsString, Self::Error> { +            match self { +                Untagged::String(s) => Ok(s.into()), +                Untagged::Base64 { b64 } => match STANDARD.decode(&b64) { +                    Err(_) => Err(b64), +                    Ok(b) => Ok(OsStr::from_bytes(&b).to_owned()), +                }, +            } +        } +    } + +    Vec::<Untagged>::deserialize(deserializer)? +        .into_iter() +        .map(TryInto::<OsString>::try_into) +        .collect::<Result<_, _>>() +        .map_err(|e| de::Error::invalid_value(de::Unexpected::Str(&e), &"valid Base64")) +} +  impl<'de> Deserialize<'de> for super::Program {      fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {          #[derive(Deserialize)]          #[serde(remote = "super::Program")]          struct Helper { -            command: Box<[String]>, +            #[serde(deserialize_with = "deserialize_box_slice_os_string")] +            command: Box<[OsString]>,              #[serde(default, deserialize_with = "deserialize_timeout_opt")]              timeout: Option<Duration>,          } @@ -92,7 +129,8 @@ impl<'de> Deserialize<'de> for super::Program {          #[derive(Deserialize)]          #[serde(untagged)]          enum Untagged { -            Short(Box<[String]>), +            #[serde(deserialize_with = "deserialize_box_slice_os_string")] +            Short(Box<[OsString]>),              #[serde(with = "Helper")]              Full(super::Program),          } | 
