#[cfg(feature = "intl")]
use intl::unicode::Script;
#[derive(Clone, Copy)]
pub(crate) enum PropEscape {
Binary(BinProp),
Gc(GcSel),
Script(ScriptId),
ScriptExt(ScriptId),
}
#[derive(Clone, Copy)]
pub(crate) enum BinProp {
Ascii,
AsciiHexDigit,
Alphabetic,
Any,
Assigned,
BidiControl,
BidiMirrored,
CaseIgnorable,
Cased,
ChangesWhenCasefolded,
ChangesWhenCasemapped,
ChangesWhenLowercased,
ChangesWhenNfkcCasefolded,
ChangesWhenTitlecased,
ChangesWhenUppercased,
Dash,
DefaultIgnorable,
Deprecated,
Diacritic,
Emoji,
EmojiComponent,
EmojiModifier,
EmojiModifierBase,
EmojiPresentation,
ExtendedPictographic,
Extender,
GraphemeBase,
GraphemeExtend,
HexDigit,
IdsBinaryOperator,
IdsTrinaryOperator,
IdContinue,
IdStart,
Ideographic,
JoinControl,
LogicalOrderException,
Lowercase,
Math,
NoncharacterCodePoint,
PatternSyntax,
PatternWhiteSpace,
QuotationMark,
Radical,
RegionalIndicator,
SentenceTerminal,
SoftDotted,
TerminalPunctuation,
UnifiedIdeograph,
Uppercase,
VariationSelector,
WhiteSpace,
XidContinue,
XidStart,
}
#[derive(Clone, Copy)]
pub(crate) enum GcSel {
Group(u8),
Sub([u8; 2]),
CasedLetter,
}
#[cfg(feature = "intl")]
#[derive(Clone, Copy)]
pub(crate) struct ScriptId(Script);
#[cfg(not(feature = "intl"))]
#[derive(Clone, Copy)]
pub(crate) struct ScriptId;
pub(crate) fn resolve_lone(name: &str) -> Option<PropEscape> {
if let Some(b) = binary_property(name) {
return Some(PropEscape::Binary(b));
}
gc_value(name).map(PropEscape::Gc)
}
#[must_use]
pub(crate) fn is_property_of_strings(name: &str) -> bool {
matches!(
name,
"Basic_Emoji"
| "Emoji_Keycap_Sequence"
| "RGI_Emoji"
| "RGI_Emoji_Flag_Sequence"
| "RGI_Emoji_Modifier_Sequence"
| "RGI_Emoji_Tag_Sequence"
| "RGI_Emoji_ZWJ_Sequence"
)
}
pub(crate) fn resolve_pair(name: &str, value: &str) -> Option<PropEscape> {
match name {
"General_Category" | "gc" => gc_value(value).map(PropEscape::Gc),
"Script" | "sc" => script_id(value).map(PropEscape::Script),
"Script_Extensions" | "scx" => script_id(value).map(PropEscape::ScriptExt),
_ => None,
}
}
fn binary_property(name: &str) -> Option<BinProp> {
use BinProp::*;
Some(match name {
"ASCII" => Ascii,
"AHex" | "ASCII_Hex_Digit" => AsciiHexDigit,
"Alpha" | "Alphabetic" => Alphabetic,
"Any" => Any,
"Assigned" => Assigned,
"Bidi_C" | "Bidi_Control" => BidiControl,
"Bidi_M" | "Bidi_Mirrored" => BidiMirrored,
"CI" | "Case_Ignorable" => CaseIgnorable,
"Cased" => Cased,
"CWCF" | "Changes_When_Casefolded" => ChangesWhenCasefolded,
"CWCM" | "Changes_When_Casemapped" => ChangesWhenCasemapped,
"CWL" | "Changes_When_Lowercased" => ChangesWhenLowercased,
"CWKCF" | "Changes_When_NFKC_Casefolded" => ChangesWhenNfkcCasefolded,
"CWT" | "Changes_When_Titlecased" => ChangesWhenTitlecased,
"CWU" | "Changes_When_Uppercased" => ChangesWhenUppercased,
"Dash" => Dash,
"DI" | "Default_Ignorable_Code_Point" => DefaultIgnorable,
"Dep" | "Deprecated" => Deprecated,
"Dia" | "Diacritic" => Diacritic,
"Emoji" => Emoji,
"EComp" | "Emoji_Component" => EmojiComponent,
"EMod" | "Emoji_Modifier" => EmojiModifier,
"EBase" | "Emoji_Modifier_Base" => EmojiModifierBase,
"EPres" | "Emoji_Presentation" => EmojiPresentation,
"ExtPict" | "Extended_Pictographic" => ExtendedPictographic,
"Ext" | "Extender" => Extender,
"Gr_Base" | "Grapheme_Base" => GraphemeBase,
"Gr_Ext" | "Grapheme_Extend" => GraphemeExtend,
"Hex" | "Hex_Digit" => HexDigit,
"IDSB" | "IDS_Binary_Operator" => IdsBinaryOperator,
"IDST" | "IDS_Trinary_Operator" => IdsTrinaryOperator,
"IDC" | "ID_Continue" => IdContinue,
"IDS" | "ID_Start" => IdStart,
"Ideo" | "Ideographic" => Ideographic,
"Join_C" | "Join_Control" => JoinControl,
"LOE" | "Logical_Order_Exception" => LogicalOrderException,
"Lower" | "Lowercase" => Lowercase,
"Math" => Math,
"NChar" | "Noncharacter_Code_Point" => NoncharacterCodePoint,
"Pat_Syn" | "Pattern_Syntax" => PatternSyntax,
"Pat_WS" | "Pattern_White_Space" => PatternWhiteSpace,
"QMark" | "Quotation_Mark" => QuotationMark,
"Radical" => Radical,
"RI" | "Regional_Indicator" => RegionalIndicator,
"STerm" | "Sentence_Terminal" => SentenceTerminal,
"SD" | "Soft_Dotted" => SoftDotted,
"Term" | "Terminal_Punctuation" => TerminalPunctuation,
"UIdeo" | "Unified_Ideograph" => UnifiedIdeograph,
"Upper" | "Uppercase" => Uppercase,
"VS" | "Variation_Selector" => VariationSelector,
"White_Space" | "space" => WhiteSpace,
"XIDC" | "XID_Continue" => XidContinue,
"XIDS" | "XID_Start" => XidStart,
_ => return None,
})
}
fn gc_value(name: &str) -> Option<GcSel> {
let code: &str = match name {
"Other" => "C",
"Letter" => "L",
"Cased_Letter" | "LC" => return Some(GcSel::CasedLetter),
"Mark" | "Combining_Mark" => "M",
"Number" => "N",
"Punctuation" | "punct" => "P",
"Symbol" => "S",
"Separator" => "Z",
"Uppercase_Letter" => "Lu",
"Lowercase_Letter" => "Ll",
"Titlecase_Letter" => "Lt",
"Modifier_Letter" => "Lm",
"Other_Letter" => "Lo",
"Nonspacing_Mark" => "Mn",
"Spacing_Mark" => "Mc",
"Enclosing_Mark" => "Me",
"Decimal_Number" | "digit" => "Nd",
"Letter_Number" => "Nl",
"Other_Number" => "No",
"Connector_Punctuation" => "Pc",
"Dash_Punctuation" => "Pd",
"Open_Punctuation" => "Ps",
"Close_Punctuation" => "Pe",
"Initial_Punctuation" => "Pi",
"Final_Punctuation" => "Pf",
"Other_Punctuation" => "Po",
"Math_Symbol" => "Sm",
"Currency_Symbol" => "Sc",
"Modifier_Symbol" => "Sk",
"Other_Symbol" => "So",
"Space_Separator" => "Zs",
"Line_Separator" => "Zl",
"Paragraph_Separator" => "Zp",
"Control" | "cntrl" => "Cc",
"Format" => "Cf",
"Surrogate" => "Cs",
"Private_Use" => "Co",
"Unassigned" => "Cn",
other => other,
};
const SUBCATS: [&str; 30] = [
"Lu", "Ll", "Lt", "Lm", "Lo", "Mn", "Mc", "Me", "Nd", "Nl", "No", "Pc", "Pd", "Ps", "Pe",
"Pi", "Pf", "Po", "Sm", "Sc", "Sk", "So", "Zs", "Zl", "Zp", "Cc", "Cf", "Cs", "Co", "Cn",
];
let b = code.as_bytes();
match code {
"L" | "M" | "N" | "P" | "S" | "Z" | "C" => Some(GcSel::Group(b[0])),
_ if SUBCATS.contains(&code) => Some(GcSel::Sub([b[0], b[1]])),
_ => None,
}
}
#[cfg(feature = "intl")]
fn script_id(name: &str) -> Option<ScriptId> {
let s = match name {
"Adlam" | "Adlm" => Script::Adlam,
"Ahom" => Script::Ahom,
"Anatolian_Hieroglyphs" | "Hluw" => Script::AnatolianHieroglyphs,
"Arabic" | "Arab" => Script::Arabic,
"Armenian" | "Armn" => Script::Armenian,
"Avestan" | "Avst" => Script::Avestan,
"Balinese" | "Bali" => Script::Balinese,
"Bamum" | "Bamu" => Script::Bamum,
"Bassa_Vah" | "Bass" => Script::BassaVah,
"Batak" | "Batk" => Script::Batak,
"Bengali" | "Beng" => Script::Bengali,
"Beria_Erfe" | "Berf" => Script::BeriaErfe,
"Bhaiksuki" | "Bhks" => Script::Bhaiksuki,
"Bopomofo" | "Bopo" => Script::Bopomofo,
"Brahmi" | "Brah" => Script::Brahmi,
"Braille" | "Brai" => Script::Braille,
"Buginese" | "Bugi" => Script::Buginese,
"Buhid" | "Buhd" => Script::Buhid,
"Canadian_Aboriginal" | "Cans" => Script::CanadianAboriginal,
"Carian" | "Cari" => Script::Carian,
"Caucasian_Albanian" | "Aghb" => Script::CaucasianAlbanian,
"Chakma" | "Cakm" => Script::Chakma,
"Cham" => Script::Cham,
"Cherokee" | "Cher" => Script::Cherokee,
"Chorasmian" | "Chrs" => Script::Chorasmian,
"Common" | "Zyyy" => Script::Common,
"Coptic" | "Copt" | "Qaac" => Script::Coptic,
"Cuneiform" | "Xsux" => Script::Cuneiform,
"Cypriot" | "Cprt" => Script::Cypriot,
"Cypro_Minoan" | "Cpmn" => Script::CyproMinoan,
"Cyrillic" | "Cyrl" => Script::Cyrillic,
"Deseret" | "Dsrt" => Script::Deseret,
"Devanagari" | "Deva" => Script::Devanagari,
"Dives_Akuru" | "Diak" => Script::DivesAkuru,
"Dogra" | "Dogr" => Script::Dogra,
"Duployan" | "Dupl" => Script::Duployan,
"Egyptian_Hieroglyphs" | "Egyp" => Script::EgyptianHieroglyphs,
"Elbasan" | "Elba" => Script::Elbasan,
"Elymaic" | "Elym" => Script::Elymaic,
"Ethiopic" | "Ethi" => Script::Ethiopic,
"Garay" | "Gara" => Script::Garay,
"Georgian" | "Geor" => Script::Georgian,
"Glagolitic" | "Glag" => Script::Glagolitic,
"Gothic" | "Goth" => Script::Gothic,
"Grantha" | "Gran" => Script::Grantha,
"Greek" | "Grek" => Script::Greek,
"Gujarati" | "Gujr" => Script::Gujarati,
"Gunjala_Gondi" | "Gong" => Script::GunjalaGondi,
"Gurmukhi" | "Guru" => Script::Gurmukhi,
"Gurung_Khema" | "Gukh" => Script::GurungKhema,
"Han" | "Hani" => Script::Han,
"Hangul" | "Hang" => Script::Hangul,
"Hanifi_Rohingya" | "Rohg" => Script::HanifiRohingya,
"Hanunoo" | "Hano" => Script::Hanunoo,
"Hatran" | "Hatr" => Script::Hatran,
"Hebrew" | "Hebr" => Script::Hebrew,
"Hiragana" | "Hira" => Script::Hiragana,
"Imperial_Aramaic" | "Armi" => Script::ImperialAramaic,
"Inherited" | "Zinh" | "Qaai" => Script::Inherited,
"Inscriptional_Pahlavi" | "Phli" => Script::InscriptionalPahlavi,
"Inscriptional_Parthian" | "Prti" => Script::InscriptionalParthian,
"Javanese" | "Java" => Script::Javanese,
"Kaithi" | "Kthi" => Script::Kaithi,
"Kannada" | "Knda" => Script::Kannada,
"Katakana" | "Kana" => Script::Katakana,
"Kawi" => Script::Kawi,
"Kayah_Li" | "Kali" => Script::KayahLi,
"Kharoshthi" | "Khar" => Script::Kharoshthi,
"Khitan_Small_Script" | "Kits" => Script::KhitanSmallScript,
"Khmer" | "Khmr" => Script::Khmer,
"Khojki" | "Khoj" => Script::Khojki,
"Khudawadi" | "Sind" => Script::Khudawadi,
"Kirat_Rai" | "Krai" => Script::KiratRai,
"Lao" | "Laoo" => Script::Lao,
"Latin" | "Latn" => Script::Latin,
"Lepcha" | "Lepc" => Script::Lepcha,
"Limbu" | "Limb" => Script::Limbu,
"Linear_A" | "Lina" => Script::LinearA,
"Linear_B" | "Linb" => Script::LinearB,
"Lisu" => Script::Lisu,
"Lycian" | "Lyci" => Script::Lycian,
"Lydian" | "Lydi" => Script::Lydian,
"Mahajani" | "Mahj" => Script::Mahajani,
"Makasar" | "Maka" => Script::Makasar,
"Malayalam" | "Mlym" => Script::Malayalam,
"Mandaic" | "Mand" => Script::Mandaic,
"Manichaean" | "Mani" => Script::Manichaean,
"Marchen" | "Marc" => Script::Marchen,
"Masaram_Gondi" | "Gonm" => Script::MasaramGondi,
"Medefaidrin" | "Medf" => Script::Medefaidrin,
"Meetei_Mayek" | "Mtei" => Script::MeeteiMayek,
"Mende_Kikakui" | "Mend" => Script::MendeKikakui,
"Meroitic_Cursive" | "Merc" => Script::MeroiticCursive,
"Meroitic_Hieroglyphs" | "Mero" => Script::MeroiticHieroglyphs,
"Miao" | "Plrd" => Script::Miao,
"Modi" => Script::Modi,
"Mongolian" | "Mong" => Script::Mongolian,
"Mro" | "Mroo" => Script::Mro,
"Multani" | "Mult" => Script::Multani,
"Myanmar" | "Mymr" => Script::Myanmar,
"Nabataean" | "Nbat" => Script::Nabataean,
"Nag_Mundari" | "Nagm" => Script::NagMundari,
"Nandinagari" | "Nand" => Script::Nandinagari,
"New_Tai_Lue" | "Talu" => Script::NewTaiLue,
"Newa" => Script::Newa,
"Nko" | "Nkoo" => Script::Nko,
"Nushu" | "Nshu" => Script::Nushu,
"Nyiakeng_Puachue_Hmong" | "Hmnp" => Script::NyiakengPuachueHmong,
"Ogham" | "Ogam" => Script::Ogham,
"Ol_Chiki" | "Olck" => Script::OlChiki,
"Ol_Onal" | "Onao" => Script::OlOnal,
"Old_Hungarian" | "Hung" => Script::OldHungarian,
"Old_Italic" | "Ital" => Script::OldItalic,
"Old_North_Arabian" | "Narb" => Script::OldNorthArabian,
"Old_Permic" | "Perm" => Script::OldPermic,
"Old_Persian" | "Xpeo" => Script::OldPersian,
"Old_Sogdian" | "Sogo" => Script::OldSogdian,
"Old_South_Arabian" | "Sarb" => Script::OldSouthArabian,
"Old_Turkic" | "Orkh" => Script::OldTurkic,
"Old_Uyghur" | "Ougr" => Script::OldUyghur,
"Oriya" | "Orya" => Script::Oriya,
"Osage" | "Osge" => Script::Osage,
"Osmanya" | "Osma" => Script::Osmanya,
"Pahawh_Hmong" | "Hmng" => Script::PahawhHmong,
"Palmyrene" | "Palm" => Script::Palmyrene,
"Pau_Cin_Hau" | "Pauc" => Script::PauCinHau,
"Phags_Pa" | "Phag" => Script::PhagsPa,
"Phoenician" | "Phnx" => Script::Phoenician,
"Psalter_Pahlavi" | "Phlp" => Script::PsalterPahlavi,
"Rejang" | "Rjng" => Script::Rejang,
"Runic" | "Runr" => Script::Runic,
"Samaritan" | "Samr" => Script::Samaritan,
"Saurashtra" | "Saur" => Script::Saurashtra,
"Sharada" | "Shrd" => Script::Sharada,
"Shavian" | "Shaw" => Script::Shavian,
"Siddham" | "Sidd" => Script::Siddham,
"Sidetic" | "Sidt" => Script::Sidetic,
"SignWriting" | "Sgnw" => Script::SignWriting,
"Sinhala" | "Sinh" => Script::Sinhala,
"Sogdian" | "Sogd" => Script::Sogdian,
"Sora_Sompeng" | "Sora" => Script::SoraSompeng,
"Soyombo" | "Soyo" => Script::Soyombo,
"Sundanese" | "Sund" => Script::Sundanese,
"Sunuwar" | "Sunu" => Script::Sunuwar,
"Syloti_Nagri" | "Sylo" => Script::SylotiNagri,
"Syriac" | "Syrc" => Script::Syriac,
"Tagalog" | "Tglg" => Script::Tagalog,
"Tagbanwa" | "Tagb" => Script::Tagbanwa,
"Tai_Le" | "Tale" => Script::TaiLe,
"Tai_Tham" | "Lana" => Script::TaiTham,
"Tai_Viet" | "Tavt" => Script::TaiViet,
"Tai_Yo" | "Tayo" => Script::TaiYo,
"Takri" | "Takr" => Script::Takri,
"Tamil" | "Taml" => Script::Tamil,
"Tangsa" | "Tnsa" => Script::Tangsa,
"Tangut" | "Tang" => Script::Tangut,
"Telugu" | "Telu" => Script::Telugu,
"Thaana" | "Thaa" => Script::Thaana,
"Thai" => Script::Thai,
"Tibetan" | "Tibt" => Script::Tibetan,
"Tifinagh" | "Tfng" => Script::Tifinagh,
"Tirhuta" | "Tirh" => Script::Tirhuta,
"Todhri" | "Todr" => Script::Todhri,
"Tolong_Siki" | "Tols" => Script::TolongSiki,
"Toto" => Script::Toto,
"Tulu_Tigalari" | "Tutg" => Script::TuluTigalari,
"Ugaritic" | "Ugar" => Script::Ugaritic,
"Vai" | "Vaii" => Script::Vai,
"Vithkuqi" | "Vith" => Script::Vithkuqi,
"Wancho" | "Wcho" => Script::Wancho,
"Warang_Citi" | "Wara" => Script::WarangCiti,
"Yezidi" | "Yezi" => Script::Yezidi,
"Yi" | "Yiii" => Script::Yi,
"Zanabazar_Square" | "Zanb" => Script::ZanabazarSquare,
"Unknown" | "Zzzz" => Script::Unknown,
_ => return None,
};
Some(ScriptId(s))
}
#[cfg(not(feature = "intl"))]
fn script_id(name: &str) -> Option<ScriptId> {
if name.is_empty() {
None
} else {
Some(ScriptId)
}
}
impl PropEscape {
pub(crate) fn matches(self, cp: u32) -> bool {
match self {
PropEscape::Binary(b) => b.matches(cp),
PropEscape::Gc(sel) => sel.matches(cp),
PropEscape::Script(id) => script_of(cp) == Some(id),
PropEscape::ScriptExt(id) => script_ext_contains(cp, id),
}
}
}
impl PartialEq for ScriptId {
fn eq(&self, other: &Self) -> bool {
#[cfg(feature = "intl")]
{
self.0 == other.0
}
#[cfg(not(feature = "intl"))]
{
let _ = other;
false
}
}
}
#[cfg(feature = "intl")]
fn script_of(cp: u32) -> Option<ScriptId> {
Some(ScriptId(intl::unicode::script_u32(cp)))
}
#[cfg(not(feature = "intl"))]
fn script_of(_cp: u32) -> Option<ScriptId> {
None
}
#[cfg(feature = "intl")]
fn script_ext_contains(cp: u32, id: ScriptId) -> bool {
intl::unicode::script_extensions_u32(cp).contains(id.0)
}
#[cfg(not(feature = "intl"))]
fn script_ext_contains(_cp: u32, _id: ScriptId) -> bool {
false
}
impl GcSel {
fn matches(self, cp: u32) -> bool {
match self {
GcSel::Group(g) => gc_group_matches(g, cp),
GcSel::Sub(code) => gc_sub_matches(code, cp),
GcSel::CasedLetter => {
gc_sub_matches(*b"Lu", cp)
|| gc_sub_matches(*b"Ll", cp)
|| gc_sub_matches(*b"Lt", cp)
}
}
}
}
#[cfg(feature = "intl")]
fn gc_group_matches(g: u8, cp: u32) -> bool {
use intl::unicode::category::Group;
let want = match g {
b'L' => Group::Letter,
b'M' => Group::Mark,
b'N' => Group::Number,
b'P' => Group::Punctuation,
b'S' => Group::Symbol,
b'Z' => Group::Separator,
b'C' => Group::Other,
_ => return false,
};
intl::unicode::general_category_u32(cp).group() == want
}
#[cfg(feature = "intl")]
fn gc_sub_matches(code: [u8; 2], cp: u32) -> bool {
intl::unicode::general_category_u32(cp).abbr().as_bytes() == code
}
#[cfg(not(feature = "intl"))]
fn gc_group_matches(g: u8, cp: u32) -> bool {
let Some(c) = char::from_u32(cp) else {
return g == b'C';
};
match g {
b'L' => c.is_alphabetic(),
b'N' => c.is_numeric(),
b'Z' => c == ' ' || (c.is_whitespace() && !c.is_control()),
b'C' => c.is_control(),
b'P' => c.is_ascii_punctuation(),
_ => false,
}
}
#[cfg(not(feature = "intl"))]
fn gc_sub_matches(code: [u8; 2], cp: u32) -> bool {
let Some(c) = char::from_u32(cp) else {
return &code == b"Cs";
};
match &code {
b"Lu" => c.is_uppercase(),
b"Ll" => c.is_lowercase(),
b"Lt" => false,
b"Lo" => c.is_alphabetic() && !c.is_uppercase() && !c.is_lowercase(),
b"Nd" => c.is_ascii_digit(),
b"Cc" => c.is_control(),
_ => false,
}
}
impl BinProp {
fn matches(self, cp: u32) -> bool {
use BinProp::*;
match self {
Ascii => cp <= 0x7F,
AsciiHexDigit => {
matches!(cp, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66)
}
Any => cp <= 0x10_FFFF,
BidiControl => {
matches!(cp, 0x061C | 0x200E | 0x200F | 0x202A..=0x202E | 0x2066..=0x2069)
}
JoinControl => matches!(cp, 0x200C | 0x200D),
RegionalIndicator => matches!(cp, 0x1F1E6..=0x1F1FF),
NoncharacterCodePoint => {
matches!(cp, 0xFDD0..=0xFDEF) || (cp & 0xFFFE) == 0xFFFE && cp <= 0x10_FFFF
}
VariationSelector => {
matches!(cp, 0x180B..=0x180D | 0x180F | 0xFE00..=0xFE0F | 0xE0100..=0xE01EF)
}
other => other.matches_table(cp),
}
}
#[cfg(feature = "intl")]
fn matches_table(self, cp: u32) -> bool {
use BinProp::*;
use intl::unicode as u;
let Some(c) = char::from_u32(cp) else {
return matches!(self, Assigned);
};
match self {
Alphabetic => u::is_alphabetic(c),
Assigned => u::is_assigned(c),
BidiMirrored => u::is_bidi_mirrored(c),
Cased => {
u::general_category(c).is_cased_letter() || u::is_lowercase(c) || u::is_uppercase(c)
}
ChangesWhenCasefolded => u::changes_when_casefolded(c),
ChangesWhenCasemapped => u::changes_when_casemapped(c),
ChangesWhenLowercased => u::changes_when_lowercased(c),
ChangesWhenTitlecased => u::changes_when_titlecased(c),
ChangesWhenUppercased => u::changes_when_uppercased(c),
Dash => u::is_dash(c),
DefaultIgnorable => u::is_default_ignorable(c),
Diacritic => u::is_diacritic(c),
HexDigit => u::is_hex_digit(c),
Lowercase => u::is_lowercase(c),
Math => u::is_math(c),
QuotationMark => u::is_quotation_mark(c),
Uppercase => u::is_uppercase(c),
WhiteSpace => u::is_whitespace(c),
XidStart => u::is_xid_start(c),
XidContinue => u::is_xid_continue(c),
IdStart
| IdContinue
| CaseIgnorable
| ChangesWhenNfkcCasefolded
| Deprecated
| Emoji
| EmojiComponent
| EmojiModifier
| EmojiModifierBase
| EmojiPresentation
| ExtendedPictographic
| Extender
| GraphemeBase
| GraphemeExtend
| IdsBinaryOperator
| IdsTrinaryOperator
| Ideographic
| LogicalOrderException
| PatternSyntax
| PatternWhiteSpace
| Radical
| SentenceTerminal
| SoftDotted
| TerminalPunctuation
| UnifiedIdeograph => false,
Ascii
| AsciiHexDigit
| Any
| BidiControl
| JoinControl
| RegionalIndicator
| NoncharacterCodePoint
| VariationSelector => false,
}
}
#[cfg(not(feature = "intl"))]
fn matches_table(self, cp: u32) -> bool {
use BinProp::*;
let Some(c) = char::from_u32(cp) else {
return matches!(self, Assigned);
};
match self {
Alphabetic => c.is_alphabetic(),
Lowercase => c.is_lowercase(),
Uppercase => c.is_uppercase(),
WhiteSpace => c.is_whitespace(),
HexDigit => c.is_ascii_hexdigit(),
_ => false,
}
}
}