use std::fmt;
use zeroize::Zeroizing;
pub struct Secret(Zeroizing<String>);
impl Secret {
pub fn new(value: impl Into<String>) -> Self {
Secret(Zeroizing::new(value.into()))
}
pub fn expose(&self) -> &str {
&self.0
}
}
impl fmt::Debug for Secret {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Secret(<redacted>)")
}
}
impl From<String> for Secret {
fn from(value: String) -> Self {
Secret::new(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_never_shows_the_value() {
let s = Secret::new("ghs_supersecret");
assert_eq!(format!("{s:?}"), "Secret(<redacted>)");
assert_eq!(s.expose(), "ghs_supersecret");
}
}