rust_cutil/cutil/
string.rs

1pub fn is_empty_string(value: Option<String>) -> Option<String> {
2  if let Some(v) = value {
3    if !v.is_empty() {
4      return Some(v);
5    }
6  }
7  None
8}
9
10pub fn is_empty_string_ref(value: &Option<String>) -> Option<&String> {
11  if let Some(v) = value {
12    if !v.is_empty() {
13      return Some(v);
14    }
15  }
16  None
17}
18
19/// 脱密,仅保留前 1/3 和后 1/3,剩余使用 `*` 替代
20pub fn mask_sensitive(text: &str) -> String {
21  let length = text.chars().count();
22  if length == 0 {
23    return String::new();
24  }
25  if length <= 3 {
26    return text.to_string();
27  }
28
29  let front_len = length / 3;
30  let back_len = length / 3;
31  let middle_len = length - front_len - back_len;
32
33  // 预留容量:按字节长度预估,避免多次分配
34  let mut result = String::with_capacity(text.len());
35
36  for (i, ch) in text.chars().enumerate() {
37    if i < front_len || i >= length - back_len {
38      result.push(ch);
39    } else if i == front_len {
40      result.extend(std::iter::repeat('*').take(middle_len));
41    }
42  }
43
44  result
45}
46
47#[cfg(test)]
48mod tests {
49  use super::mask_sensitive;
50
51  #[test]
52  fn test_empty_string() {
53    assert_eq!(mask_sensitive(""), "");
54  }
55
56  #[test]
57  fn test_short_strings() {
58    assert_eq!(mask_sensitive("a"), "a");
59    assert_eq!(mask_sensitive("ab"), "ab");
60    assert_eq!(mask_sensitive("abc"), "abc");
61  }
62
63  #[test]
64  fn test_regular_ascii() {
65    // length = 9, front=3, back=3, middle=3
66    assert_eq!(mask_sensitive("abcdefghi"), "abc***ghi");
67    // length = 4, front=1, back=1, middle=2
68    assert_eq!(mask_sensitive("abcd"), "a**d");
69    assert_eq!(mask_sensitive("abcde"), "a***e");
70  }
71
72  #[test]
73  fn test_unicode_chars() {
74    // 5个字符:前1 后1 中间3
75    assert_eq!(mask_sensitive("你好世界啊"), "你***啊");
76  }
77}