pub(crate) fn is_combining_mark(c: char) -> bool {
let code = c as u32;
matches!(code,
0x0300..=0x036F
| 0x1AB0..=0x1AFF
| 0x1DC0..=0x1DFF
| 0xFE20..=0xFE2F
| 0x0901..=0x0903
| 0x093E..=0x094D
| 0x0E31..=0x0E3A
| 0x0E47..=0x0E4E
| 0x0981..=0x0983
| 0x09BE..=0x09CD
| 0x0A01..=0x0A03
| 0x0A3E..=0x0A4D
| 0x0B01..=0x0B03
| 0x0B3E..=0x0B4D
| 0x0F82..=0x0F84
| 0x0F86..=0x0F8B
)
}
pub(crate) fn is_variation_selector(c: char) -> bool {
let code = c as u32;
matches!(code, 0xFE00..=0xFE0F)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_predicates_cover_their_documented_ranges() {
assert!(is_combining_mark('\u{0301}'), "U+0301 is a combining acute");
assert!(is_combining_mark('\u{093E}'), "U+093E is a Devanagari matra");
assert!(is_variation_selector('\u{FE0F}'), "U+FE0F is the emoji variation selector");
assert!(!is_combining_mark('a'), "a base letter is not a mark");
assert!(!is_variation_selector('a'), "a base letter is not a selector");
assert!(!is_variation_selector('\u{FE10}'), "the selector range must not over-reach");
}
}