1pub use secrecy::{ExposeSecret, SecretString};
2
3pub fn redact(value: &str) -> String {
6 let len = value.chars().count();
7 if len < 8 {
8 return "****".to_string();
9 }
10 let tail: String = value.chars().skip(len - 4).collect();
11 format!("****{tail}")
12}
13
14#[cfg(test)]
15#[allow(clippy::unwrap_used)]
16mod tests {
17 use super::*;
18
19 #[test]
20 fn redacts_short_values_entirely() {
21 assert_eq!(redact("abc"), "****");
22 assert_eq!(redact(""), "****");
23 }
24
25 #[test]
26 fn redacts_all_but_last_four() {
27 assert_eq!(redact("ATATT3xFfGF0abcd"), "****abcd");
28 }
29
30 #[test]
31 fn redaction_never_contains_the_secret_prefix() {
32 let secret = "ATATT3xFfGF0_super_secret_value";
33 let shown = redact(secret);
34 assert!(!shown.contains("ATATT"), "prefix leaked: {shown}");
35 assert!(!shown.contains("super_secret"), "body leaked: {shown}");
36 }
37}