use crate::bidi::BidiMirroringGlyph;
use crate::props::{
BidiClass, CanonicalCombiningClass, EastAsianWidth, GeneralCategory, GeneralCategoryGroup,
GraphemeClusterBreak, HangulSyllableType, IndicSyllabicCategory, JoiningType, LineBreak,
Script, SentenceBreak, WordBreak,
};
use crate::script::ScriptWithExt;
use core::convert::TryInto;
use core::num::TryFromIntError;
use zerovec::ule::{AsULE, RawBytesULE};
use icu_collections::codepointtrie::TrieValue;
use core::convert::TryFrom;
impl TrieValue for CanonicalCombiningClass {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for BidiClass {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for GeneralCategory {
type TryFromU32Error = &'static str;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
GeneralCategory::new_from_u8(i.try_into().unwrap_or(u8::MAX))
.ok_or("Cannot parse GeneralCategory from integer")
}
fn to_u32(self) -> u32 {
u32::from(self as u8)
}
}
impl TrieValue for Script {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u16::try_from(i).map(Script)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for HangulSyllableType {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for ScriptWithExt {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u16::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for EastAsianWidth {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for LineBreak {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for GraphemeClusterBreak {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for WordBreak {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for SentenceBreak {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl TrieValue for IndicSyllabicCategory {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}
impl AsULE for GeneralCategoryGroup {
type ULE = RawBytesULE<2>;
fn to_unaligned(self) -> Self::ULE {
let value = gcg_to_packed_u16(self);
value.to_unaligned()
}
fn from_unaligned(ule: Self::ULE) -> Self {
let value = ule.as_unsigned_int();
packed_u16_to_gcg(value)
}
}
fn packed_u16_to_gcg(value: u16) -> GeneralCategoryGroup {
match value {
0xFFFF => GeneralCategoryGroup::CasedLetter,
0xFFFE => GeneralCategoryGroup::Letter,
0xFFFD => GeneralCategoryGroup::Mark,
0xFFFC => GeneralCategoryGroup::Number,
0xFFFB => GeneralCategoryGroup::Separator,
0xFFFA => GeneralCategoryGroup::Other,
0xFFF9 => GeneralCategoryGroup::Punctuation,
0xFFF8 => GeneralCategoryGroup::Symbol,
v if v < 32 => GeneralCategory::new_from_u8(v as u8)
.map(|gc| gc.into())
.unwrap_or(GeneralCategoryGroup(0)),
_ => GeneralCategoryGroup(0),
}
}
fn gcg_to_packed_u16(gcg: GeneralCategoryGroup) -> u16 {
if gcg.0.is_power_of_two() {
gcg.0.trailing_zeros() as u16
} else {
match gcg {
GeneralCategoryGroup::CasedLetter => 0xFFFF,
GeneralCategoryGroup::Letter => 0xFFFE,
GeneralCategoryGroup::Mark => 0xFFFD,
GeneralCategoryGroup::Number => 0xFFFC,
GeneralCategoryGroup::Separator => 0xFFFB,
GeneralCategoryGroup::Other => 0xFFFA,
GeneralCategoryGroup::Punctuation => 0xFFF9,
GeneralCategoryGroup::Symbol => 0xFFF8,
_ => 0xFF00, }
}
}
impl TrieValue for GeneralCategoryGroup {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u16::try_from(i).map(packed_u16_to_gcg)
}
fn to_u32(self) -> u32 {
u32::from(gcg_to_packed_u16(self))
}
}
impl TrieValue for BidiMirroringGlyph {
type TryFromU32Error = u32;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
let code_point = i & 0x1FFFFF;
let mirroring_glyph = if code_point == 0 {
None
} else {
Some(char::try_from_u32(code_point).map_err(|_| i)?)
};
let mirrored = ((i >> 21) & 0x1) == 1;
let paired_bracket_type = {
let value = ((i >> 22) & 0x3) as u8;
match value {
0 => crate::bidi::BidiPairedBracketType::None,
1 => crate::bidi::BidiPairedBracketType::Open,
2 => crate::bidi::BidiPairedBracketType::Close,
_ => return Err(i),
}
};
Ok(Self {
mirrored,
mirroring_glyph,
paired_bracket_type,
})
}
fn to_u32(self) -> u32 {
self.mirroring_glyph.unwrap_or_default() as u32
| ((self.mirrored as u32) << 21)
| (match self.paired_bracket_type {
crate::bidi::BidiPairedBracketType::None => 0,
crate::bidi::BidiPairedBracketType::Open => 1,
crate::bidi::BidiPairedBracketType::Close => 2,
} << 22)
}
}
impl TrieValue for JoiningType {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
u8::try_from(i).map(Self)
}
fn to_u32(self) -> u32 {
u32::from(self.0)
}
}