From 6f3c6ec8408a34548993870202067d0229cc5800 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Sun, 26 Jan 2025 09:28:47 -0800 Subject: [PATCH] feat: var interpolation --- src/app/mod.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/app/mod.rs b/src/app/mod.rs index eec1ed7..41aa3e5 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -213,6 +213,71 @@ pub struct Data<'a> { pub sonarr_data: SonarrData<'a>, } +fn deserialize_env_var<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let s: String = String::deserialize(deserializer)?; + let interpolated = interpolate_env_vars(&s); + Ok(interpolated) +} + +fn deserialize_optional_env_var<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s: Option = Option::deserialize(deserializer)?; + match s { + Some(value) => { + let interpolated = interpolate_env_vars(&value); + Ok(Some(interpolated)) + } + None => Ok(None), + } +} + +fn deserialize_u16_env_var<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s: Option = Option::deserialize(deserializer)?; + match s { + Some(value) => { + let interpolated = interpolate_env_vars(&value); + interpolated + .parse::() + .map(Some) + .map_err(serde::de::Error::custom) + } + None => Ok(None), + } +} + +fn interpolate_env_vars(s: &str) -> String { + let mut result = s.to_string(); + let start = "${"; + let end = "}"; + + while let Some(start_index) = result.find(start) { + let end_index = result[start_index..] + .find(end) + .map(|i| start_index + i + end.len()); + if let Some(end_index) = end_index { + let var_name = &result[start_index + start.len()..end_index - end.len()]; + if let Ok(value) = std::env::var(var_name) { + // Match found; interpolate + result.replace_range(start_index..end_index, &value); + } else { + break; // No var match found; interpret it literally + } + } else { + break; // No closing brace found + } + } + + result +} + #[derive(Debug, Deserialize, Serialize, Default, Clone)] pub struct AppConfig { pub radarr: Option, @@ -260,10 +325,15 @@ impl AppConfig { #[derive(Debug, Deserialize, Serialize, Clone)] pub struct ServarrConfig { + #[serde(deserialize_with = "deserialize_optional_env_var")] pub host: Option, + #[serde(deserialize_with = "deserialize_u16_env_var")] pub port: Option, + #[serde(deserialize_with = "deserialize_optional_env_var")] pub uri: Option, + #[serde(deserialize_with = "deserialize_env_var")] pub api_token: String, + #[serde(deserialize_with = "deserialize_optional_env_var")] pub ssl_cert_path: Option, }