Skip to main content

runmat_test/event/
redact.rs

1#[derive(Clone, Debug)]
2pub struct RedactionPolicy {
3    secrets: Vec<String>,
4    pub max_text_bytes: usize,
5}
6
7impl RedactionPolicy {
8    pub fn new(secrets: impl IntoIterator<Item = String>, max_text_bytes: usize) -> Self {
9        let mut secrets: Vec<_> = secrets
10            .into_iter()
11            .filter(|value| !value.is_empty())
12            .collect();
13        secrets.sort_by_key(|value| std::cmp::Reverse(value.len()));
14        secrets.dedup();
15        Self {
16            secrets,
17            max_text_bytes,
18        }
19    }
20
21    pub fn redact(&self, value: &str) -> RedactedText {
22        self.redact_with_limit(value, self.max_text_bytes)
23    }
24
25    pub fn redact_with_limit(&self, value: &str, max_text_bytes: usize) -> RedactedText {
26        let mut text = value.to_owned();
27        for secret in &self.secrets {
28            text = text.replace(secret, "[REDACTED]");
29        }
30        let truncated = text.len() > max_text_bytes;
31        if truncated {
32            let mut boundary = max_text_bytes;
33            while boundary > 0 && !text.is_char_boundary(boundary) {
34                boundary -= 1;
35            }
36            text.truncate(boundary);
37        }
38        RedactedText { text, truncated }
39    }
40}
41
42#[derive(Clone, Debug, Eq, PartialEq)]
43pub struct RedactedText {
44    pub text: String,
45    pub truncated: bool,
46}