secret_string/
lib.rs

1//! A wrapper around strings that hides their contents when printed or
2//! formatted for debugging.
3
4#![deny(warnings)]
5#![warn(unused_extern_crates)]
6#![deny(clippy::todo)]
7#![deny(clippy::unimplemented)]
8#![deny(clippy::unwrap_used)]
9#![deny(clippy::expect_used)]
10#![deny(clippy::panic)]
11#![deny(clippy::unreachable)]
12#![deny(clippy::await_holding_lock)]
13#![deny(clippy::needless_pass_by_value)]
14#![deny(clippy::trivially_copy_pass_by_ref)]
15
16use std::fmt::Debug;
17
18/// A string wrapper that hides its contents when printed or formatted for
19/// debugging.
20/// # Examples
21/// ```
22/// use secret_string::SecretString;
23/// let secret = SecretString::new("my_secret_password");
24/// assert_eq!(format!("{}", secret), "******************");
25/// assert_eq!(format!("{:?}", secret), "SecretString(******************)");
26/// assert_eq!(secret.value(), "my_secret_password");
27pub struct SecretString<T>(T)
28where
29    T: AsRef<str>;
30
31impl<T: AsRef<str>> SecretString<T> {
32    pub fn new(s: T) -> Self {
33        SecretString(s)
34    }
35
36    pub fn value(&self) -> &str {
37        self.0.as_ref()
38    }
39
40    fn as_stars(&self) -> String {
41        self.0.as_ref().bytes().map(|_| "*").collect::<String>()
42    }
43}
44
45impl<T: AsRef<str>> std::fmt::Display for SecretString<T> {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        write!(f, "{}", self.as_stars())
48    }
49}
50
51impl Debug for SecretString<&str> {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        write!(f, "SecretString({})", self.as_stars())
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::SecretString;
60
61    #[test]
62    fn test_secret_string_display() {
63        let secret = SecretString::new("my_secret_password");
64        assert_eq!(format!("{}", secret), "******************");
65    }
66
67    #[test]
68    fn test_secret_string_debug() {
69        let secret = SecretString::new("my_secret_password");
70        assert_eq!(format!("{:?}", secret), "SecretString(******************)");
71    }
72    #[test]
73    fn test_secret_string_value() {
74        let secret = SecretString::new("my_secret_password");
75        assert_eq!(secret.value(), "my_secret_password");
76    }
77}