runmat_test/event/
redact.rs1#[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}