use crate::tables::Fvs;
use crate::Error;
pub(crate) const MVS: u32 = 0x180E;
pub(crate) const NIRUGU: u32 = 0x180A;
pub(crate) const ZWJ: u32 = 0x200D;
pub(crate) const NNBSP: u32 = 0x202F;
const fn is_fvs(cp: u32) -> bool {
Fvs::from_cp(cp).is_some()
}
pub(crate) const fn is_mongolian_letter_cp(cp: u32) -> bool {
if is_fvs(cp) || cp == MVS || cp == NIRUGU {
return false;
}
if cp >= 0x1800 && cp < 0x180A {
return false; }
if cp >= 0x1810 && cp < 0x181A {
return false; }
cp >= 0x1800 && cp < 0x18B0
}
pub fn is_mongolian_letter(c: char) -> bool {
is_mongolian_letter_cp(c as u32)
}
pub(crate) const fn is_mongolian_word_char_cp(cp: u32) -> bool {
is_mongolian_letter_cp(cp) || is_fvs(cp) || matches!(cp, MVS | NNBSP | NIRUGU | ZWJ)
}
pub fn is_mongolian_word_char(c: char) -> bool {
is_mongolian_word_char_cp(c as u32)
}
pub(crate) fn check_word_chars(text: &str) -> Result<(), Error> {
match text
.chars()
.enumerate()
.find(|(_, c)| !is_mongolian_word_char(*c))
{
Some((index, ch)) => Err(Error::NonMongolianChar { ch, index }),
None => Ok(()),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn letters_and_controls() {
assert!(is_mongolian_letter('\u{1820}'));
assert!(is_mongolian_letter('\u{1842}'));
assert!(is_mongolian_letter('\u{18AA}'));
assert!(is_mongolian_letter('\u{181A}')); for cp in [
0x180B, 0x180C, 0x180D, 0x180F, 0x180E, 0x180A, 0x1800, 0x1809, 0x1810, 0x1819,
] {
assert!(
!is_mongolian_letter(char::from_u32(cp).unwrap()),
"U+{cp:04X}"
);
}
assert!(!is_mongolian_letter('a'));
assert!(!is_mongolian_letter('\u{200D}'));
assert!(!is_mongolian_letter('\u{202F}'));
}
#[test]
fn word_chars() {
for cp in [0x1820, 0x180B, 0x180F, 0x180E, 0x202F, 0x180A, 0x200D] {
assert!(
is_mongolian_word_char(char::from_u32(cp).unwrap()),
"U+{cp:04X}"
);
}
for c in [' ', 'a', '\u{200C}', '\u{1800}', '\u{1810}', ','] {
assert!(!is_mongolian_word_char(c), "{c:?}");
}
}
#[test]
fn check_word_chars_reports_the_first_offender() {
assert_eq!(
check_word_chars("\u{1820}\u{180B}\u{180E}\u{180A}\u{200D}\u{202F}"),
Ok(())
);
assert_eq!(check_word_chars(""), Ok(()));
assert_eq!(
check_word_chars("\u{1820} \u{1820}x"),
Err(Error::NonMongolianChar { ch: ' ', index: 1 })
);
let message = check_word_chars("\u{1820}x").unwrap_err().to_string();
assert!(
message.starts_with("non-Mongolian character 'x' (U+0078) at index 1:"),
"{message}"
);
}
}