use super::trie::graphemes_lookup;
use crate::{Mem, charu, impl_trait};
#[doc = crate::_tags!(text)]
#[doc = concat![crate::_ABBR_EGC!(), " property values from Unicode Standard Annex #29."]]
#[doc = crate::_doc_location!("text/grapheme")]
#[doc = crate::_doc!(vendor: "grapheme_machine")]
#[repr(u8)]
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, Eq)]
pub enum GraphemePropCb {
None = 0x00,
CR = 0x01,
Control = 0x02,
Extend = 0x03,
ExtendedPictographic = 0x04,
L = 0x05,
LF = 0x06,
LV = 0x07,
LVT = 0x08,
Prepend = 0x09,
RegionalIndicator = 0x0a,
SpacingMark = 0x0b,
T = 0x0c,
V = 0x0d,
Zwj = 0x0e,
}
impl_trait! { PartialEq for GraphemePropCb |self, other| Self::eq(*self, *other) }
impl_trait! { Hash for GraphemePropCb |self, state| { Mem::discriminant(self).hash(state); } }
impl GraphemePropCb {
pub const fn eq(self, other: Self) -> bool {
matches!(
(self, other),
(Self::None, Self::None)
| (Self::CR, Self::CR)
| (Self::Control, Self::Control)
| (Self::Extend, Self::Extend)
| (Self::ExtendedPictographic, Self::ExtendedPictographic)
| (Self::L, Self::L)
| (Self::LF, Self::LF)
| (Self::LV, Self::LV)
| (Self::LVT, Self::LVT)
| (Self::Prepend, Self::Prepend)
| (Self::RegionalIndicator, Self::RegionalIndicator)
| (Self::SpacingMark, Self::SpacingMark)
| (Self::T, Self::T)
| (Self::V, Self::V)
| (Self::Zwj, Self::Zwj)
)
}
}
#[doc = crate::_tags!(text)]
#[doc = crate::_doc_location!("text/grapheme")]
#[doc = crate::_doc!(vendor: "grapheme_machine")]
#[repr(u8)]
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, Eq)]
pub enum GraphemePropInCb {
None = 0x00,
Consonant = 0x10,
Extend = 0x20,
Linker = 0x30,
}
impl_trait! { PartialEq for GraphemePropInCb |self, other| Self::eq(*self, *other) }
impl_trait! { Hash for GraphemePropInCb |self, state| { Mem::discriminant(self).hash(state); } }
impl GraphemePropInCb {
pub const fn eq(self, other: Self) -> bool {
matches!(
(self, other),
(Self::None, Self::None)
| (Self::Consonant, Self::Consonant)
| (Self::Extend, Self::Extend)
| (Self::Linker, Self::Linker)
)
}
}
#[doc = crate::_tags!(text)]
#[doc = concat!["Combined ", crate::_ABBR_EGC!(), " break properties for a single code point."]]
#[doc = crate::_doc_location!("text/grapheme")]
#[doc = crate::_doc!(vendor: "grapheme_machine")]
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Eq)]
pub struct GraphemeProps {
raw: u8,
}
impl_trait! { PartialEq for GraphemeProps |self, other| Self::eq(*self, *other) }
impl_trait! { Hash for GraphemeProps |self, state| { self.raw.hash(state); } }
impl GraphemeProps {
pub const fn new(gcb: GraphemePropCb, incb: GraphemePropInCb) -> Self {
Self { raw: gcb as u8 | incb as u8 }
}
pub const fn for_charu(c: charu) -> Self {
Self { raw: graphemes_lookup(c) }
}
pub const fn for_char(c: char) -> Self {
Self { raw: graphemes_lookup(charu::from_char(c)) }
}
pub const fn gcb_property(self) -> GraphemePropCb {
#[cfg(any(feature = "safe_text", not(feature = "unsafe_layout")))]
match self.raw & 0xf {
0x00 => GraphemePropCb::None,
0x01 => GraphemePropCb::CR,
0x02 => GraphemePropCb::Control,
0x03 => GraphemePropCb::Extend,
0x04 => GraphemePropCb::ExtendedPictographic,
0x05 => GraphemePropCb::L,
0x06 => GraphemePropCb::LF,
0x07 => GraphemePropCb::LV,
0x08 => GraphemePropCb::LVT,
0x09 => GraphemePropCb::Prepend,
0x0a => GraphemePropCb::RegionalIndicator,
0x0b => GraphemePropCb::SpacingMark,
0x0c => GraphemePropCb::T,
0x0d => GraphemePropCb::V,
0x0e => GraphemePropCb::Zwj,
_ => unreachable!(), }
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_layout"))]
{
let raw = self.raw & 0xf;
unsafe { core::mem::transmute(raw) }
}
}
pub const fn incb_property(self) -> GraphemePropInCb {
#[cfg(any(feature = "safe_text", not(feature = "unsafe_layout")))]
match self.raw & 0x30 {
0x00 => GraphemePropInCb::None,
0x10 => GraphemePropInCb::Consonant,
0x20 => GraphemePropInCb::Extend,
0x30 => GraphemePropInCb::Linker,
_ => unreachable!(), }
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_layout"))]
{
let raw = self.raw & 0x30;
unsafe { core::mem::transmute(raw) }
}
}
pub const fn is_any_control(self) -> bool {
matches!(
self.gcb_property(),
GraphemePropCb::LF | GraphemePropCb::CR | GraphemePropCb::Control,
)
}
pub const fn eq(self, other: Self) -> bool {
self.raw == other.raw
}
}
#[cfg(test)]
#[allow(unused, non_upper_case_globals)]
impl GraphemeProps {
pub(crate) const None: Self = Self::gcb_only(GraphemePropCb::None);
pub(crate) const CR: Self = Self::gcb_only(GraphemePropCb::CR);
pub(crate) const Control: Self = Self::gcb_only(GraphemePropCb::Control);
pub(crate) const Extend: Self = Self::gcb_only(GraphemePropCb::Extend);
pub(crate) const ExtendedPictographic: Self =
Self::gcb_only(GraphemePropCb::ExtendedPictographic);
pub(crate) const L: Self = Self::gcb_only(GraphemePropCb::L);
pub(crate) const LF: Self = Self::gcb_only(GraphemePropCb::LF);
pub(crate) const LV: Self = Self::gcb_only(GraphemePropCb::LV);
pub(crate) const LVT: Self = Self::gcb_only(GraphemePropCb::LVT);
pub(crate) const Prepend: Self = Self::gcb_only(GraphemePropCb::Prepend);
pub(crate) const RegionalIndicator: Self = Self::gcb_only(GraphemePropCb::RegionalIndicator);
pub(crate) const SpacingMark: Self = Self::gcb_only(GraphemePropCb::SpacingMark);
pub(crate) const T: Self = Self::gcb_only(GraphemePropCb::T);
pub(crate) const V: Self = Self::gcb_only(GraphemePropCb::V);
pub(crate) const Zwj: Self = Self::gcb_only(GraphemePropCb::Zwj);
const fn gcb_only(gcb: GraphemePropCb) -> Self {
Self::new(gcb, GraphemePropInCb::None)
}
}