unicode_normalize_aligned/
quick_check.rs1use crate::props::{Props, QuickCheck};
4use crate::UnicodeNormalization;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum IsNormalized {
13 Yes,
15 No,
17 Maybe,
19}
20
21#[derive(Clone, Copy)]
22enum Form {
23 Nfc,
24 Nfd,
25 Nfkc,
26 Nfkd,
27}
28
29fn quick_check<I: Iterator<Item = char>>(s: I, form: Form) -> IsNormalized {
30 let mut last_ccc = 0u8;
31 let mut result = IsNormalized::Yes;
32 for c in s {
33 if (c as u32) < 0x80 {
34 last_ccc = 0;
35 continue;
36 }
37 let p = Props::of(c);
38 let ccc = p.ccc();
39 if ccc != 0 && last_ccc > ccc {
40 return IsNormalized::No;
41 }
42 let qc = match form {
43 Form::Nfc => p.nfc_qc(),
44 Form::Nfkc => p.nfkc_qc(),
45 Form::Nfd => {
46 if p.nfd_no() {
47 QuickCheck::No
48 } else {
49 QuickCheck::Yes
50 }
51 }
52 Form::Nfkd => {
53 if p.nfkd_no() {
54 QuickCheck::No
55 } else {
56 QuickCheck::Yes
57 }
58 }
59 };
60 match qc {
61 QuickCheck::No => return IsNormalized::No,
62 QuickCheck::Maybe => result = IsNormalized::Maybe,
63 QuickCheck::Yes => {}
64 }
65 last_ccc = ccc;
66 }
67 result
68}
69
70pub fn is_nfc_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
72 quick_check(s, Form::Nfc)
73}
74
75pub fn is_nfd_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
77 quick_check(s, Form::Nfd)
78}
79
80pub fn is_nfkc_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
82 quick_check(s, Form::Nfkc)
83}
84
85pub fn is_nfkd_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
87 quick_check(s, Form::Nfkd)
88}
89
90pub fn is_nfc(s: &str) -> bool {
93 match is_nfc_quick(s.chars()) {
94 IsNormalized::Yes => true,
95 IsNormalized::No => false,
96 IsNormalized::Maybe => s.nfc().map(|p| p.0).eq(s.chars()),
97 }
98}
99
100pub fn is_nfd(s: &str) -> bool {
103 match is_nfd_quick(s.chars()) {
104 IsNormalized::Yes => true,
105 IsNormalized::No => false,
106 IsNormalized::Maybe => s.nfd().map(|p| p.0).eq(s.chars()),
107 }
108}
109
110pub fn is_nfkc(s: &str) -> bool {
113 match is_nfkc_quick(s.chars()) {
114 IsNormalized::Yes => true,
115 IsNormalized::No => false,
116 IsNormalized::Maybe => s.nfkc().map(|p| p.0).eq(s.chars()),
117 }
118}
119
120pub fn is_nfkd(s: &str) -> bool {
123 match is_nfkd_quick(s.chars()) {
124 IsNormalized::Yes => true,
125 IsNormalized::No => false,
126 IsNormalized::Maybe => s.nfkd().map(|p| p.0).eq(s.chars()),
127 }
128}