1#[must_use]
4pub fn misleads_display(character: char) -> bool {
5 character.is_control()
6 || matches!(
7 character,
8 '\u{00AD}'
9 | '\u{0600}'..='\u{0605}'
10 | '\u{061C}'
11 | '\u{06DD}'
12 | '\u{070F}'
13 | '\u{0890}'..='\u{0891}'
14 | '\u{08E2}'
15 | '\u{115F}'..='\u{1160}'
16 | '\u{180E}'
17 | '\u{200B}'
18 | '\u{200E}'..='\u{200F}'
19 | '\u{2028}'..='\u{202E}'
20 | '\u{2060}'..='\u{2064}'
21 | '\u{2066}'..='\u{206F}'
22 | '\u{3164}'
23 | '\u{FEFF}'
24 | '\u{FFA0}'
25 | '\u{FFF9}'..='\u{FFFB}'
26 | '\u{110BD}'
27 | '\u{110CD}'
28 | '\u{13430}'..='\u{1343F}'
29 | '\u{1BCA0}'..='\u{1BCA3}'
30 | '\u{1D173}'..='\u{1D17A}'
31 | '\u{E0001}'
32 | '\u{E0020}'..='\u{E007F}'
33 )
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn refuses_reordering_and_hiding_but_keeps_joiners() {
42 for refused in [
43 '\u{0}', '\n', '\u{1B}', '\u{202E}', '\u{2067}', '\u{200B}', '\u{FEFF}', '\u{200F}',
44 '\u{061C}', '\u{2028}',
45 ] {
46 assert!(misleads_display(refused), "{refused:?}");
47 }
48 for kept in ['a', 'é', 'ş', '\u{200C}', '\u{200D}', ' '] {
49 assert!(!misleads_display(kept), "{kept:?}");
50 }
51 }
52
53 #[test]
54 fn refuses_every_format_character_and_the_hangul_fillers() {
55 for invisible in [
56 '\u{00AD}',
57 '\u{3164}',
58 '\u{E0067}',
59 '\u{2062}',
60 '\u{180E}',
61 '\u{206A}',
62 '\u{FFFB}',
63 '\u{0601}',
64 '\u{1BCA0}',
65 '\u{1D173}',
66 ] {
67 assert!(misleads_display(invisible), "{invisible:?}");
68 }
69 }
70}