use std::borrow::Cow;
pub fn control_picture(ch: char) -> Option<char> {
match ch {
'\n' | '\t' => None,
'\u{0}'..='\u{1f}' => char::from_u32(0x2400 + ch as u32),
'\u{7f}' => Some('\u{2421}'), '\u{80}'..='\u{9f}' => Some('\u{fffd}'), _ => None,
}
}
pub fn printable(text: &str) -> Cow<'_, str> {
if !text.chars().any(|ch| control_picture(ch).is_some()) {
return Cow::Borrowed(text);
}
Cow::Owned(
text.chars()
.map(|ch| control_picture(ch).unwrap_or(ch))
.collect(),
)
}
pub fn sanitize_key_text(text: &str) -> String {
text.chars()
.filter(|ch| !ch.is_control() && !matches!(*ch, '\u{f700}'..='\u{f8ff}'))
.collect()
}
#[cfg(test)]
mod tests {
use super::{printable, sanitize_key_text};
use std::borrow::Cow;
#[test]
fn printable_leaves_ordinary_text_borrowed() {
assert!(matches!(printable("Deployment [RL]"), Cow::Borrowed(_)));
assert_eq!(printable("Ünïcödé — 😀\tok\n"), "Ünïcödé — 😀\tok\n");
}
#[test]
fn printable_substitutes_control_pictures() {
assert_eq!(printable("Depl\u{1b}oyment"), "Depl␛oyment");
assert_eq!(printable("\u{0}\u{7}\u{1f}"), "␀␇␟");
assert_eq!(printable("\u{7f}"), "␡");
assert_eq!(printable("\u{85}"), "\u{fffd}");
}
#[test]
fn printable_preserves_char_count_so_measurements_stay_aligned() {
let text = "a\u{1b}b\u{7f}c";
assert_eq!(printable(text).chars().count(), text.chars().count());
}
#[test]
fn sanitize_key_text_keeps_ordinary_typed_text() {
assert_eq!(sanitize_key_text("a"), "a");
assert_eq!(sanitize_key_text("Ünïcödé — ok 😀"), "Ünïcödé — ok 😀");
assert_eq!(sanitize_key_text(" "), " ");
}
#[test]
fn sanitize_key_text_drops_control_and_function_key_codepoints() {
assert_eq!(sanitize_key_text("\u{1b}"), "");
assert_eq!(sanitize_key_text("\t"), "");
assert_eq!(sanitize_key_text("\r"), "");
assert_eq!(sanitize_key_text("\u{f704}"), "");
assert_eq!(sanitize_key_text("a\u{1b}b"), "ab");
}
}