#[must_use]
pub fn strip_control_chars(s: &str) -> String {
s.chars()
.filter(|c| !c.is_control() && !matches!(*c as u32, 0x202A..=0x202E | 0x2066..=0x2069))
.collect()
}
#[must_use]
pub fn strip_control_chars_preserve_whitespace(s: &str) -> String {
s.chars()
.filter(|&c| {
(!c.is_control() || c == '\t' || c == '\n' || c == '\r')
&& !matches!(c as u32, 0x202A..=0x202E | 0x2066..=0x2069)
})
.collect()
}
#[must_use]
pub fn strip_null_bytes(s: &str) -> String {
s.chars().filter(|c| *c != '\0').collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn control_chars_removed() {
let s = "hello\x00\x01\x1f world\x7f";
assert_eq!(strip_control_chars(s), "hello world");
}
#[test]
fn bidi_overrides_removed() {
let bidi = "\u{202A}hidden\u{202C}text";
let result = strip_control_chars(bidi);
assert!(!result.contains('\u{202A}'));
assert!(!result.contains('\u{202C}'));
}
#[test]
fn normal_text_unchanged() {
assert_eq!(strip_control_chars("hello world"), "hello world");
}
#[test]
fn null_bytes_removed() {
assert_eq!(strip_null_bytes("hel\0lo"), "hello");
}
#[test]
fn null_bytes_empty_string() {
assert_eq!(strip_null_bytes(""), "");
}
}