use crate::props::{Props, QuickCheck};
use crate::UnicodeNormalization;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IsNormalized {
Yes,
No,
Maybe,
}
#[derive(Clone, Copy)]
enum Form {
Nfc,
Nfd,
Nfkc,
Nfkd,
}
fn quick_check<I: Iterator<Item = char>>(s: I, form: Form) -> IsNormalized {
let mut last_ccc = 0u8;
let mut result = IsNormalized::Yes;
for c in s {
if (c as u32) < 0x80 {
last_ccc = 0;
continue;
}
let p = Props::of(c);
let ccc = p.ccc();
if ccc != 0 && last_ccc > ccc {
return IsNormalized::No;
}
let qc = match form {
Form::Nfc => p.nfc_qc(),
Form::Nfkc => p.nfkc_qc(),
Form::Nfd => {
if p.nfd_no() {
QuickCheck::No
} else {
QuickCheck::Yes
}
}
Form::Nfkd => {
if p.nfkd_no() {
QuickCheck::No
} else {
QuickCheck::Yes
}
}
};
match qc {
QuickCheck::No => return IsNormalized::No,
QuickCheck::Maybe => result = IsNormalized::Maybe,
QuickCheck::Yes => {}
}
last_ccc = ccc;
}
result
}
pub fn is_nfc_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
quick_check(s, Form::Nfc)
}
pub fn is_nfd_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
quick_check(s, Form::Nfd)
}
pub fn is_nfkc_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
quick_check(s, Form::Nfkc)
}
pub fn is_nfkd_quick<I: Iterator<Item = char>>(s: I) -> IsNormalized {
quick_check(s, Form::Nfkd)
}
pub fn is_nfc(s: &str) -> bool {
match is_nfc_quick(s.chars()) {
IsNormalized::Yes => true,
IsNormalized::No => false,
IsNormalized::Maybe => s.nfc().map(|p| p.0).eq(s.chars()),
}
}
pub fn is_nfd(s: &str) -> bool {
match is_nfd_quick(s.chars()) {
IsNormalized::Yes => true,
IsNormalized::No => false,
IsNormalized::Maybe => s.nfd().map(|p| p.0).eq(s.chars()),
}
}
pub fn is_nfkc(s: &str) -> bool {
match is_nfkc_quick(s.chars()) {
IsNormalized::Yes => true,
IsNormalized::No => false,
IsNormalized::Maybe => s.nfkc().map(|p| p.0).eq(s.chars()),
}
}
pub fn is_nfkd(s: &str) -> bool {
match is_nfkd_quick(s.chars()) {
IsNormalized::Yes => true,
IsNormalized::No => false,
IsNormalized::Maybe => s.nfkd().map(|p| p.0).eq(s.chars()),
}
}