1use crate::codepointtrie::error::Error;
6use crate::codepointtrie::impl_const::*;
7
8#[cfg(feature = "alloc")]
9use crate::codepointinvlist::CodePointInversionList;
10use core::char::CharTryFromError;
11use core::convert::Infallible;
12use core::convert::TryFrom;
13use core::fmt::Display;
14#[cfg(feature = "alloc")]
15use core::iter::FromIterator;
16use core::num::TryFromIntError;
17use core::ops::RangeInclusive;
18use yoke::Yokeable;
19use zerofrom::ZeroFrom;
20use zerovec::ZeroSlice;
21use zerovec::ZeroVec;
22use zerovec::ule::AsULE;
23#[cfg(feature = "alloc")]
24use zerovec::ule::UleError;
25
26#[derive(#[automatically_derived]#[doc(hidden)]#[allow(clippy::exhaustive_enums)]
unsafe impl ::core::clone::TrivialClone for TrieType { }
#[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::clone::Clone for TrieType {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::marker::Copy for TrieType { }Copy, #[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::marker::StructuralPartialEq for TrieType { }
#[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::cmp::PartialEq for TrieType {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::fmt::Debug for TrieType {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TrieType::Fast => "Fast",
TrieType::Small => "Small",
})
}
}Debug, #[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl ::core::cmp::Eq for TrieType { }Eq)]
43#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
44#[cfg_attr(feature = "databake", derive(databake::Bake))]
45#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
46#[allow(clippy::exhaustive_enums)] pub enum TrieType {
48 Fast = 0,
51 Small = 1,
54}
55
56pub trait TrieValue: Copy + Eq + PartialEq + AsULE + 'static {
65 type TryFromU32Error: Display;
71 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error>;
75
76 fn to_u32(self) -> u32;
83}
84
85macro_rules! impl_primitive_trie_value {
86 ($primitive:ty, $error:ty) => {
87 impl TrieValue for $primitive {
88 type TryFromU32Error = $error;
89 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
90 Self::try_from(i)
91 }
92
93 #[allow(trivial_numeric_casts)]
94 fn to_u32(self) -> u32 {
95 self as u32
98 }
99 }
100 };
101}
102
103impl TrieValue for u8 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u8, TryFromIntError);
104impl TrieValue for u16 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u16, TryFromIntError);
105impl TrieValue for u32 {
type TryFromU32Error = Infallible;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u32, Infallible);
106impl TrieValue for i8 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i8, TryFromIntError);
107impl TrieValue for i16 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i16, TryFromIntError);
108impl TrieValue for i32 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i32, TryFromIntError);
109impl TrieValue for char {
type TryFromU32Error = CharTryFromError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
#[allow(trivial_numeric_casts)]
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(char, CharTryFromError);
110
111fn maybe_filter_value<T: TrieValue>(value: T, trie_null_value: T, null_value: T) -> T {
120 if value == trie_null_value {
121 null_value
122 } else {
123 value
124 }
125}
126
127#[derive(#[automatically_derived]impl<'trie, T: ::core::fmt::Debug + TrieValue>
::core::fmt::Debug for CodePointTrie<'trie, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"CodePointTrie header index data error_value null_value",
&self.header, &self.index, &self.data, &self.error_value,
&&self.null_value)
}
}Debug, #[automatically_derived]impl<'trie, T: ::core::cmp::Eq + TrieValue>
::core::cmp::Eq for CodePointTrie<'trie, T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<CodePointTrieHeader>;
let _: ::core::cmp::AssertParamIsEq<ZeroVec<'trie, u16>>;
let _: ::core::cmp::AssertParamIsEq<ZeroVec<'trie, T>>;
let _: ::core::cmp::AssertParamIsEq<T>;
}
}Eq, #[automatically_derived]impl<'trie, T: ::core::cmp::PartialEq + TrieValue>
::core::marker::StructuralPartialEq for CodePointTrie<'trie, T> {
}
#[automatically_derived]impl<'trie, T: ::core::cmp::PartialEq + TrieValue>
::core::cmp::PartialEq for CodePointTrie<'trie, T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.header == other.header && self.index == other.index &&
self.data == other.data &&
self.error_value == other.error_value &&
self.null_value == other.null_value
}
}PartialEq, unsafe impl<'yoke, T: TrieValue> yoke::Yokeable<'yoke> for
CodePointTrie<'static, T> where T: 'static {
type Output = CodePointTrie<'yoke, T>;
#[inline]
fn transform(&'yoke self) -> &'yoke Self::Output {
if false { let _: *const &'yoke Self::Output = &raw const self; }
self
}
#[inline]
fn transform_owned(self) -> Self::Output { self }
#[inline]
unsafe fn make(from: Self::Output) -> Self {
::core::mem::transmute::<Self::Output, Self>(from)
}
#[inline]
fn transform_mut<F>(&'yoke mut self, f: F) where F: 'static +
for<'_yoke> FnOnce(&'_yoke mut Self::Output) {
let y = unsafe { &mut *(self as *mut Self as *mut Self::Output) };
f(y)
}
}Yokeable, impl<'zf, 'zf_inner, T: TrieValue>
zerofrom::ZeroFrom<'zf, CodePointTrie<'zf_inner, T>> for
CodePointTrie<'zf, T> where
ZeroVec<'zf, T>: zerofrom::ZeroFrom<'zf, ZeroVec<'zf_inner, T>> {
fn zero_from(this: &'zf CodePointTrie<'zf_inner, T>) -> Self {
match *this {
CodePointTrie {
header: ref __binding_0,
index: ref __binding_1,
data: ref __binding_2,
error_value: ref __binding_3,
null_value: ref __binding_4 } => {
CodePointTrie {
header: *__binding_0,
index: <ZeroVec<'zf, u16> as
zerofrom::ZeroFrom<'zf,
ZeroVec<'zf_inner, u16>>>::zero_from(__binding_1),
data: <ZeroVec<'zf, T> as
zerofrom::ZeroFrom<'zf,
ZeroVec<'zf_inner, T>>>::zero_from(__binding_2),
error_value: __binding_3.clone(),
null_value: __binding_4.clone(),
}
}
}
}
}ZeroFrom)]
135pub struct CodePointTrie<'trie, T: TrieValue> {
136 pub(crate) header: CodePointTrieHeader,
140 pub(crate) index: ZeroVec<'trie, u16>,
149 pub(crate) data: ZeroVec<'trie, T>,
159 #[zerofrom(clone)] pub(crate) error_value: T,
163 #[zerofrom(clone)] pub(crate) null_value: T,
167}
168
169#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
178#[cfg_attr(feature = "databake", derive(databake::Bake))]
179#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
180#[derive(#[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::marker::Copy for CodePointTrieHeader { }Copy, #[automatically_derived]#[doc(hidden)]#[allow(clippy::exhaustive_structs)]
unsafe impl ::core::clone::TrivialClone for CodePointTrieHeader { }
#[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::clone::Clone for CodePointTrieHeader {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u16>;
let _: ::core::clone::AssertParamIsClone<TrieType>;
*self
}
}Clone, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::fmt::Debug for CodePointTrieHeader {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
"CodePointTrieHeader high_start shifted12_high_start index3_null_offset data_null_offset null_value trie_type";
let values: &[&dyn ::core::fmt::Debug] =
&[&self.high_start, &self.shifted12_high_start,
&self.index3_null_offset, &self.data_null_offset,
&self.null_value, &&self.trie_type];
::core::fmt::Formatter::debug_struct_fields_finish(f, names, values)
}
}Debug, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::Eq for CodePointTrieHeader {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<u16>;
let _: ::core::cmp::AssertParamIsEq<TrieType>;
}
}Eq, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::marker::StructuralPartialEq for CodePointTrieHeader { }
#[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::PartialEq for CodePointTrieHeader {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.high_start == other.high_start &&
self.shifted12_high_start == other.shifted12_high_start &&
self.index3_null_offset == other.index3_null_offset &&
self.data_null_offset == other.data_null_offset &&
self.null_value == other.null_value &&
self.trie_type == other.trie_type
}
}PartialEq, unsafe impl<'yoke> yoke::Yokeable<'yoke> for CodePointTrieHeader<> where
Self: Sized {
type Output = Self;
#[inline]
fn transform(&self) -> &Self::Output { self }
#[inline]
fn transform_owned(self) -> Self::Output { self }
#[inline]
unsafe fn make(this: Self::Output) -> Self { this }
#[inline]
fn transform_mut<F>(&'yoke mut self, f: F) where F: 'static +
for<'_yoke> FnOnce(&'_yoke mut Self::Output) {
f(self)
}
}Yokeable, impl<'zf> zerofrom::ZeroFrom<'zf, CodePointTrieHeader<>> for
CodePointTrieHeader<> where {
fn zero_from(this: &'zf Self) -> Self { *this }
}ZeroFrom)]
181#[allow(clippy::exhaustive_structs)] pub struct CodePointTrieHeader {
183 pub high_start: u32,
195 pub shifted12_high_start: u16,
199 pub index3_null_offset: u16,
203 pub data_null_offset: u32,
207 pub null_value: u32,
210 pub trie_type: TrieType,
217}
218
219impl TryFrom<u8> for TrieType {
220 type Error = Error;
221
222 fn try_from(trie_type_int: u8) -> Result<TrieType, Error> {
223 match trie_type_int {
224 0 => Ok(TrieType::Fast),
225 1 => Ok(TrieType::Small),
226 _ => Err(Error::FromDeserialized {
227 reason: "Cannot parse value for trie_type",
228 }),
229 }
230 }
231}
232
233macro_rules! w(
241 ($a:tt + $b:expr) => {
244 {
245 #[allow(unused_parens)]
246 let a = $a;
247 let b = $b;
248 debug_assert!(a.checked_add(b).is_some());
249 $a.wrapping_add($b)
250 }
251 };
252 ($a:tt - $b:expr) => {
253
254 {
255 #[allow(unused_parens)]
256 let a = $a;
257 let b = $b;
258 debug_assert!(a.checked_sub(b).is_some());
259 $a.wrapping_sub($b)
260 }
261 };
262 ($a:tt * $b:expr) => {
263 {
264 #[allow(unused_parens)]
265 let a = $a;
266 let b = $b;
267 debug_assert!(a.checked_mul(b).is_some());
268 $a.wrapping_mul($b)
269 }
270 };
271);
272
273impl<'trie, T: TrieValue> CodePointTrie<'trie, T> {
274 #[doc(hidden)] pub const unsafe fn from_parts_unstable_unchecked_v1(
281 header: CodePointTrieHeader,
282 index: ZeroVec<'trie, u16>,
283 data: ZeroVec<'trie, T>,
284 error_value: T,
285 null_value: T,
286 ) -> Self {
287 Self {
292 header,
293 index,
294 data,
295 error_value,
296 null_value,
297 }
298 }
299
300 pub fn try_new(
303 header: CodePointTrieHeader,
304 index: ZeroVec<'trie, u16>,
305 data: ZeroVec<'trie, T>,
306 ) -> Result<CodePointTrie<'trie, T>, Error> {
307 let (error_value, null_value) = Self::validate_fields(&header, &index, &data)?;
308 let trie: CodePointTrie<'trie, T> = CodePointTrie {
310 header,
311 index,
312 data,
313 error_value,
314 null_value,
315 };
316 Ok(trie)
317 }
318
319 pub(crate) fn validate_fields(
329 header: &CodePointTrieHeader,
330 index: &ZeroSlice<u16>,
331 data: &ZeroSlice<T>,
332 ) -> Result<(T, T), Error> {
333 let error_value = data.last().ok_or(Error::EmptyDataVector)?;
334 let null_value = T::try_from_u32(header.null_value).map_err(|_| Error::InvalidNullValue)?;
335
336 let fast_max = match header.trie_type {
365 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
366 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
367 };
368 let max_bit_prefix = fast_max >> FAST_TYPE_SHIFT;
370 let fast_index = index
375 .get_subslice(0..(max_bit_prefix as usize) + 1)
376 .ok_or(Error::IndexTooShortForFastAccess)?;
377 let max_offset = fast_index
386 .iter()
387 .max()
388 .ok_or(Error::IndexTooShortForFastAccess)?;
389 if (max_offset) as usize + (FAST_TYPE_DATA_MASK as usize) >= data.len() {
393 return Err(Error::DataTooShortForFastAccess);
394 }
395
396 Ok((error_value, null_value))
402 }
403
404 #[inline]
406 pub fn to_typed(self) -> Typed<FastCodePointTrie<'trie, T>, SmallCodePointTrie<'trie, T>> {
407 match self.header.trie_type {
408 TrieType::Fast => Typed::Fast(FastCodePointTrie { inner: self }),
409 TrieType::Small => Typed::Small(SmallCodePointTrie { inner: self }),
410 }
411 }
412
413 #[inline]
415 pub fn as_typed_ref(
416 &self,
417 ) -> Typed<&FastCodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>> {
418 match self.header.trie_type {
422 TrieType::Fast => Typed::Fast(unsafe {
423 &*(self as *const CodePointTrie<'trie, T> as *const FastCodePointTrie<'trie, T>)
424 }),
425 TrieType::Small => Typed::Small(unsafe {
426 &*(self as *const CodePointTrie<'trie, T> as *const SmallCodePointTrie<'trie, T>)
427 }),
428 }
429 }
430
431 #[inline(always)] fn trie_error_val_index(&self) -> u32 {
435 if true {
if !(self.data.len() as u32 >= ERROR_VALUE_NEG_DATA_OFFSET) {
::core::panicking::panic("assertion failed: self.data.len() as u32 >= ERROR_VALUE_NEG_DATA_OFFSET")
};
};debug_assert!(self.data.len() as u32 >= ERROR_VALUE_NEG_DATA_OFFSET);
439 {
#[allow(unused_parens)]
let a = (self.data.len() as u32);
let b = ERROR_VALUE_NEG_DATA_OFFSET;
if true {
if !a.checked_sub(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_sub(b).is_some()")
};
};
(self.data.len() as u32).wrapping_sub(ERROR_VALUE_NEG_DATA_OFFSET)
}w!((self.data.len() as u32) - ERROR_VALUE_NEG_DATA_OFFSET)
440 }
441
442 fn internal_small_index(&self, code_point: u32) -> u32 {
443 let mut index1_pos: u32 = code_point >> SHIFT_1;
447 if self.header.trie_type == TrieType::Fast {
448 if true {
if !(FAST_TYPE_FAST_INDEXING_MAX < code_point &&
code_point < self.header.high_start) {
::core::panicking::panic("assertion failed: FAST_TYPE_FAST_INDEXING_MAX < code_point &&\n code_point < self.header.high_start")
};
};debug_assert!(
449 FAST_TYPE_FAST_INDEXING_MAX < code_point && code_point < self.header.high_start
450 );
451 index1_pos = {
#[allow(unused_parens)]
let a = index1_pos;
let b = BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
index1_pos.wrapping_add(BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH)
}w!(index1_pos + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH);
452 } else {
453 if !(code_point < self.header.high_start &&
self.header.high_start > SMALL_LIMIT) {
::core::panicking::panic("assertion failed: code_point < self.header.high_start && self.header.high_start > SMALL_LIMIT")
};assert!(code_point < self.header.high_start && self.header.high_start > SMALL_LIMIT);
454 index1_pos = {
#[allow(unused_parens)]
let a = index1_pos;
let b = SMALL_INDEX_LENGTH;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
index1_pos.wrapping_add(SMALL_INDEX_LENGTH)
}w!(index1_pos + SMALL_INDEX_LENGTH);
455 }
456 let index1_val = if let Some(index1_val) = self.index.get(index1_pos as usize) {
457 index1_val
458 } else {
459 return self.trie_error_val_index();
460 };
461 let index3_block_idx: u32 =
462 {
#[allow(unused_parens)]
let a = (index1_val as u32);
let b = (code_point >> SHIFT_2) & INDEX_2_MASK;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
(index1_val as u32).wrapping_add((code_point >> SHIFT_2) & INDEX_2_MASK)
}w!((index1_val as u32) + (code_point >> SHIFT_2) & INDEX_2_MASK);
463 let mut index3_block: u32 =
464 if let Some(index3_block) = self.index.get(index3_block_idx as usize) {
465 index3_block as u32
466 } else {
467 return self.trie_error_val_index();
468 };
469 let mut index3_pos: u32 = (code_point >> SHIFT_3) & INDEX_3_MASK;
470 let mut data_block: u32;
471 if index3_block & 0x8000 == 0 {
472 data_block =
474 if let Some(data_block) = self.index.get({
#[allow(unused_parens)]
let a = index3_block;
let b = index3_pos;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
index3_block.wrapping_add(index3_pos)
}w!(index3_block + index3_pos) as usize) {
475 data_block as u32
476 } else {
477 return self.trie_error_val_index();
478 };
479 } else {
480 index3_block = {
#[allow(unused_parens)]
let a = (index3_block & 0x7fff);
let b =
{
#[allow(unused_parens)]
let a = (index3_pos & !7);
let b = index3_pos >> 3;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
(index3_pos & !7).wrapping_add(index3_pos >> 3)
};
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
(index3_block &
0x7fff).wrapping_add({
#[allow(unused_parens)]
let a = (index3_pos & !7);
let b = index3_pos >> 3;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
(index3_pos & !7).wrapping_add(index3_pos >> 3)
})
}w!((index3_block & 0x7fff) + w!((index3_pos & !7) + index3_pos >> 3));
482 index3_pos &= 7;
483 data_block = if let Some(data_block) = self.index.get(index3_block as usize) {
484 data_block as u32
485 } else {
486 return self.trie_error_val_index();
487 };
488 data_block = (data_block << {
#[allow(unused_parens)]
let a = 2u32;
let b =
{
#[allow(unused_parens)]
let a = 2u32;
let b = index3_pos;
if true {
if !a.checked_mul(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_mul(b).is_some()")
};
};
2u32.wrapping_mul(index3_pos)
};
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
2u32.wrapping_add({
#[allow(unused_parens)]
let a = 2u32;
let b = index3_pos;
if true {
if !a.checked_mul(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_mul(b).is_some()")
};
};
2u32.wrapping_mul(index3_pos)
})
}w!(2u32 + w!(2u32 * index3_pos))) & 0x30000;
489 index3_block += 1;
490 data_block =
491 if let Some(index3_val) = self.index.get({
#[allow(unused_parens)]
let a = index3_block;
let b = index3_pos;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
index3_block.wrapping_add(index3_pos)
}w!(index3_block + index3_pos) as usize) {
492 data_block | (index3_val as u32)
493 } else {
494 return self.trie_error_val_index();
495 };
496 }
497 {
#[allow(unused_parens)]
let a = data_block;
let b = code_point & SMALL_DATA_MASK;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
data_block.wrapping_add(code_point & SMALL_DATA_MASK)
}w!(data_block + code_point & SMALL_DATA_MASK)
500 }
501
502 fn small_index(&self, code_point: u32) -> u32 {
513 if code_point >= self.header.high_start {
514 {
#[allow(unused_parens)]
let a = (self.data.len() as u32);
let b = HIGH_VALUE_NEG_DATA_OFFSET;
if true {
if !a.checked_sub(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_sub(b).is_some()")
};
};
(self.data.len() as u32).wrapping_sub(HIGH_VALUE_NEG_DATA_OFFSET)
}w!((self.data.len() as u32) - HIGH_VALUE_NEG_DATA_OFFSET)
515 } else {
516 self.internal_small_index(code_point) }
518 }
519
520 fn fast_index(&self, code_point: u32) -> u32 {
532 let index_array_pos: u32 = code_point >> FAST_TYPE_SHIFT;
533 let index_array_val: u16 =
534 if let Some(index_array_val) = self.index.get(index_array_pos as usize) {
535 index_array_val
536 } else {
537 return self.trie_error_val_index();
538 };
539 let masked_cp = code_point & FAST_TYPE_DATA_MASK;
540 let index_array_val = index_array_val as u32;
541 let fast_index_val: u32 = {
#[allow(unused_parens)]
let a = index_array_val;
let b = masked_cp;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
index_array_val.wrapping_add(masked_cp)
}w!(index_array_val + masked_cp);
542 fast_index_val
543 }
544
545 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
550 let fast_max = match self.header.trie_type {
551 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
552 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
553 };
554 if code_point <= fast_max {
555 Some(unsafe { self.get32_assuming_fast_index(code_point) })
562 } else {
563 None
566 }
567 }
568
569 #[inline(always)]
577 unsafe fn get32_assuming_fast_index(&self, code_point: u32) -> T {
578 if true {
if !(code_point <=
match self.header.trie_type {
TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
}) {
::core::panicking::panic("assertion failed: code_point <=\n match self.header.trie_type {\n TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,\n TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,\n }")
};
};debug_assert!(
580 code_point
581 <= match self.header.trie_type {
582 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
583 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
584 }
585 );
586
587 let bit_prefix = (code_point as usize) >> FAST_TYPE_SHIFT;
588 if true {
if !(bit_prefix < self.index.len()) {
::core::panicking::panic("assertion failed: bit_prefix < self.index.len()")
};
};debug_assert!(bit_prefix < self.index.len());
589 let base_offset_to_data: usize = usize::from(u16::from_unaligned(*unsafe {
593 self.index.as_ule_slice().get_unchecked(bit_prefix)
594 }));
595 let bit_suffix = (code_point & FAST_TYPE_DATA_MASK) as usize;
596 let offset_to_data = {
#[allow(unused_parens)]
let a = base_offset_to_data;
let b = bit_suffix;
if true {
if !a.checked_add(b).is_some() {
::core::panicking::panic("assertion failed: a.checked_add(b).is_some()")
};
};
base_offset_to_data.wrapping_add(bit_suffix)
}w!(base_offset_to_data + bit_suffix);
602 if true {
if !(offset_to_data < self.data.len()) {
::core::panicking::panic("assertion failed: offset_to_data < self.data.len()")
};
};debug_assert!(offset_to_data < self.data.len());
603 T::from_unaligned(*unsafe { self.data.as_ule_slice().get_unchecked(offset_to_data) })
607 }
608
609 #[cold]
612 #[inline(always)]
613 fn get32_by_small_index_cold(&self, code_point: u32) -> T {
614 self.get32_by_small_index(code_point)
615 }
616
617 #[inline(never)]
630 fn get32_by_small_index(&self, code_point: u32) -> T {
631 if true {
if !(code_point <= CODE_POINT_MAX) {
::core::panicking::panic("assertion failed: code_point <= CODE_POINT_MAX")
};
};debug_assert!(code_point <= CODE_POINT_MAX);
632 if true {
if !(code_point >
match self.header.trie_type {
TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
}) {
::core::panicking::panic("assertion failed: code_point >\n match self.header.trie_type {\n TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,\n TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,\n }")
};
};debug_assert!(
633 code_point
634 > match self.header.trie_type {
635 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
636 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
637 }
638 );
639 self.data
640 .get(self.small_index(code_point) as usize)
641 .unwrap_or(self.error_value)
642 }
643
644 #[inline(always)] pub fn get32(&self, code_point: u32) -> T {
658 if let Some(v) = self.get32_by_fast_index(code_point) {
659 v
660 } else if code_point <= CODE_POINT_MAX {
661 self.get32_by_small_index_cold(code_point)
662 } else {
663 self.error_value
664 }
665 }
666
667 #[inline(always)]
680 pub fn get(&self, c: char) -> T {
681 let code_point = u32::from(c);
685 if let Some(v) = self.get32_by_fast_index(code_point) {
686 v
687 } else {
688 self.get32_by_small_index_cold(code_point)
689 }
690 }
691
692 #[inline(always)]
694 pub fn get16(&self, bmp: u16) -> T {
695 let code_point = u32::from(bmp);
699 if let Some(v) = self.get32_by_fast_index(code_point) {
700 v
701 } else {
702 self.get32_by_small_index_cold(code_point)
703 }
704 }
705
706 #[inline(always)]
712 pub fn get32_supplementary(&self, supplementary: u32) -> T {
713 if true {
if !(supplementary > 0xFFFF) {
::core::panicking::panic("assertion failed: supplementary > 0xFFFF")
};
};debug_assert!(supplementary > 0xFFFF);
714 if true {
if !(supplementary <= CODE_POINT_MAX) {
::core::panicking::panic("assertion failed: supplementary <= CODE_POINT_MAX")
};
};debug_assert!(supplementary <= CODE_POINT_MAX);
715 self.get32_by_small_index(supplementary)
716 }
717
718 #[inline(always)] pub fn get32_ule(&self, code_point: u32) -> Option<&T::ULE> {
732 let fast_max = match self.header.trie_type {
737 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
738 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
739 };
740 let data_pos: u32 = if code_point <= fast_max {
741 Self::fast_index(self, code_point)
742 } else if code_point <= CODE_POINT_MAX {
743 Self::small_index(self, code_point)
744 } else {
745 self.trie_error_val_index()
746 };
747 self.data.as_ule_slice().get(data_pos as usize)
749 }
750
751 #[cfg(feature = "alloc")]
780 pub fn try_into_converted<P>(self) -> Result<CodePointTrie<'trie, P>, UleError>
781 where
782 P: TrieValue,
783 {
784 let converted_data = self.data.try_into_converted()?;
785 let error_ule = self.error_value.to_unaligned();
786 let error_slice = &[error_ule];
787 let error_vec = ZeroVec::<T>::new_borrowed(error_slice);
788 let error_converted = error_vec.try_into_converted::<P>()?;
789 let null_ule = self.null_value.to_unaligned();
790 let null_slice = &[null_ule];
791 let null_vec = ZeroVec::<T>::new_borrowed(null_slice);
792 let null_converted = null_vec.try_into_converted::<P>()?;
793 #[expect(clippy::expect_used)] Ok(CodePointTrie {
795 header: self.header,
796 index: self.index,
797 data: converted_data,
798 error_value: error_converted
799 .get(0)
800 .expect("vector known to have one element"),
801 null_value: null_converted
802 .get(0)
803 .expect("vector known to have one element"),
804 })
805 }
806
807 #[cfg(feature = "alloc")]
830 pub fn try_alloc_map_value<P, E>(
831 &self,
832 mut f: impl FnMut(T) -> Result<P, E>,
833 ) -> Result<CodePointTrie<'trie, P>, E>
834 where
835 P: TrieValue,
836 {
837 let error_converted = f(self.error_value)?;
838 let null_converted = f(self.error_value)?;
839 let converted_data = self.data.iter().map(f).collect::<Result<ZeroVec<P>, E>>()?;
840 Ok(CodePointTrie {
841 header: self.header,
842 index: self.index.clone(),
843 data: converted_data,
844 error_value: error_converted,
845 null_value: null_converted,
846 })
847 }
848
849 pub fn get_range(&self, start: u32) -> Option<CodePointMapRange<T>> {
903 if CODE_POINT_MAX < start {
907 return None;
908 }
909 if start >= self.header.high_start {
910 let di: usize = self.data.len() - (HIGH_VALUE_NEG_DATA_OFFSET as usize);
911 let value: T = self.data.get(di)?;
912 return Some(CodePointMapRange {
913 range: start..=CODE_POINT_MAX,
914 value,
915 });
916 }
917
918 let mut prev_i3_block: u32 = u32::MAX; let mut prev_block: u32 = u32::MAX; let mut c: u32 = start;
921 let mut trie_value: T = self.error_value();
922 let mut value: T = self.error_value();
923 let mut have_value: bool = false;
924
925 loop {
926 let i3_block: u32;
927 let mut i3: u32;
928 let i3_block_length: u32;
929 let data_block_length: u32;
930
931 if c <= 0xffff
944 && (self.header.trie_type == TrieType::Fast || c <= SMALL_TYPE_FAST_INDEXING_MAX)
945 {
946 i3_block = 0;
947 i3 = c >> FAST_TYPE_SHIFT;
948 i3_block_length = if self.header.trie_type == TrieType::Fast {
949 BMP_INDEX_LENGTH
950 } else {
951 SMALL_INDEX_LENGTH
952 };
953 data_block_length = FAST_TYPE_DATA_BLOCK_LENGTH;
954 } else {
955 let mut i1: u32 = c >> SHIFT_1;
957 if self.header.trie_type == TrieType::Fast {
958 if true {
if !(0xffff < c && c < self.header.high_start) {
::core::panicking::panic("assertion failed: 0xffff < c && c < self.header.high_start")
};
};debug_assert!(0xffff < c && c < self.header.high_start);
959 i1 = i1 + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH;
960 } else {
961 if true {
if !(c < self.header.high_start && self.header.high_start > SMALL_LIMIT) {
::core::panicking::panic("assertion failed: c < self.header.high_start && self.header.high_start > SMALL_LIMIT")
};
};debug_assert!(
962 c < self.header.high_start && self.header.high_start > SMALL_LIMIT
963 );
964 i1 += SMALL_INDEX_LENGTH;
965 }
966 let i2: u16 = self.index.get(i1 as usize)?;
967 let i3_block_idx: u32 = (i2 as u32) + ((c >> SHIFT_2) & INDEX_2_MASK);
968 i3_block = self.index.get(i3_block_idx as usize)? as u32;
969 if i3_block == prev_i3_block && (c - start) >= CP_PER_INDEX_2_ENTRY {
970 if true {
if !((c & (CP_PER_INDEX_2_ENTRY - 1)) == 0) {
::core::panicking::panic("assertion failed: (c & (CP_PER_INDEX_2_ENTRY - 1)) == 0")
};
};debug_assert!((c & (CP_PER_INDEX_2_ENTRY - 1)) == 0);
972 c += CP_PER_INDEX_2_ENTRY;
973
974 if c >= self.header.high_start {
975 break;
976 } else {
977 continue;
978 }
979 }
980 prev_i3_block = i3_block;
981 if i3_block == self.header.index3_null_offset as u32 {
982 if have_value {
989 if self.null_value != value {
990 return Some(CodePointMapRange {
991 range: start..=(c - 1),
992 value,
993 });
994 }
995 } else {
996 trie_value = self.null_value;
997 value = self.null_value;
998 have_value = true;
999 }
1000 prev_block = self.header.data_null_offset;
1001 c = (c + CP_PER_INDEX_2_ENTRY) & !(CP_PER_INDEX_2_ENTRY - 1);
1002
1003 if c >= self.header.high_start {
1004 break;
1005 } else {
1006 continue;
1007 }
1008 }
1009 i3 = (c >> SHIFT_3) & INDEX_3_MASK;
1010 i3_block_length = INDEX_3_BLOCK_LENGTH;
1011 data_block_length = SMALL_DATA_BLOCK_LENGTH;
1012 }
1013
1014 loop {
1016 let mut block: u32;
1017 if (i3_block & 0x8000) == 0 {
1018 block = self.index.get((i3_block + i3) as usize)? as u32;
1019 } else {
1020 let mut group: u32 = (i3_block & 0x7fff) + (i3 & !7) + (i3 >> 3);
1022 let gi: u32 = i3 & 7;
1023 let gi_val: u32 = self.index.get(group as usize)?.into();
1024 block = (gi_val << (2 + (2 * gi))) & 0x30000;
1025 group += 1;
1026 let ggi_val: u32 = self.index.get((group + gi) as usize)? as u32;
1027 block |= ggi_val;
1028 }
1029
1030 if block == prev_block && (c - start) >= data_block_length {
1038 if true {
if !((c & (data_block_length - 1)) == 0) {
::core::panicking::panic("assertion failed: (c & (data_block_length - 1)) == 0")
};
};debug_assert!((c & (data_block_length - 1)) == 0);
1040 c += data_block_length;
1041 } else {
1042 let data_mask: u32 = data_block_length - 1;
1043 prev_block = block;
1044 if block == self.header.data_null_offset {
1045 if have_value {
1050 if self.null_value != value {
1051 return Some(CodePointMapRange {
1052 range: start..=(c - 1),
1053 value,
1054 });
1055 }
1056 } else {
1057 trie_value = self.null_value;
1058 value = self.null_value;
1059 have_value = true;
1060 }
1061 c = (c + data_block_length) & !data_mask;
1062 } else {
1063 let mut di: u32 = block + (c & data_mask);
1064 let mut trie_value_2: T = self.data.get(di as usize)?;
1065 if have_value {
1066 if trie_value_2 != trie_value {
1067 if maybe_filter_value(
1068 trie_value_2,
1069 self.null_value,
1070 self.null_value,
1071 ) != value
1072 {
1073 return Some(CodePointMapRange {
1074 range: start..=(c - 1),
1075 value,
1076 });
1077 }
1078 trie_value = trie_value_2; }
1097 } else {
1098 trie_value = trie_value_2;
1099 value =
1100 maybe_filter_value(trie_value_2, self.null_value, self.null_value);
1101 have_value = true;
1102 }
1103
1104 c += 1;
1105 while (c & data_mask) != 0 {
1106 di += 1;
1107 trie_value_2 = self.data.get(di as usize)?;
1108 if trie_value_2 != trie_value {
1109 if maybe_filter_value(
1110 trie_value_2,
1111 self.null_value,
1112 self.null_value,
1113 ) != value
1114 {
1115 return Some(CodePointMapRange {
1116 range: start..=(c - 1),
1117 value,
1118 });
1119 }
1120 trie_value = trie_value_2; }
1139
1140 c += 1;
1141 }
1142 }
1143 }
1144
1145 i3 += 1;
1146 if i3 >= i3_block_length {
1147 break;
1148 }
1149 }
1150
1151 if c >= self.header.high_start {
1152 break;
1153 }
1154 }
1155
1156 if true {
if !have_value {
::core::panicking::panic("assertion failed: have_value")
};
};debug_assert!(have_value);
1157
1158 let di: u32 = self.data.len() as u32 - HIGH_VALUE_NEG_DATA_OFFSET;
1163 let high_value: T = self.data.get(di as usize)?;
1164 if maybe_filter_value(high_value, self.null_value, self.null_value) != value {
1165 c -= 1;
1166 } else {
1167 c = CODE_POINT_MAX;
1168 }
1169 Some(CodePointMapRange {
1170 range: start..=c,
1171 value,
1172 })
1173 }
1174
1175 pub fn iter_ranges(&self) -> CodePointMapRangeIterator<'_, T> {
1208 let init_range = Some(CodePointMapRange {
1209 range: u32::MAX..=u32::MAX,
1210 value: self.error_value(),
1211 });
1212 CodePointMapRangeIterator::<T> {
1213 cpt: self,
1214 cpm_range: init_range,
1215 }
1216 }
1217
1218 pub fn iter_ranges_for_value(
1240 &self,
1241 value: T,
1242 ) -> impl Iterator<Item = RangeInclusive<u32>> + '_ {
1243 self.iter_ranges()
1244 .filter(move |cpm_range| cpm_range.value == value)
1245 .map(|cpm_range| cpm_range.range)
1246 }
1247
1248 pub fn iter_ranges_mapped<'a, U: Eq + 'a>(
1270 &'a self,
1271 mut map: impl FnMut(T) -> U + Copy + 'a,
1272 ) -> impl Iterator<Item = CodePointMapRange<U>> + 'a {
1273 crate::iterator_utils::RangeListIteratorCoalescer::new(self.iter_ranges().map(
1274 move |range| CodePointMapRange {
1275 range: range.range,
1276 value: map(range.value),
1277 },
1278 ))
1279 }
1280
1281 #[cfg(feature = "alloc")]
1305 pub fn get_set_for_value(&self, value: T) -> CodePointInversionList<'static> {
1306 let value_ranges = self.iter_ranges_for_value(value);
1307 CodePointInversionList::from_iter(value_ranges)
1308 }
1309
1310 #[inline]
1312 pub fn error_value(&self) -> T {
1313 self.error_value
1314 }
1315
1316 #[inline]
1318 pub fn null_value(&self) -> T {
1319 self.null_value
1320 }
1321}
1322
1323#[cfg(feature = "databake")]
1324impl<T: TrieValue + databake::Bake> databake::Bake for CodePointTrie<'_, T> {
1325 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
1326 let header = self.header.bake(env);
1327 let index = self.index.bake(env);
1328 let data = self.data.bake(env);
1329 let error_value = self.error_value.bake(env);
1330 let null_value = self.null_value.bake(env);
1331 databake::quote! { unsafe {
1332 #[allow(unused_unsafe)]
1333 icu_collections::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(#header, #index, #data, #error_value, #null_value)
1334 }}
1335 }
1336}
1337
1338#[cfg(feature = "databake")]
1339impl<T: TrieValue + databake::Bake> databake::BakeSize for CodePointTrie<'_, T> {
1340 fn borrows_size(&self) -> usize {
1341 self.header.borrows_size() + self.index.borrows_size() + self.data.borrows_size()
1342 }
1343}
1344
1345impl<T: TrieValue + Into<u32>> CodePointTrie<'_, T> {
1346 pub fn get32_u32(&self, code_point: u32) -> u32 {
1364 self.get32(code_point).into()
1365 }
1366}
1367
1368impl<T: TrieValue> Clone for CodePointTrie<'_, T>
1369where
1370 <T as AsULE>::ULE: Clone,
1371{
1372 fn clone(&self) -> Self {
1373 CodePointTrie {
1374 header: self.header,
1375 index: self.index.clone(),
1376 data: self.data.clone(),
1377 error_value: self.error_value,
1378 null_value: self.null_value,
1379 }
1380 }
1381}
1382
1383#[derive(#[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl<T: ::core::cmp::PartialEq> ::core::marker::StructuralPartialEq for
CodePointMapRange<T> {
}
#[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
CodePointMapRange<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.range == other.range && self.value == other.value
}
}PartialEq, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for CodePointMapRange<T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<RangeInclusive<u32>>;
let _: ::core::cmp::AssertParamIsEq<T>;
}
}Eq, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for CodePointMapRange<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"CodePointMapRange range value", &self.range, &&self.value)
}
}Debug, #[automatically_derived]#[allow(clippy::exhaustive_structs)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for CodePointMapRange<T> {
#[inline]
fn clone(&self) -> Self {
CodePointMapRange {
range: ::core::clone::Clone::clone(&self.range),
value: ::core::clone::Clone::clone(&self.value),
}
}
}Clone)]
1389#[allow(clippy::exhaustive_structs)] pub struct CodePointMapRange<T> {
1391 pub range: RangeInclusive<u32>,
1393 pub value: T,
1395}
1396
1397#[derive(#[automatically_derived]impl<'a, T: ::core::fmt::Debug + TrieValue>
::core::fmt::Debug for CodePointMapRangeIterator<'a, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"CodePointMapRangeIterator cpt cpm_range", &self.cpt,
&&self.cpm_range)
}
}Debug)]
1400pub struct CodePointMapRangeIterator<'a, T: TrieValue> {
1401 cpt: &'a CodePointTrie<'a, T>,
1402 cpm_range: Option<CodePointMapRange<T>>,
1409}
1410
1411impl<T: TrieValue> Iterator for CodePointMapRangeIterator<'_, T> {
1412 type Item = CodePointMapRange<T>;
1413
1414 fn next(&mut self) -> Option<Self::Item> {
1415 self.cpm_range = match &self.cpm_range {
1416 Some(cpmr) => {
1417 if *cpmr.range.start() == u32::MAX {
1418 self.cpt.get_range(0)
1419 } else {
1420 self.cpt.get_range(cpmr.range.end() + 1)
1421 }
1422 }
1423 None => None,
1424 };
1425 self.cpm_range.clone()
1427 }
1428}
1429
1430trait Seal {}
1436
1437#[allow(private_bounds)] pub trait TypedCodePointTrie<'trie, T: TrieValue>: Seal {
1441 const TRIE_TYPE: TrieType;
1447
1448 #[inline(always)]
1450 fn get32_u32(&self, code_point: u32) -> u32 {
1451 self.get32(code_point).to_u32()
1452 }
1453
1454 #[inline(always)]
1456 fn get16(&self, bmp: u16) -> T {
1457 let code_point = u32::from(bmp);
1461 if let Some(v) = self.get32_by_fast_index(code_point) {
1462 v
1463 } else {
1464 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1465 }
1466 }
1467
1468 #[inline(always)]
1470 fn get32_supplementary(&self, supplementary: u32) -> T {
1471 self.as_untyped_ref().get32_supplementary(supplementary)
1472 }
1473
1474 #[inline(always)]
1476 fn get(&self, c: char) -> T {
1477 let code_point = u32::from(c);
1481 if let Some(v) = self.get32_by_fast_index(code_point) {
1482 v
1483 } else {
1484 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1485 }
1486 }
1487
1488 #[inline(always)]
1490 fn get32(&self, code_point: u32) -> T {
1491 if let Some(v) = self.get32_by_fast_index(code_point) {
1492 v
1493 } else if code_point <= CODE_POINT_MAX {
1494 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1495 } else {
1496 self.as_untyped_ref().error_value
1497 }
1498 }
1499
1500 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
1505 if true {
{
match (&Self::TRIE_TYPE, &self.as_untyped_ref().header.trie_type) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(Self::TRIE_TYPE, self.as_untyped_ref().header.trie_type);
1506 let fast_max = match Self::TRIE_TYPE {
1507 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
1508 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
1509 };
1510 if code_point <= fast_max {
1511 Some(unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) })
1522 } else {
1523 None
1526 }
1527 }
1528
1529 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T>;
1531
1532 fn to_untyped(self) -> CodePointTrie<'trie, T>;
1534}
1535
1536#[derive(#[automatically_derived]impl<'trie, T: ::core::fmt::Debug + TrieValue>
::core::fmt::Debug for FastCodePointTrie<'trie, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"FastCodePointTrie inner", &&self.inner)
}
}Debug)]
1541#[repr(transparent)]
1542pub struct FastCodePointTrie<'trie, T: TrieValue> {
1543 inner: CodePointTrie<'trie, T>,
1544}
1545
1546impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for FastCodePointTrie<'trie, T> {
1547 const TRIE_TYPE: TrieType = TrieType::Fast;
1548
1549 #[inline(always)]
1551 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1552 &self.inner
1553 }
1554
1555 #[inline(always)]
1557 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1558 self.inner
1559 }
1560
1561 #[inline(always)]
1563 fn get16(&self, bmp: u16) -> T {
1564 if true {
if !(u32::from(u16::MAX) <= FAST_TYPE_FAST_INDEXING_MAX) {
::core::panicking::panic("assertion failed: u32::from(u16::MAX) <= FAST_TYPE_FAST_INDEXING_MAX")
};
};debug_assert!(u32::from(u16::MAX) <= FAST_TYPE_FAST_INDEXING_MAX);
1565 if true {
{
match (&Self::TRIE_TYPE, &TrieType::Fast) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(Self::TRIE_TYPE, TrieType::Fast);
1566 if true {
{
match (&self.as_untyped_ref().header.trie_type, &TrieType::Fast) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(self.as_untyped_ref().header.trie_type, TrieType::Fast);
1567 let code_point = u32::from(bmp);
1568 unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) }
1577 }
1578}
1579
1580impl<'trie, T: TrieValue> Seal for FastCodePointTrie<'trie, T> {}
1581
1582impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1583 for &'trie FastCodePointTrie<'trie, T>
1584{
1585 type Error = TypedCodePointTrieError;
1586
1587 fn try_from(
1588 reference: &'trie CodePointTrie<'trie, T>,
1589 ) -> Result<&'trie FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1590 match reference.as_typed_ref() {
1591 Typed::Fast(trie) => Ok(trie),
1592 Typed::Small(_) => Err(TypedCodePointTrieError),
1593 }
1594 }
1595}
1596
1597impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for FastCodePointTrie<'trie, T> {
1598 type Error = TypedCodePointTrieError;
1599
1600 fn try_from(
1601 value: CodePointTrie<'trie, T>,
1602 ) -> Result<FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1603 match value.to_typed() {
1604 Typed::Fast(trie) => Ok(trie),
1605 Typed::Small(_) => Err(TypedCodePointTrieError),
1606 }
1607 }
1608}
1609
1610#[derive(#[automatically_derived]impl<'trie, T: ::core::fmt::Debug + TrieValue>
::core::fmt::Debug for SmallCodePointTrie<'trie, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"SmallCodePointTrie inner", &&self.inner)
}
}Debug)]
1613#[repr(transparent)]
1614pub struct SmallCodePointTrie<'trie, T: TrieValue> {
1615 inner: CodePointTrie<'trie, T>,
1616}
1617
1618impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for SmallCodePointTrie<'trie, T> {
1619 const TRIE_TYPE: TrieType = TrieType::Small;
1620
1621 #[inline(always)]
1623 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1624 &self.inner
1625 }
1626
1627 #[inline(always)]
1629 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1630 self.inner
1631 }
1632}
1633
1634impl<'trie, T: TrieValue> Seal for SmallCodePointTrie<'trie, T> {}
1635
1636impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1637 for &'trie SmallCodePointTrie<'trie, T>
1638{
1639 type Error = TypedCodePointTrieError;
1640
1641 fn try_from(
1642 reference: &'trie CodePointTrie<'trie, T>,
1643 ) -> Result<&'trie SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1644 match reference.as_typed_ref() {
1645 Typed::Fast(_) => Err(TypedCodePointTrieError),
1646 Typed::Small(trie) => Ok(trie),
1647 }
1648 }
1649}
1650
1651impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for SmallCodePointTrie<'trie, T> {
1652 type Error = TypedCodePointTrieError;
1653
1654 fn try_from(
1655 value: CodePointTrie<'trie, T>,
1656 ) -> Result<SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1657 match value.to_typed() {
1658 Typed::Fast(_) => Err(TypedCodePointTrieError),
1659 Typed::Small(trie) => Ok(trie),
1660 }
1661 }
1662}
1663
1664#[derive(#[automatically_derived]impl ::core::fmt::Debug for TypedCodePointTrieError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "TypedCodePointTrieError")
}
}Debug)]
1667#[non_exhaustive]
1668pub struct TypedCodePointTrieError;
1669
1670#[allow(clippy::exhaustive_enums)]
1673#[derive(#[automatically_derived]#[allow(clippy::exhaustive_enums)]
impl<F: ::core::fmt::Debug, S: ::core::fmt::Debug> ::core::fmt::Debug for
Typed<F, S> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Fast(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Fast",
&__self_0),
Self::Small(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Small",
&__self_0),
}
}
}Debug)]
1674pub enum Typed<F, S> {
1675 Fast(F),
1677 Small(S),
1679}
1680
1681#[cfg(test)]
1682mod tests {
1683 use super::*;
1684 use crate::codepointtrie::planes;
1685 use alloc::vec::Vec;
1686
1687 #[test]
1688 #[cfg(feature = "serde")]
1689 fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> {
1690 let trie = planes::get_planes_trie();
1691 let trie_serialized: Vec<u8> = postcard::to_allocvec(&trie).unwrap();
1692
1693 const EXP_TRIE_SERIALIZED: &[u8] = &[
1695 128, 128, 64, 128, 2, 2, 0, 0, 1, 160, 18, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1698 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1699 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136,
1700 2, 144, 2, 144, 2, 144, 2, 176, 2, 176, 2, 176, 2, 176, 2, 208, 2, 208, 2, 208, 2, 208,
1701 2, 240, 2, 240, 2, 240, 2, 240, 2, 16, 3, 16, 3, 16, 3, 16, 3, 48, 3, 48, 3, 48, 3, 48,
1702 3, 80, 3, 80, 3, 80, 3, 80, 3, 112, 3, 112, 3, 112, 3, 112, 3, 144, 3, 144, 3, 144, 3,
1703 144, 3, 176, 3, 176, 3, 176, 3, 176, 3, 208, 3, 208, 3, 208, 3, 208, 3, 240, 3, 240, 3,
1704 240, 3, 240, 3, 16, 4, 16, 4, 16, 4, 16, 4, 48, 4, 48, 4, 48, 4, 48, 4, 80, 4, 80, 4,
1705 80, 4, 80, 4, 112, 4, 112, 4, 112, 4, 112, 4, 0, 0, 16, 0, 32, 0, 48, 0, 64, 0, 80, 0,
1706 96, 0, 112, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32,
1707 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48,
1708 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 128, 0, 128, 0, 128, 0, 128,
1709 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1710 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1711 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1712 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1713 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1714 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1715 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1716 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1717 0, 160, 0, 160, 0, 160, 0, 160, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1718 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1719 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1720 0, 176, 0, 176, 0, 176, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1721 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1722 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1723 0, 192, 0, 192, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1724 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1725 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1726 0, 208, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1727 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1728 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1729 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1730 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1731 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 0,
1732 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1733 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
1734 1, 0, 1, 0, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1,
1735 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16,
1736 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 32, 1, 32, 1, 32, 1,
1737 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32,
1738 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1,
1739 32, 1, 32, 1, 32, 1, 32, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48,
1740 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1,
1741 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 64, 1, 64,
1742 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1,
1743 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64,
1744 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1,
1745 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80,
1746 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1,
1747 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96,
1748 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1,
1749 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 128, 0, 136, 0, 136, 0, 136, 0, 136,
1750 0, 136, 0, 136, 0, 136, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
1751 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
1752 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1753 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1754 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1755 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1756 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1757 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1758 200, 0, 200, 0, 200, 0, 200, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1759 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1760 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1761 232, 0, 232, 0, 232, 0, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8,
1762 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1,
1763 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40,
1764 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1,
1765 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40,
1766 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1,
1767 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72,
1768 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1769 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1770 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1771 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1772 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1773 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1774 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1775 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1776 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1777 168, 1, 168, 1, 168, 1, 168, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1778 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1779 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1780 200, 1, 200, 1, 200, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1781 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1782 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1783 232, 1, 232, 1, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2,
1784 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8,
1785 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40,
1786 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2,
1787 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 72,
1788 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2,
1789 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72,
1790 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1791 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1792 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1793 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 244, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1794 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1795 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1796 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1798 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1799 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1800 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
1801 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
1802 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
1803 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
1804 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
1805 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
1806 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1807 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 0,
1808 ];
1809 assert_eq!(trie_serialized, EXP_TRIE_SERIALIZED);
1810
1811 let trie_deserialized = postcard::from_bytes::<CodePointTrie<u8>>(&trie_serialized)?;
1812
1813 assert_eq!(&trie.index, &trie_deserialized.index);
1814 assert_eq!(&trie.data, &trie_deserialized.data);
1815
1816 assert!(!trie_deserialized.index.is_owned());
1817 assert!(!trie_deserialized.data.is_owned());
1818
1819 Ok(())
1820 }
1821
1822 #[test]
1823 fn test_typed() {
1824 let untyped = planes::get_planes_trie();
1825 assert_eq!(untyped.get('\u{10000}'), 1);
1826 let small_ref = <&SmallCodePointTrie<_>>::try_from(&untyped).unwrap();
1827 assert_eq!(small_ref.get('\u{10000}'), 1);
1828 let _ = <&FastCodePointTrie<_>>::try_from(&untyped).is_err();
1829 let small = <SmallCodePointTrie<_>>::try_from(untyped).unwrap();
1830 assert_eq!(small.get('\u{10000}'), 1);
1831 }
1832
1833 #[test]
1834 fn test_get_range() {
1835 let planes_trie = planes::get_planes_trie();
1836
1837 let first_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x0);
1838 assert_eq!(
1839 first_range,
1840 Some(CodePointMapRange {
1841 range: 0x0..=0xffff,
1842 value: 0
1843 })
1844 );
1845
1846 let second_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x1_0000);
1847 assert_eq!(
1848 second_range,
1849 Some(CodePointMapRange {
1850 range: 0x10000..=0x1ffff,
1851 value: 1
1852 })
1853 );
1854
1855 let penultimate_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0xf_0000);
1856 assert_eq!(
1857 penultimate_range,
1858 Some(CodePointMapRange {
1859 range: 0xf_0000..=0xf_ffff,
1860 value: 15
1861 })
1862 );
1863
1864 let last_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x10_0000);
1865 assert_eq!(
1866 last_range,
1867 Some(CodePointMapRange {
1868 range: 0x10_0000..=0x10_ffff,
1869 value: 16
1870 })
1871 );
1872 }
1873
1874 #[test]
1875 fn databake() {
1876 databake::test_bake!(
1877 CodePointTrie<'static, u32>,
1878 const,
1879 unsafe {
1880 #[allow(unused_unsafe)]
1881 crate::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(
1882 crate::codepointtrie::CodePointTrieHeader {
1883 high_start: 1u32,
1884 shifted12_high_start: 2u16,
1885 index3_null_offset: 3u16,
1886 data_null_offset: 4u32,
1887 null_value: 5u32,
1888 trie_type: crate::codepointtrie::TrieType::Small,
1889 },
1890 zerovec::ZeroVec::new(),
1891 zerovec::ZeroVec::new(),
1892 0u32,
1893 5u32,
1894 )
1895 },
1896 icu_collections,
1897 [zerovec],
1898 );
1899 }
1900}