use core::fmt;
use unic_char_property::{CharProperty, NumericCharProperty, TotalCharProperty};
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct CanonicalCombiningClass(u8);
impl CharProperty for CanonicalCombiningClass {
fn prop_abbr_name() -> &'static str {
"ccc"
}
fn prop_long_name() -> &'static str {
"Canonical_Combining_Class"
}
fn prop_human_name() -> &'static str {
"Canonical Combining Class"
}
}
impl TotalCharProperty for CanonicalCombiningClass {
fn of(ch: char) -> Self {
Self::of(ch)
}
}
impl NumericCharProperty<u8> for CanonicalCombiningClass {
fn number(&self) -> u8 {
Self::number(self)
}
}
mod data {
use super::CanonicalCombiningClass;
use unic_char_property::tables::CharDataTable;
pub const CANONICAL_COMBINING_CLASS_VALUES: CharDataTable<CanonicalCombiningClass> =
include!("../tables/canonical_combining_class_values.rsv");
}
#[cfg_attr(rustfmt, rustfmt_skip)] #[allow(non_upper_case_globals)]
impl CanonicalCombiningClass {
pub fn of(ch: char) -> CanonicalCombiningClass {
data::CANONICAL_COMBINING_CLASS_VALUES.find_or_default(ch)
}
pub const NotReordered: CanonicalCombiningClass = CanonicalCombiningClass(0);
pub const Overlay: CanonicalCombiningClass = CanonicalCombiningClass(1);
pub const Nukta: CanonicalCombiningClass = CanonicalCombiningClass(7);
pub const KanaVoicing: CanonicalCombiningClass = CanonicalCombiningClass(8);
pub const Virama: CanonicalCombiningClass = CanonicalCombiningClass(9);
pub const AttatchedBelowLeft: CanonicalCombiningClass = CanonicalCombiningClass(200);
pub const AttachedBelow: CanonicalCombiningClass = CanonicalCombiningClass(202);
pub const AttachedBelowRight: CanonicalCombiningClass = CanonicalCombiningClass(204);
pub const AttachedLeft: CanonicalCombiningClass = CanonicalCombiningClass(208);
pub const AttachedRight: CanonicalCombiningClass = CanonicalCombiningClass(210);
pub const AttachedAboveLeft: CanonicalCombiningClass = CanonicalCombiningClass(212);
pub const AttatchedAbove: CanonicalCombiningClass = CanonicalCombiningClass(214);
pub const AttatchedAboveRight: CanonicalCombiningClass = CanonicalCombiningClass(216);
pub const BelowLeft: CanonicalCombiningClass = CanonicalCombiningClass(218);
pub const Below: CanonicalCombiningClass = CanonicalCombiningClass(220);
pub const BelowRight: CanonicalCombiningClass = CanonicalCombiningClass(222);
pub const Left: CanonicalCombiningClass = CanonicalCombiningClass(224);
pub const Right: CanonicalCombiningClass = CanonicalCombiningClass(226);
pub const AboveLeft: CanonicalCombiningClass = CanonicalCombiningClass(228);
pub const Above: CanonicalCombiningClass = CanonicalCombiningClass(230);
pub const AboveRight: CanonicalCombiningClass = CanonicalCombiningClass(232);
pub const DoubleBelow: CanonicalCombiningClass = CanonicalCombiningClass(233);
pub const DoubleAbove: CanonicalCombiningClass = CanonicalCombiningClass(234);
pub const IotaSubscript: CanonicalCombiningClass = CanonicalCombiningClass(240);
}
impl fmt::Display for CanonicalCombiningClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.number())
}
}
impl CanonicalCombiningClass {
pub fn number(&self) -> u8 {
self.0
}
pub fn is_not_reordered(&self) -> bool {
self.0 == 0
}
pub fn is_reordered(&self) -> bool {
self.0 != 0
}
}
#[cfg(test)]
mod tests {
use super::CanonicalCombiningClass as CCC;
#[test]
fn test_ascii() {
assert_eq!(CCC::of('\u{0000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0040}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0041}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0062}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{007F}'), CCC::NotReordered);
}
#[test]
fn test_bmp() {
assert_eq!(CCC::of('\u{0300}'), CCC::Above);
assert_eq!(CCC::of('\u{0314}'), CCC::Above);
assert_eq!(CCC::of('\u{0315}'), CCC::AboveRight);
assert_eq!(CCC::of('\u{0316}'), CCC::Below);
assert_eq!(CCC::of('\u{0319}'), CCC::Below);
assert_eq!(CCC::of('\u{0590}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{05D0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{05D1}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{05FF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0600}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0627}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{064B}'), CCC(27));
assert_eq!(CCC::of('\u{064C}'), CCC(28));
assert_eq!(CCC::of('\u{064D}'), CCC(29));
assert_eq!(CCC::of('\u{064E}'), CCC(30));
assert_eq!(CCC::of('\u{064F}'), CCC(31));
assert_eq!(CCC::of('\u{0650}'), CCC(32));
assert_eq!(CCC::of('\u{0651}'), CCC(33));
assert_eq!(CCC::of('\u{0652}'), CCC(34));
assert_eq!(CCC::of('\u{07BF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{07C0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{085F}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0860}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{0870}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{089F}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{08A0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{089F}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{08FF}'), CCC::Above);
assert_eq!(CCC::of('\u{20A0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{20CF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FB1D}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FB4F}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FB50}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDCF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDF0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDFF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FE70}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FEFE}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FEFF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDD0}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDD1}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDEE}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FDEF}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FFFE}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{FFFF}'), CCC::NotReordered);
}
#[test]
fn test_smp() {
assert_eq!(CCC::of('\u{10000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{101fc}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{101fd}'), CCC::Below);
assert_eq!(CCC::of('\u{101fe}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{1e000}'), CCC::Above);
assert_eq!(CCC::of('\u{1e949}'), CCC::Above);
assert_eq!(CCC::of('\u{1e94a}'), CCC(7));
assert_eq!(CCC::of('\u{1e94b}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{1efff}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{1fffe}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{1ffff}'), CCC::NotReordered);
}
#[test]
fn test_unassigned_planes() {
assert_eq!(CCC::of('\u{30000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{40000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{50000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{60000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{70000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{80000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{90000}'), CCC::NotReordered);
assert_eq!(CCC::of('\u{a0000}'), CCC::NotReordered);
}
#[test]
fn test_number() {
assert_eq!(CCC::of('\u{0000}').number(), 0);
assert_eq!(CCC::of('\u{0300}').number(), 230);
assert_eq!(CCC::of('\u{0315}').number(), 232);
assert_eq!(CCC::of('\u{1e94a}').number(), 7);
}
}