1pub const LIMITE_MINIMO_MASCARAR: usize = 16;
12
13pub const CHARS_INICIO: usize = 12;
15
16pub const CHARS_FIM: usize = 4;
18
19#[must_use]
33pub fn mascarar(valor: &str) -> String {
34 let total: usize = valor.chars().count();
35
36 if total <= LIMITE_MINIMO_MASCARAR {
37 return "***".to_string();
38 }
39
40 let inicio: String = valor.chars().take(CHARS_INICIO).collect();
41 let fim: String = valor.chars().skip(total - CHARS_FIM).collect();
42
43 format!("{inicio}...{fim}")
44}
45
46#[cfg(test)]
47mod testes {
48 use super::*;
49
50 #[test]
51 fn valor_vazio_retorna_triplo_asterisco() {
52 assert_eq!(mascarar(""), "***");
53 }
54
55 #[test]
56 fn valor_curto_retorna_triplo_asterisco() {
57 assert_eq!(mascarar("abc"), "***");
58 }
59
60 #[test]
61 fn valor_com_16_caracteres_retorna_triplo_asterisco() {
62 assert_eq!(mascarar("1234567890abcdef"), "***");
63 }
64
65 #[test]
66 fn valor_com_17_caracteres_mostra_inicio_e_fim() {
67 let r = mascarar("1234567890abcdefg");
68 assert_eq!(r, "1234567890ab...defg");
69 }
70
71 #[test]
72 fn valor_longo_preserva_12_iniciais_e_4_finais() {
73 let senha = "senha-secreta-muito-longa-aqui-123456";
74 let r = mascarar(senha);
75 assert!(r.starts_with("senha-secret"));
76 assert!(r.ends_with("3456"));
77 assert!(r.contains("..."));
78 }
79
80 #[test]
81 fn valor_com_acentos_preserva_grafemas() {
82 let acentuado = "ação-configuração-senha-segura-123";
83 let r = mascarar(acentuado);
84 assert!(r.starts_with("ação-configu"));
85 assert!(r.contains("..."));
86 }
87
88 #[test]
89 fn valor_com_unicode_nao_crasha() {
90 let emojis = "🔒🔑🛡🔐✨🎉💎⚡🌟🔥🎨🚀🌈🍀🎯🎪🎭🎬🎮🎲";
91 let _ = mascarar(emojis);
92 }
93}