use derive_more::{Debug, Display};
#[derive(Clone, PartialEq, Eq, Debug, Display)]
#[debug("<redacted>")]
#[display("<redacted>")]
pub struct Redacted(String);
impl Redacted {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
pub fn expose(&self) -> &str {
&self.0
}
pub fn into_inner(self) -> String {
self.0
}
}
impl From<String> for Redacted {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for Redacted {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_is_redacted() {
let redacted = Redacted::new("secret");
assert_eq!(format!("{redacted:?}"), "<redacted>");
}
#[test]
fn display_is_redacted() {
let redacted = Redacted::new("secret");
assert_eq!(format!("{redacted}"), "<redacted>");
}
#[test]
fn expose_returns_inner() {
let redacted = Redacted::new("hunter2");
assert_eq!(redacted.expose(), "hunter2");
}
#[test]
fn into_inner_returns_owned() {
let redacted = Redacted::new("pass");
assert_eq!(redacted.into_inner(), "pass");
}
#[test]
fn from_string() {
let redacted: Redacted = "hello".to_string().into();
assert_eq!(redacted.expose(), "hello");
}
#[test]
fn from_str() {
let redacted: Redacted = "hello".into();
assert_eq!(redacted.expose(), "hello");
}
#[test]
fn equality() {
let first = Redacted::new("same");
let second = Redacted::new("same");
let third = Redacted::new("different");
assert_eq!(first, second);
assert_ne!(first, third);
}
}