#[derive(Clone)]
pub struct Token(String);
impl Token {
pub fn as_str(&self) -> &str {
&self.0
}
pub fn new<S: Into<String>>(s: S) -> Self {
Self(s.into())
}
}
impl std::fmt::Debug for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Token(<redacted; {} chars>)", self.0.len())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_format_redacts_body() {
let t = Token::new("my-secret-token-value");
let s = format!("{t:?}");
assert!(!s.contains("my-secret-token-value"), "got: {s}");
assert!(s.contains("redacted"), "got: {s}");
}
#[test]
fn debug_format_includes_length_for_diagnostics() {
let t = Token::new("abcd");
let s = format!("{t:?}");
assert!(s.contains("4"), "got: {s}");
}
#[test]
fn as_str_returns_underlying_value() {
let t = Token::new("plain");
assert_eq!(t.as_str(), "plain");
}
#[test]
fn does_not_implement_display() {
fn _is_not_display<T>(_: &T)
where
T: ?Sized,
{
}
let t = Token::new("plain");
_is_not_display(&t);
}
}