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]
#[allow(clippy::exhaustive_enums)]
impl ::core::clone::Clone for TrieType {
#[inline]
fn clone(&self) -> TrieType { *self }
}Clone, #[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::marker::Copy for TrieType { }Copy, #[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::cmp::PartialEq for TrieType {
#[inline]
fn eq(&self, other: &TrieType) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}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 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}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_field4_finish(f, "CodePointTrie",
"header", &self.header, "index", &self.index, "data", &self.data,
"error_value", &&self.error_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::cmp::PartialEq for
CodePointTrie<'trie, T> {
#[inline]
fn eq(&self, other: &CodePointTrie<'trie, T>) -> bool {
self.header == other.header && self.index == other.index &&
self.data == other.data &&
self.error_value == other.error_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 } => {
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(),
}
}
}
}
}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}
164
165#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
174#[cfg_attr(feature = "databake", derive(databake::Bake))]
175#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
176#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::marker::Copy for CodePointTrieHeader { }Copy, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::clone::Clone for CodePointTrieHeader {
#[inline]
fn clone(&self) -> CodePointTrieHeader {
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 _ =
&["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,
"CodePointTrieHeader", 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::cmp::PartialEq for CodePointTrieHeader {
#[inline]
fn eq(&self, other: &CodePointTrieHeader) -> 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)]
177#[allow(clippy::exhaustive_structs)] pub struct CodePointTrieHeader {
179 pub high_start: u32,
191 pub shifted12_high_start: u16,
195 pub index3_null_offset: u16,
199 pub data_null_offset: u32,
203 pub null_value: u32,
206 pub trie_type: TrieType,
213}
214
215impl TryFrom<u8> for TrieType {
216 type Error = Error;
217
218 fn try_from(trie_type_int: u8) -> Result<TrieType, Error> {
219 match trie_type_int {
220 0 => Ok(TrieType::Fast),
221 1 => Ok(TrieType::Small),
222 _ => Err(Error::FromDeserialized {
223 reason: "Cannot parse value for trie_type",
224 }),
225 }
226 }
227}
228
229macro_rules! w(
237 ($a:tt + $b:expr) => {
240 {
241 #[allow(unused_parens)]
242 let a = $a;
243 let b = $b;
244 debug_assert!(a.checked_add(b).is_some());
245 $a.wrapping_add($b)
246 }
247 };
248 ($a:tt - $b:expr) => {
249
250 {
251 #[allow(unused_parens)]
252 let a = $a;
253 let b = $b;
254 debug_assert!(a.checked_sub(b).is_some());
255 $a.wrapping_sub($b)
256 }
257 };
258 ($a:tt * $b:expr) => {
259 {
260 #[allow(unused_parens)]
261 let a = $a;
262 let b = $b;
263 debug_assert!(a.checked_mul(b).is_some());
264 $a.wrapping_mul($b)
265 }
266 };
267);
268
269impl<'trie, T: TrieValue> CodePointTrie<'trie, T> {
270 #[doc(hidden)] pub const unsafe fn from_parts_unstable_unchecked_v1(
277 header: CodePointTrieHeader,
278 index: ZeroVec<'trie, u16>,
279 data: ZeroVec<'trie, T>,
280 error_value: T,
281 ) -> Self {
282 Self {
287 header,
288 index,
289 data,
290 error_value,
291 }
292 }
293
294 pub fn try_new(
297 header: CodePointTrieHeader,
298 index: ZeroVec<'trie, u16>,
299 data: ZeroVec<'trie, T>,
300 ) -> Result<CodePointTrie<'trie, T>, Error> {
301 let error_value = Self::validate_fields(&header, &index, &data)?;
302 let trie: CodePointTrie<'trie, T> = CodePointTrie {
304 header,
305 index,
306 data,
307 error_value,
308 };
309 Ok(trie)
310 }
311
312 pub(crate) fn validate_fields(
322 header: &CodePointTrieHeader,
323 index: &ZeroSlice<u16>,
324 data: &ZeroSlice<T>,
325 ) -> Result<T, Error> {
326 let error_value = data.last().ok_or(Error::EmptyDataVector)?;
327
328 let fast_max = match header.trie_type {
357 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
358 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
359 };
360 let max_bit_prefix = fast_max >> FAST_TYPE_SHIFT;
362 let fast_index = index
367 .get_subslice(0..(max_bit_prefix as usize) + 1)
368 .ok_or(Error::IndexTooShortForFastAccess)?;
369 let max_offset = fast_index
378 .iter()
379 .max()
380 .ok_or(Error::IndexTooShortForFastAccess)?;
381 if (max_offset) as usize + (FAST_TYPE_DATA_MASK as usize) >= data.len() {
385 return Err(Error::DataTooShortForFastAccess);
386 }
387
388 Ok(error_value)
394 }
395
396 #[inline]
398 pub fn to_typed(self) -> Typed<FastCodePointTrie<'trie, T>, SmallCodePointTrie<'trie, T>> {
399 match self.header.trie_type {
400 TrieType::Fast => Typed::Fast(FastCodePointTrie { inner: self }),
401 TrieType::Small => Typed::Small(SmallCodePointTrie { inner: self }),
402 }
403 }
404
405 #[inline]
407 pub fn as_typed_ref(
408 &self,
409 ) -> Typed<&FastCodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>> {
410 match self.header.trie_type {
414 TrieType::Fast => Typed::Fast(unsafe {
415 &*(self as *const CodePointTrie<'trie, T> as *const FastCodePointTrie<'trie, T>)
416 }),
417 TrieType::Small => Typed::Small(unsafe {
418 &*(self as *const CodePointTrie<'trie, T> as *const SmallCodePointTrie<'trie, T>)
419 }),
420 }
421 }
422
423 #[inline(always)] fn trie_error_val_index(&self) -> u32 {
427 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);
431 {
#[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)
432 }
433
434 fn internal_small_index(&self, code_point: u32) -> u32 {
435 let mut index1_pos: u32 = code_point >> SHIFT_1;
439 if self.header.trie_type == TrieType::Fast {
440 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!(
441 FAST_TYPE_FAST_INDEXING_MAX < code_point && code_point < self.header.high_start
442 );
443 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);
444 } else {
445 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);
446 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);
447 }
448 let index1_val = if let Some(index1_val) = self.index.get(index1_pos as usize) {
449 index1_val
450 } else {
451 return self.trie_error_val_index();
452 };
453 let index3_block_idx: u32 =
454 {
#[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);
455 let mut index3_block: u32 =
456 if let Some(index3_block) = self.index.get(index3_block_idx as usize) {
457 index3_block as u32
458 } else {
459 return self.trie_error_val_index();
460 };
461 let mut index3_pos: u32 = (code_point >> SHIFT_3) & INDEX_3_MASK;
462 let mut data_block: u32;
463 if index3_block & 0x8000 == 0 {
464 data_block =
466 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) {
467 data_block as u32
468 } else {
469 return self.trie_error_val_index();
470 };
471 } else {
472 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));
474 index3_pos &= 7;
475 data_block = if let Some(data_block) = self.index.get(index3_block as usize) {
476 data_block as u32
477 } else {
478 return self.trie_error_val_index();
479 };
480 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;
481 index3_block += 1;
482 data_block =
483 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) {
484 data_block | (index3_val as u32)
485 } else {
486 return self.trie_error_val_index();
487 };
488 }
489 {
#[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)
492 }
493
494 fn small_index(&self, code_point: u32) -> u32 {
505 if code_point >= self.header.high_start {
506 {
#[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)
507 } else {
508 self.internal_small_index(code_point) }
510 }
511
512 fn fast_index(&self, code_point: u32) -> u32 {
524 let index_array_pos: u32 = code_point >> FAST_TYPE_SHIFT;
525 let index_array_val: u16 =
526 if let Some(index_array_val) = self.index.get(index_array_pos as usize) {
527 index_array_val
528 } else {
529 return self.trie_error_val_index();
530 };
531 let masked_cp = code_point & FAST_TYPE_DATA_MASK;
532 let index_array_val = index_array_val as u32;
533 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);
534 fast_index_val
535 }
536
537 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
542 let fast_max = match self.header.trie_type {
543 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
544 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
545 };
546 if code_point <= fast_max {
547 Some(unsafe { self.get32_assuming_fast_index(code_point) })
554 } else {
555 None
558 }
559 }
560
561 #[inline(always)]
569 unsafe fn get32_assuming_fast_index(&self, code_point: u32) -> T {
570 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!(
572 code_point
573 <= match self.header.trie_type {
574 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
575 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
576 }
577 );
578
579 let bit_prefix = (code_point as usize) >> FAST_TYPE_SHIFT;
580 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());
581 let base_offset_to_data: usize = usize::from(u16::from_unaligned(*unsafe {
585 self.index.as_ule_slice().get_unchecked(bit_prefix)
586 }));
587 let bit_suffix = (code_point & FAST_TYPE_DATA_MASK) as usize;
588 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);
594 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());
595 T::from_unaligned(*unsafe { self.data.as_ule_slice().get_unchecked(offset_to_data) })
599 }
600
601 #[cold]
604 #[inline(always)]
605 fn get32_by_small_index_cold(&self, code_point: u32) -> T {
606 self.get32_by_small_index(code_point)
607 }
608
609 #[inline(never)]
622 fn get32_by_small_index(&self, code_point: u32) -> T {
623 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);
624 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!(
625 code_point
626 > match self.header.trie_type {
627 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
628 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
629 }
630 );
631 self.data
632 .get(self.small_index(code_point) as usize)
633 .unwrap_or(self.error_value)
634 }
635
636 #[inline(always)] pub fn get32(&self, code_point: u32) -> T {
650 if let Some(v) = self.get32_by_fast_index(code_point) {
651 v
652 } else if code_point <= CODE_POINT_MAX {
653 self.get32_by_small_index_cold(code_point)
654 } else {
655 self.error_value
656 }
657 }
658
659 #[inline(always)]
672 pub fn get(&self, c: char) -> T {
673 let code_point = u32::from(c);
677 if let Some(v) = self.get32_by_fast_index(code_point) {
678 v
679 } else {
680 self.get32_by_small_index_cold(code_point)
681 }
682 }
683
684 #[inline(always)]
686 pub fn get16(&self, bmp: u16) -> T {
687 let code_point = u32::from(bmp);
691 if let Some(v) = self.get32_by_fast_index(code_point) {
692 v
693 } else {
694 self.get32_by_small_index_cold(code_point)
695 }
696 }
697
698 #[inline(always)]
704 pub fn get32_supplementary(&self, supplementary: u32) -> T {
705 if true {
if !(supplementary > 0xFFFF) {
::core::panicking::panic("assertion failed: supplementary > 0xFFFF")
};
};debug_assert!(supplementary > 0xFFFF);
706 if true {
if !(supplementary <= CODE_POINT_MAX) {
::core::panicking::panic("assertion failed: supplementary <= CODE_POINT_MAX")
};
};debug_assert!(supplementary <= CODE_POINT_MAX);
707 self.get32_by_small_index(supplementary)
708 }
709
710 #[inline(always)] pub fn get32_ule(&self, code_point: u32) -> Option<&T::ULE> {
724 let fast_max = match self.header.trie_type {
729 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
730 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
731 };
732 let data_pos: u32 = if code_point <= fast_max {
733 Self::fast_index(self, code_point)
734 } else if code_point <= CODE_POINT_MAX {
735 Self::small_index(self, code_point)
736 } else {
737 self.trie_error_val_index()
738 };
739 self.data.as_ule_slice().get(data_pos as usize)
741 }
742
743 #[cfg(feature = "alloc")]
772 pub fn try_into_converted<P>(self) -> Result<CodePointTrie<'trie, P>, UleError>
773 where
774 P: TrieValue,
775 {
776 let converted_data = self.data.try_into_converted()?;
777 let error_ule = self.error_value.to_unaligned();
778 let slice = &[error_ule];
779 let error_vec = ZeroVec::<T>::new_borrowed(slice);
780 let error_converted = error_vec.try_into_converted::<P>()?;
781 #[expect(clippy::expect_used)] Ok(CodePointTrie {
783 header: self.header,
784 index: self.index,
785 data: converted_data,
786 error_value: error_converted
787 .get(0)
788 .expect("vector known to have one element"),
789 })
790 }
791
792 #[cfg(feature = "alloc")]
815 pub fn try_alloc_map_value<P, E>(
816 &self,
817 mut f: impl FnMut(T) -> Result<P, E>,
818 ) -> Result<CodePointTrie<'trie, P>, E>
819 where
820 P: TrieValue,
821 {
822 let error_converted = f(self.error_value)?;
823 let converted_data = self.data.iter().map(f).collect::<Result<ZeroVec<P>, E>>()?;
824 Ok(CodePointTrie {
825 header: self.header,
826 index: self.index.clone(),
827 data: converted_data,
828 error_value: error_converted,
829 })
830 }
831
832 pub fn get_range(&self, start: u32) -> Option<CodePointMapRange<T>> {
886 if CODE_POINT_MAX < start {
890 return None;
891 }
892 if start >= self.header.high_start {
893 let di: usize = self.data.len() - (HIGH_VALUE_NEG_DATA_OFFSET as usize);
894 let value: T = self.data.get(di)?;
895 return Some(CodePointMapRange {
896 range: start..=CODE_POINT_MAX,
897 value,
898 });
899 }
900
901 let null_value: T = T::try_from_u32(self.header.null_value).ok()?;
902
903 let mut prev_i3_block: u32 = u32::MAX; let mut prev_block: u32 = u32::MAX; let mut c: u32 = start;
906 let mut trie_value: T = self.error_value();
907 let mut value: T = self.error_value();
908 let mut have_value: bool = false;
909
910 loop {
911 let i3_block: u32;
912 let mut i3: u32;
913 let i3_block_length: u32;
914 let data_block_length: u32;
915
916 if c <= 0xffff
929 && (self.header.trie_type == TrieType::Fast || c <= SMALL_TYPE_FAST_INDEXING_MAX)
930 {
931 i3_block = 0;
932 i3 = c >> FAST_TYPE_SHIFT;
933 i3_block_length = if self.header.trie_type == TrieType::Fast {
934 BMP_INDEX_LENGTH
935 } else {
936 SMALL_INDEX_LENGTH
937 };
938 data_block_length = FAST_TYPE_DATA_BLOCK_LENGTH;
939 } else {
940 let mut i1: u32 = c >> SHIFT_1;
942 if self.header.trie_type == TrieType::Fast {
943 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);
944 i1 = i1 + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH;
945 } else {
946 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!(
947 c < self.header.high_start && self.header.high_start > SMALL_LIMIT
948 );
949 i1 += SMALL_INDEX_LENGTH;
950 }
951 let i2: u16 = self.index.get(i1 as usize)?;
952 let i3_block_idx: u32 = (i2 as u32) + ((c >> SHIFT_2) & INDEX_2_MASK);
953 i3_block = self.index.get(i3_block_idx as usize)? as u32;
954 if i3_block == prev_i3_block && (c - start) >= CP_PER_INDEX_2_ENTRY {
955 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);
957 c += CP_PER_INDEX_2_ENTRY;
958
959 if c >= self.header.high_start {
960 break;
961 } else {
962 continue;
963 }
964 }
965 prev_i3_block = i3_block;
966 if i3_block == self.header.index3_null_offset as u32 {
967 if have_value {
974 if null_value != value {
975 return Some(CodePointMapRange {
976 range: start..=(c - 1),
977 value,
978 });
979 }
980 } else {
981 trie_value = T::try_from_u32(self.header.null_value).ok()?;
982 value = null_value;
983 have_value = true;
984 }
985 prev_block = self.header.data_null_offset;
986 c = (c + CP_PER_INDEX_2_ENTRY) & !(CP_PER_INDEX_2_ENTRY - 1);
987
988 if c >= self.header.high_start {
989 break;
990 } else {
991 continue;
992 }
993 }
994 i3 = (c >> SHIFT_3) & INDEX_3_MASK;
995 i3_block_length = INDEX_3_BLOCK_LENGTH;
996 data_block_length = SMALL_DATA_BLOCK_LENGTH;
997 }
998
999 loop {
1001 let mut block: u32;
1002 if (i3_block & 0x8000) == 0 {
1003 block = self.index.get((i3_block + i3) as usize)? as u32;
1004 } else {
1005 let mut group: u32 = (i3_block & 0x7fff) + (i3 & !7) + (i3 >> 3);
1007 let gi: u32 = i3 & 7;
1008 let gi_val: u32 = self.index.get(group as usize)?.into();
1009 block = (gi_val << (2 + (2 * gi))) & 0x30000;
1010 group += 1;
1011 let ggi_val: u32 = self.index.get((group + gi) as usize)? as u32;
1012 block |= ggi_val;
1013 }
1014
1015 if block == prev_block && (c - start) >= data_block_length {
1023 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);
1025 c += data_block_length;
1026 } else {
1027 let data_mask: u32 = data_block_length - 1;
1028 prev_block = block;
1029 if block == self.header.data_null_offset {
1030 if have_value {
1035 if null_value != value {
1036 return Some(CodePointMapRange {
1037 range: start..=(c - 1),
1038 value,
1039 });
1040 }
1041 } else {
1042 trie_value = T::try_from_u32(self.header.null_value).ok()?;
1043 value = null_value;
1044 have_value = true;
1045 }
1046 c = (c + data_block_length) & !data_mask;
1047 } else {
1048 let mut di: u32 = block + (c & data_mask);
1049 let mut trie_value_2: T = self.data.get(di as usize)?;
1050 if have_value {
1051 if trie_value_2 != trie_value {
1052 if maybe_filter_value(
1053 trie_value_2,
1054 T::try_from_u32(self.header.null_value).ok()?,
1055 null_value,
1056 ) != value
1057 {
1058 return Some(CodePointMapRange {
1059 range: start..=(c - 1),
1060 value,
1061 });
1062 }
1063 trie_value = trie_value_2; }
1082 } else {
1083 trie_value = trie_value_2;
1084 value = maybe_filter_value(
1085 trie_value_2,
1086 T::try_from_u32(self.header.null_value).ok()?,
1087 null_value,
1088 );
1089 have_value = true;
1090 }
1091
1092 c += 1;
1093 while (c & data_mask) != 0 {
1094 di += 1;
1095 trie_value_2 = self.data.get(di as usize)?;
1096 if trie_value_2 != trie_value {
1097 if maybe_filter_value(
1098 trie_value_2,
1099 T::try_from_u32(self.header.null_value).ok()?,
1100 null_value,
1101 ) != value
1102 {
1103 return Some(CodePointMapRange {
1104 range: start..=(c - 1),
1105 value,
1106 });
1107 }
1108 trie_value = trie_value_2; }
1127
1128 c += 1;
1129 }
1130 }
1131 }
1132
1133 i3 += 1;
1134 if i3 >= i3_block_length {
1135 break;
1136 }
1137 }
1138
1139 if c >= self.header.high_start {
1140 break;
1141 }
1142 }
1143
1144 if true {
if !have_value {
::core::panicking::panic("assertion failed: have_value")
};
};debug_assert!(have_value);
1145
1146 let di: u32 = self.data.len() as u32 - HIGH_VALUE_NEG_DATA_OFFSET;
1151 let high_value: T = self.data.get(di as usize)?;
1152 if maybe_filter_value(
1153 high_value,
1154 T::try_from_u32(self.header.null_value).ok()?,
1155 null_value,
1156 ) != value
1157 {
1158 c -= 1;
1159 } else {
1160 c = CODE_POINT_MAX;
1161 }
1162 Some(CodePointMapRange {
1163 range: start..=c,
1164 value,
1165 })
1166 }
1167
1168 pub fn iter_ranges(&self) -> CodePointMapRangeIterator<'_, T> {
1201 let init_range = Some(CodePointMapRange {
1202 range: u32::MAX..=u32::MAX,
1203 value: self.error_value(),
1204 });
1205 CodePointMapRangeIterator::<T> {
1206 cpt: self,
1207 cpm_range: init_range,
1208 }
1209 }
1210
1211 pub fn iter_ranges_for_value(
1233 &self,
1234 value: T,
1235 ) -> impl Iterator<Item = RangeInclusive<u32>> + '_ {
1236 self.iter_ranges()
1237 .filter(move |cpm_range| cpm_range.value == value)
1238 .map(|cpm_range| cpm_range.range)
1239 }
1240
1241 pub fn iter_ranges_mapped<'a, U: Eq + 'a>(
1263 &'a self,
1264 mut map: impl FnMut(T) -> U + Copy + 'a,
1265 ) -> impl Iterator<Item = CodePointMapRange<U>> + 'a {
1266 crate::iterator_utils::RangeListIteratorCoalescer::new(self.iter_ranges().map(
1267 move |range| CodePointMapRange {
1268 range: range.range,
1269 value: map(range.value),
1270 },
1271 ))
1272 }
1273
1274 #[cfg(feature = "alloc")]
1298 pub fn get_set_for_value(&self, value: T) -> CodePointInversionList<'static> {
1299 let value_ranges = self.iter_ranges_for_value(value);
1300 CodePointInversionList::from_iter(value_ranges)
1301 }
1302
1303 #[inline]
1305 pub fn error_value(&self) -> T {
1306 self.error_value
1307 }
1308}
1309
1310#[cfg(feature = "databake")]
1311impl<T: TrieValue + databake::Bake> databake::Bake for CodePointTrie<'_, T> {
1312 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
1313 let header = self.header.bake(env);
1314 let index = self.index.bake(env);
1315 let data = self.data.bake(env);
1316 let error_value = self.error_value.bake(env);
1317 databake::quote! { unsafe {
1318 #[allow(unused_unsafe)]
1319 icu_collections::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(#header, #index, #data, #error_value)
1320 }}
1321 }
1322}
1323
1324#[cfg(feature = "databake")]
1325impl<T: TrieValue + databake::Bake> databake::BakeSize for CodePointTrie<'_, T> {
1326 fn borrows_size(&self) -> usize {
1327 self.header.borrows_size() + self.index.borrows_size() + self.data.borrows_size()
1328 }
1329}
1330
1331impl<T: TrieValue + Into<u32>> CodePointTrie<'_, T> {
1332 pub fn get32_u32(&self, code_point: u32) -> u32 {
1350 self.get32(code_point).into()
1351 }
1352}
1353
1354impl<T: TrieValue> Clone for CodePointTrie<'_, T>
1355where
1356 <T as AsULE>::ULE: Clone,
1357{
1358 fn clone(&self) -> Self {
1359 CodePointTrie {
1360 header: self.header,
1361 index: self.index.clone(),
1362 data: self.data.clone(),
1363 error_value: self.error_value,
1364 }
1365 }
1366}
1367
1368#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
CodePointMapRange<T> {
#[inline]
fn eq(&self, other: &CodePointMapRange<T>) -> 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", &self.range, "value", &&self.value)
}
}Debug, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for CodePointMapRange<T> {
#[inline]
fn clone(&self) -> CodePointMapRange<T> {
CodePointMapRange {
range: ::core::clone::Clone::clone(&self.range),
value: ::core::clone::Clone::clone(&self.value),
}
}
}Clone)]
1374#[allow(clippy::exhaustive_structs)] pub struct CodePointMapRange<T> {
1376 pub range: RangeInclusive<u32>,
1378 pub value: T,
1380}
1381
1382#[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", &self.cpt, "cpm_range",
&&self.cpm_range)
}
}Debug)]
1385pub struct CodePointMapRangeIterator<'a, T: TrieValue> {
1386 cpt: &'a CodePointTrie<'a, T>,
1387 cpm_range: Option<CodePointMapRange<T>>,
1394}
1395
1396impl<T: TrieValue> Iterator for CodePointMapRangeIterator<'_, T> {
1397 type Item = CodePointMapRange<T>;
1398
1399 fn next(&mut self) -> Option<Self::Item> {
1400 self.cpm_range = match &self.cpm_range {
1401 Some(cpmr) => {
1402 if *cpmr.range.start() == u32::MAX {
1403 self.cpt.get_range(0)
1404 } else {
1405 self.cpt.get_range(cpmr.range.end() + 1)
1406 }
1407 }
1408 None => None,
1409 };
1410 self.cpm_range.clone()
1412 }
1413}
1414
1415trait Seal {}
1421
1422#[allow(private_bounds)] pub trait TypedCodePointTrie<'trie, T: TrieValue>: Seal {
1426 const TRIE_TYPE: TrieType;
1432
1433 #[inline(always)]
1435 fn get32_u32(&self, code_point: u32) -> u32 {
1436 self.get32(code_point).to_u32()
1437 }
1438
1439 #[inline(always)]
1441 fn get16(&self, bmp: u16) -> T {
1442 let code_point = u32::from(bmp);
1446 if let Some(v) = self.get32_by_fast_index(code_point) {
1447 v
1448 } else {
1449 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1450 }
1451 }
1452
1453 #[inline(always)]
1455 fn get32_supplementary(&self, supplementary: u32) -> T {
1456 self.as_untyped_ref().get32_supplementary(supplementary)
1457 }
1458
1459 #[inline(always)]
1461 fn get(&self, c: char) -> T {
1462 let code_point = u32::from(c);
1466 if let Some(v) = self.get32_by_fast_index(code_point) {
1467 v
1468 } else {
1469 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1470 }
1471 }
1472
1473 #[inline(always)]
1475 fn get32(&self, code_point: u32) -> T {
1476 if let Some(v) = self.get32_by_fast_index(code_point) {
1477 v
1478 } else if code_point <= CODE_POINT_MAX {
1479 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1480 } else {
1481 self.as_untyped_ref().error_value
1482 }
1483 }
1484
1485 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
1490 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);
1491 let fast_max = match Self::TRIE_TYPE {
1492 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
1493 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
1494 };
1495 if code_point <= fast_max {
1496 Some(unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) })
1507 } else {
1508 None
1511 }
1512 }
1513
1514 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T>;
1516
1517 fn to_untyped(self) -> CodePointTrie<'trie, T>;
1519}
1520
1521#[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)]
1526#[repr(transparent)]
1527pub struct FastCodePointTrie<'trie, T: TrieValue> {
1528 inner: CodePointTrie<'trie, T>,
1529}
1530
1531impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for FastCodePointTrie<'trie, T> {
1532 const TRIE_TYPE: TrieType = TrieType::Fast;
1533
1534 #[inline(always)]
1536 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1537 &self.inner
1538 }
1539
1540 #[inline(always)]
1542 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1543 self.inner
1544 }
1545
1546 #[inline(always)]
1548 fn get16(&self, bmp: u16) -> T {
1549 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);
1550 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);
1551 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);
1552 let code_point = u32::from(bmp);
1553 unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) }
1562 }
1563}
1564
1565impl<'trie, T: TrieValue> Seal for FastCodePointTrie<'trie, T> {}
1566
1567impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1568 for &'trie FastCodePointTrie<'trie, T>
1569{
1570 type Error = TypedCodePointTrieError;
1571
1572 fn try_from(
1573 reference: &'trie CodePointTrie<'trie, T>,
1574 ) -> Result<&'trie FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1575 match reference.as_typed_ref() {
1576 Typed::Fast(trie) => Ok(trie),
1577 Typed::Small(_) => Err(TypedCodePointTrieError),
1578 }
1579 }
1580}
1581
1582impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for FastCodePointTrie<'trie, T> {
1583 type Error = TypedCodePointTrieError;
1584
1585 fn try_from(
1586 value: CodePointTrie<'trie, T>,
1587 ) -> Result<FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1588 match value.to_typed() {
1589 Typed::Fast(trie) => Ok(trie),
1590 Typed::Small(_) => Err(TypedCodePointTrieError),
1591 }
1592 }
1593}
1594
1595#[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)]
1598#[repr(transparent)]
1599pub struct SmallCodePointTrie<'trie, T: TrieValue> {
1600 inner: CodePointTrie<'trie, T>,
1601}
1602
1603impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for SmallCodePointTrie<'trie, T> {
1604 const TRIE_TYPE: TrieType = TrieType::Small;
1605
1606 #[inline(always)]
1608 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1609 &self.inner
1610 }
1611
1612 #[inline(always)]
1614 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1615 self.inner
1616 }
1617}
1618
1619impl<'trie, T: TrieValue> Seal for SmallCodePointTrie<'trie, T> {}
1620
1621impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1622 for &'trie SmallCodePointTrie<'trie, T>
1623{
1624 type Error = TypedCodePointTrieError;
1625
1626 fn try_from(
1627 reference: &'trie CodePointTrie<'trie, T>,
1628 ) -> Result<&'trie SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1629 match reference.as_typed_ref() {
1630 Typed::Fast(_) => Err(TypedCodePointTrieError),
1631 Typed::Small(trie) => Ok(trie),
1632 }
1633 }
1634}
1635
1636impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for SmallCodePointTrie<'trie, T> {
1637 type Error = TypedCodePointTrieError;
1638
1639 fn try_from(
1640 value: CodePointTrie<'trie, T>,
1641 ) -> Result<SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1642 match value.to_typed() {
1643 Typed::Fast(_) => Err(TypedCodePointTrieError),
1644 Typed::Small(trie) => Ok(trie),
1645 }
1646 }
1647}
1648
1649#[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)]
1652#[non_exhaustive]
1653pub struct TypedCodePointTrieError;
1654
1655#[allow(clippy::exhaustive_enums)]
1658#[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 {
Typed::Fast(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Fast",
&__self_0),
Typed::Small(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Small",
&__self_0),
}
}
}Debug)]
1659pub enum Typed<F, S> {
1660 Fast(F),
1662 Small(S),
1664}
1665
1666#[cfg(test)]
1667mod tests {
1668 use super::*;
1669 use crate::codepointtrie::planes;
1670 use alloc::vec::Vec;
1671
1672 #[test]
1673 #[cfg(feature = "serde")]
1674 fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> {
1675 let trie = planes::get_planes_trie();
1676 let trie_serialized: Vec<u8> = postcard::to_allocvec(&trie).unwrap();
1677
1678 const EXP_TRIE_SERIALIZED: &[u8] = &[
1680 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,
1681 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,
1682 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,
1683 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,
1684 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,
1685 2, 144, 2, 144, 2, 144, 2, 176, 2, 176, 2, 176, 2, 176, 2, 208, 2, 208, 2, 208, 2, 208,
1686 2, 240, 2, 240, 2, 240, 2, 240, 2, 16, 3, 16, 3, 16, 3, 16, 3, 48, 3, 48, 3, 48, 3, 48,
1687 3, 80, 3, 80, 3, 80, 3, 80, 3, 112, 3, 112, 3, 112, 3, 112, 3, 144, 3, 144, 3, 144, 3,
1688 144, 3, 176, 3, 176, 3, 176, 3, 176, 3, 208, 3, 208, 3, 208, 3, 208, 3, 240, 3, 240, 3,
1689 240, 3, 240, 3, 16, 4, 16, 4, 16, 4, 16, 4, 48, 4, 48, 4, 48, 4, 48, 4, 80, 4, 80, 4,
1690 80, 4, 80, 4, 112, 4, 112, 4, 112, 4, 112, 4, 0, 0, 16, 0, 32, 0, 48, 0, 64, 0, 80, 0,
1691 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,
1692 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,
1693 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 128, 0, 128, 0, 128, 0, 128,
1694 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1695 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1696 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1697 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1698 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1699 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1700 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1701 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1702 0, 160, 0, 160, 0, 160, 0, 160, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1703 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1704 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1705 0, 176, 0, 176, 0, 176, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1706 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1707 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1708 0, 192, 0, 192, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1709 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1710 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1711 0, 208, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1712 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1713 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1714 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1715 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1716 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 0,
1717 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,
1718 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,
1719 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,
1720 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,
1721 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,
1722 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,
1723 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,
1724 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,
1725 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,
1726 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,
1727 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,
1728 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,
1729 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,
1730 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,
1731 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,
1732 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,
1733 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,
1734 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 128, 0, 136, 0, 136, 0, 136, 0, 136,
1735 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,
1736 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,
1737 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,
1738 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1739 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1740 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1741 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1742 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1743 200, 0, 200, 0, 200, 0, 200, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1744 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1745 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1746 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,
1747 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,
1748 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,
1749 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,
1750 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,
1751 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,
1752 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,
1753 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1754 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1755 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1756 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1757 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1758 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1759 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1760 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1761 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1762 168, 1, 168, 1, 168, 1, 168, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1763 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1764 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1765 200, 1, 200, 1, 200, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1766 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1767 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1768 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,
1769 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,
1770 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,
1771 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,
1772 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,
1773 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,
1774 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,
1775 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1776 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1777 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1778 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,
1779 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,
1780 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,
1781 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,
1782 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,
1783 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,
1784 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,
1785 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,
1786 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,
1787 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,
1788 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
1789 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
1790 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
1791 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1792 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 0,
1793 ];
1794 assert_eq!(trie_serialized, EXP_TRIE_SERIALIZED);
1795
1796 let trie_deserialized = postcard::from_bytes::<CodePointTrie<u8>>(&trie_serialized)?;
1797
1798 assert_eq!(&trie.index, &trie_deserialized.index);
1799 assert_eq!(&trie.data, &trie_deserialized.data);
1800
1801 assert!(!trie_deserialized.index.is_owned());
1802 assert!(!trie_deserialized.data.is_owned());
1803
1804 Ok(())
1805 }
1806
1807 #[test]
1808 fn test_typed() {
1809 let untyped = planes::get_planes_trie();
1810 assert_eq!(untyped.get('\u{10000}'), 1);
1811 let small_ref = <&SmallCodePointTrie<_>>::try_from(&untyped).unwrap();
1812 assert_eq!(small_ref.get('\u{10000}'), 1);
1813 let _ = <&FastCodePointTrie<_>>::try_from(&untyped).is_err();
1814 let small = <SmallCodePointTrie<_>>::try_from(untyped).unwrap();
1815 assert_eq!(small.get('\u{10000}'), 1);
1816 }
1817
1818 #[test]
1819 fn test_get_range() {
1820 let planes_trie = planes::get_planes_trie();
1821
1822 let first_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x0);
1823 assert_eq!(
1824 first_range,
1825 Some(CodePointMapRange {
1826 range: 0x0..=0xffff,
1827 value: 0
1828 })
1829 );
1830
1831 let second_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x1_0000);
1832 assert_eq!(
1833 second_range,
1834 Some(CodePointMapRange {
1835 range: 0x10000..=0x1ffff,
1836 value: 1
1837 })
1838 );
1839
1840 let penultimate_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0xf_0000);
1841 assert_eq!(
1842 penultimate_range,
1843 Some(CodePointMapRange {
1844 range: 0xf_0000..=0xf_ffff,
1845 value: 15
1846 })
1847 );
1848
1849 let last_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x10_0000);
1850 assert_eq!(
1851 last_range,
1852 Some(CodePointMapRange {
1853 range: 0x10_0000..=0x10_ffff,
1854 value: 16
1855 })
1856 );
1857 }
1858
1859 #[test]
1860 fn databake() {
1861 databake::test_bake!(
1862 CodePointTrie<'static, u32>,
1863 const,
1864 unsafe {
1865 #[allow(unused_unsafe)]
1866 crate::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(
1867 crate::codepointtrie::CodePointTrieHeader {
1868 high_start: 1u32,
1869 shifted12_high_start: 2u16,
1870 index3_null_offset: 3u16,
1871 data_null_offset: 4u32,
1872 null_value: 5u32,
1873 trie_type: crate::codepointtrie::TrieType::Small,
1874 },
1875 zerovec::ZeroVec::new(),
1876 zerovec::ZeroVec::new(),
1877 0u32,
1878 )
1879 },
1880 icu_collections,
1881 [zerovec],
1882 );
1883 }
1884}