api_scanner/scanner/common/
string_utils.rs1pub fn redact_secret(s: &str, keep_chars: usize) -> String {
2 let chars: Vec<char> = s.chars().collect();
3 if chars.len() <= keep_chars * 2 {
4 return "*".repeat(chars.len());
5 }
6
7 let head: String = chars[..keep_chars].iter().collect();
8 let tail: String = chars[chars.len() - keep_chars..].iter().collect();
9 let stars = "*".repeat(chars.len().saturating_sub(keep_chars * 2).min(12));
10 format!("{head}{stars}{tail}")
11}
12
13pub fn snippet(s: &str, max_len: usize) -> String {
14 if s.len() <= max_len {
15 s.to_string()
16 } else {
17 let boundary = s
18 .char_indices()
19 .take_while(|&(i, _)| i < max_len)
20 .last()
21 .map(|(i, c)| i + c.len_utf8())
22 .unwrap_or(0);
23 format!("{}... ({} bytes total)", &s[..boundary], s.len())
24 }
25}
26
27pub fn slugify(s: &str) -> String {
28 let mut result = String::with_capacity(s.len());
29 let mut prev_dash = false;
30
31 for c in s.chars() {
32 if c.is_ascii_alphanumeric() {
33 result.push(c.to_ascii_lowercase());
34 prev_dash = false;
35 } else if !prev_dash {
36 result.push('-');
37 prev_dash = true;
38 }
39 }
40
41 result.trim_matches('-').to_string()
43}