apollo-redaction 0.2.0

Redaction utility for sensitive data in error messages, debug logs, etc.
Documentation
use crate::RedactionStrategy;
use std::fmt;

/// Redact the entire value with asterisks, preserving length.
///
/// The output will be at least 6 asterisks to avoid leaking information about very short values.
///
/// ```rust
/// use apollo_redaction::Redacted;
/// use apollo_redaction::strategy::FullRedactor;
///
/// fn full(input: &str) -> String {
///     Redacted::<_, FullRedactor>::new(input).to_string()
/// }
///
/// assert_eq!(full("secret"), "******");
/// assert_eq!(full("verylongsecret"), "**************");
/// assert_eq!(full("abc"), "******"); // minimum 6 asterisks
/// ```
#[derive(Default, Clone)]
pub struct FullRedactor;

impl<T: AsRef<str>> RedactionStrategy<T> for FullRedactor {
    fn display(&self, value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let len = value.as_ref().chars().count().max(6);
        for _ in 0..len {
            write!(f, "*")?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::Redacted;

    fn full(input: &str) -> String {
        Redacted::<_, FullRedactor>::new(input).to_string()
    }

    #[test]
    fn test_full_redaction() {
        assert_eq!(full("secret"), "******");
        assert_eq!(full("verylongsecret"), "**************");
    }

    #[test]
    fn test_minimum_length() {
        assert_eq!(full("abc"), "******");
        assert_eq!(full("a"), "******");
        assert_eq!(full(""), "******");
    }

    #[test]
    fn test_unicode() {
        // Unicode characters should count as 1 each
        assert_eq!(full("안녕하세요한글"), "*******");
    }
}