1pub mod env_var {
8 use regex::Regex;
9 use serde::{Deserialize, Deserializer};
10 use std::net::SocketAddr;
11 use std::path::PathBuf;
12
13 #[derive(Deserialize, PartialEq)]
14 struct WrappedString(String);
15
16 pub fn str<'de, D>(deserializer: D) -> Result<String, D::Error>
17 where
18 D: Deserializer<'de>,
19 {
20 let value = String::deserialize(deserializer)?;
21
22 match is_env_var(&value) {
23 true => Ok(get_env_var(&value)),
24 false => Ok(value),
25 }
26 }
27
28 pub fn opt_str<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
29 where
30 D: Deserializer<'de>,
31 {
32 Option::<WrappedString>::deserialize(deserializer).map(|option: Option<WrappedString>| {
33 option.map(|wrapped: WrappedString| {
34 let value = wrapped.0;
35
36 match is_env_var(&value) {
37 true => get_env_var(&value),
38 false => value,
39 }
40 })
41 })
42 }
43
44 pub fn socket_addr<'de, D>(deserializer: D) -> Result<SocketAddr, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 let value = String::deserialize(deserializer)?;
49
50 match is_env_var(&value) {
51 true => Ok(get_env_var(&value).parse().unwrap()),
52 false => Ok(value.parse().unwrap()),
53 }
54 }
55
56 pub fn path_buf<'de, D>(deserializer: D) -> Result<PathBuf, D::Error>
57 where
58 D: Deserializer<'de>,
59 {
60 let value = String::deserialize(deserializer)?;
61
62 match is_env_var(&value) {
63 true => Ok(PathBuf::from(get_env_var(&value))),
64 false => Ok(PathBuf::from(value)),
65 }
66 }
67
68 fn is_env_var(value: &str) -> bool {
69 Regex::new(r"^\$\{env\.\w+\}$")
70 .expect("env_var: regex is invalid")
71 .is_match(value)
72 }
73
74 fn get_env_var(wrapped_key: &str) -> String {
75 let key: String = String::from(wrapped_key)
76 .drain(6..(wrapped_key.len() - 1))
77 .collect();
78
79 std::env::var(&key).unwrap_or_else(|_| panic!("env_var: variable '{key}' is not set"))
86 }
87
88 #[cfg(test)]
89 mod tests {
90 use super::*;
91
92 #[test]
93 fn it_checks_environment_variable_patterns() {
94 assert!(is_env_var("${env.XXX}"));
95 assert!(!is_env_var("${env.XXX"));
96 assert!(!is_env_var("${env.XXX}a"));
97 assert!(!is_env_var("a${env.XXX}"));
98 assert!(!is_env_var("{env.XXX}"));
99 assert!(!is_env_var("$env.XXX}"));
100 assert!(!is_env_var("${envXXX}"));
101 assert!(!is_env_var("${.XXX}"));
102 assert!(!is_env_var("${XXX}"));
103 }
104
105 #[test]
106 fn it_gets_environment_variable() {
107 unsafe { std::env::set_var("TEST", "test") };
108
109 assert_eq!(get_env_var("${env.TEST}"), "test");
110
111 unsafe { std::env::remove_var("TEST") };
112 }
113 }
114}