use std::fmt; #[derive(Clone, Eq, PartialEq)] pub struct SecretString(String); impl SecretString { pub(crate) fn new(value: String) -> Self { Self(value) } /// Deliberate composition boundary. Never use in diagnostics or fingerprints. pub fn expose_secret(&self) -> &str { &self.0 } pub fn is_configured(&self) -> bool { !self.0.is_empty() } } impl fmt::Debug for SecretString { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter .debug_tuple("SecretString") .field(&if self.is_configured() { "configured" } else { "unconfigured" }) .finish() } } impl fmt::Display for SecretString { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(if self.is_configured() { "configured" } else { "unconfigured" }) } }