pub fn terminal_safe(text: &str) -> String {
text.chars()
.map(|c| match c {
c if c.is_control() => char::REPLACEMENT_CHARACTER,
'\u{202A}'..='\u{202E}' | '\u{2066}'..='\u{2069}' => char::REPLACEMENT_CHARACTER,
c => c,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::terminal_safe;
#[test]
fn table_text_cannot_carry_terminal_control_sequences() {
for hostile in [
"\u{1b}[31mroot\u{1b}[0m",
"\u{1b}[2J\u{1b}[H",
"\u{1b}]52;c;bWFsaWNl\u{7}",
"admin\r\nfake row",
"bell\u{7}",
"nul\u{0}byte",
"c1\u{9b}31m",
"\u{202e}moc.live@nimda",
] {
let safe = terminal_safe(hostile);
assert!(
!safe.chars().any(|c| c.is_control()
|| ('\u{202A}'..='\u{202E}').contains(&c)
|| ('\u{2066}'..='\u{2069}').contains(&c)),
"{safe:?} still carries a control character"
);
assert_eq!(safe.chars().count(), hostile.chars().count());
}
}
#[test]
fn table_text_leaves_ordinary_names_alone() {
for benign in [
"Ada Lovelace",
"ada@example.com",
"Gerd Zellweger",
"Ólafur Þórðarson",
"\u{5f20}\u{4f1f}",
"\u{645}\u{62d}\u{645}\u{62f}",
"tenant-1_a.b",
"",
] {
assert_eq!(terminal_safe(benign), benign);
}
}
}