A library for ATProtocol identities.
1//! Configuration management for AT Protocol identity operations. 2//! 3//! Environment variable utilities, DNS nameserver configuration, and TLS certificate 4//! bundle management with structured error handling. 5 6use crate::errors::ConfigError; 7use anyhow::Result; 8 9/// Certificate bundle paths for TLS verification. 10/// Contains a collection of file paths to certificate bundles. 11#[derive(Clone)] 12pub struct CertificateBundles(Vec<String>); 13 14/// DNS nameserver IP addresses for domain resolution. 15/// Contains a collection of IP addresses for custom DNS resolution. 16#[derive(Clone)] 17pub struct DnsNameservers(Vec<std::net::IpAddr>); 18 19/// Gets a required environment variable value. 20/// Returns an error if the variable is not set. 21pub fn require_env(name: &str) -> Result<String, ConfigError> { 22 std::env::var(name).map_err(|_| ConfigError::MissingEnvironmentVariable { 23 name: name.to_string(), 24 }) 25} 26 27/// Gets an optional environment variable value. 28/// Returns empty string if the variable is not set. 29pub fn optional_env(name: &str) -> String { 30 std::env::var(name).unwrap_or("".to_string()) 31} 32 33/// Gets an environment variable value with a fallback default. 34/// Returns the default value if the variable is not set. 35pub fn default_env(name: &str, default_value: &str) -> String { 36 std::env::var(name).unwrap_or(default_value.to_string()) 37} 38 39/// Gets the application version from git hash or package version. 40/// Returns the git hash if available, otherwise falls back to cargo package version. 41pub fn version() -> Result<String, ConfigError> { 42 option_env!("GIT_HASH") 43 .or(option_env!("CARGO_PKG_VERSION")) 44 .map(|val| val.to_string()) 45 .ok_or(ConfigError::VersionNotAvailable) 46} 47 48impl TryFrom<String> for CertificateBundles { 49 type Error = anyhow::Error; 50 fn try_from(value: String) -> Result<Self, Self::Error> { 51 Ok(Self( 52 value 53 .split(';') 54 .filter_map(|s| { 55 if s.is_empty() { 56 None 57 } else { 58 Some(s.to_string()) 59 } 60 }) 61 .collect::<Vec<String>>(), 62 )) 63 } 64} 65impl AsRef<Vec<String>> for CertificateBundles { 66 fn as_ref(&self) -> &Vec<String> { 67 &self.0 68 } 69} 70 71impl TryFrom<String> for DnsNameservers { 72 type Error = anyhow::Error; 73 fn try_from(value: String) -> Result<Self, Self::Error> { 74 // Allow empty value for default DNS configuration 75 if value.is_empty() { 76 return Ok(Self(Vec::new())); 77 } 78 79 let nameservers = value 80 .split(';') 81 .map(|s| s.trim()) 82 .filter(|s| !s.is_empty()) 83 .map(|s| { 84 s.parse::<std::net::IpAddr>().map_err(|_| { 85 anyhow::Error::from(ConfigError::InvalidNameserverIP { 86 value: s.to_string(), 87 }) 88 }) 89 }) 90 .collect::<Result<Vec<std::net::IpAddr>, _>>()?; 91 92 Ok(Self(nameservers)) 93 } 94} 95 96impl AsRef<Vec<std::net::IpAddr>> for DnsNameservers { 97 fn as_ref(&self) -> &Vec<std::net::IpAddr> { 98 &self.0 99 } 100}