Skip to main content

apollo_redaction/strategy/
first4.rs

1use crate::RedactionStrategy;
2use std::fmt;
3
4/// Redact all but the first 4 characters.
5///
6/// Useful for API keys or tokens where the prefix identifies the key type.
7///
8/// If the value has 4 or fewer characters, outputs at least 4 asterisks
9/// to avoid leaking information about short values.
10///
11/// ```rust
12/// use apollo_redaction::Redacted;
13/// use apollo_redaction::strategy::First4Redactor;
14///
15/// fn first4(input: &str) -> String {
16///     Redacted::<_, First4Redactor>::new(input).to_string()
17/// }
18///
19/// assert_eq!(first4("sk_live_abc123"), "sk_l****");
20/// assert_eq!(first4("abc"), "****");
21/// assert_eq!(first4("api_key_secret"), "api_****");
22/// ```
23#[derive(Default, Clone)]
24pub struct First4Redactor;
25
26impl<T: AsRef<str>> RedactionStrategy<T> for First4Redactor {
27    fn display(&self, value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        let s = value.as_ref();
29        let len = s.chars().count();
30
31        if len <= 4 {
32            write!(f, "****")
33        } else {
34            for c in s.chars().take(4) {
35                write!(f, "{c}")?;
36            }
37            write!(f, "****")
38        }
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use crate::Redacted;
46
47    fn first4(input: &str) -> String {
48        Redacted::<_, First4Redactor>::new(input).to_string()
49    }
50
51    #[test]
52    fn test_first4() {
53        assert_eq!(first4("sk_live_abc123"), "sk_l****");
54        assert_eq!(first4("api_key_secret"), "api_****");
55    }
56
57    #[test]
58    fn test_short_input() {
59        assert_eq!(first4("abc"), "****");
60        assert_eq!(first4("abcd"), "****");
61        assert_eq!(first4("a"), "****");
62        assert_eq!(first4(""), "****");
63    }
64
65    #[test]
66    fn test_exactly_5_chars() {
67        assert_eq!(first4("12345"), "1234****");
68    }
69
70    #[test]
71    fn test_unicode() {
72        assert_eq!(first4("안녕하세요한글"), "안녕하세****");
73    }
74}