#![deny(unsafe_code)]
#![forbid(missing_docs)]
extern crate unic_ucd_core;
mod composition;
mod gen_cat;
mod hangul;
pub use composition::{canonical_decomposition, compatibility_decomposition, canonical_composition,
canonical_combining_class};
pub use gen_cat::is_combining_mark;
use std::cmp::Ordering;
use std::ops::FnMut;
use unic_ucd_core::UnicodeVersion;
pub const UNICODE_VERSION: UnicodeVersion = include!("tables/unicode_version.rsv");
pub fn decompose_canonical<F>(c: char, mut i: F)
where
F: FnMut(char),
{
d(c, &mut i, false);
}
pub fn decompose_compatible<F>(c: char, mut i: F)
where
F: FnMut(char),
{
d(c, &mut i, true);
}
fn d<F>(c: char, i: &mut F, k: bool)
where
F: FnMut(char),
{
if c <= '\x7f' {
(*i)(c);
return;
}
if (c as u32) >= hangul::S_BASE && (c as u32) < (hangul::S_BASE + hangul::S_COUNT) {
hangul::decompose(c, i);
return;
}
match canonical_decomposition(c) {
Some(canon) => {
for x in canon {
d(*x, i, k);
}
return;
}
None => (),
}
if !k {
(*i)(c);
return;
}
match compatibility_decomposition(c) {
Some(compat) => {
for x in compat {
d(*x, i, k);
}
return;
}
None => (),
}
(*i)(c);
}
pub fn compose(a: char, b: char) -> Option<char> {
hangul::compose(a, b).or_else(|| match canonical_composition(a) {
None => None,
Some(candidates) => {
match candidates.binary_search_by(|&(val, _)| if b == val {
Ordering::Equal
} else if val < b {
Ordering::Less
} else {
Ordering::Greater
}) {
Ok(idx) => {
let (_, result) = candidates[idx];
Some(result)
}
Err(_) => None,
}
}
})
}