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::ule::AsULE;
21#[cfg(feature = "alloc")]
22use zerovec::ule::UleError;
23use zerovec::ZeroSlice;
24use zerovec::ZeroVec;
25
26#[derive(#[automatically_derived]
impl ::core::clone::Clone for TrieType {
#[inline]
fn clone(&self) -> TrieType { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TrieType { }Copy, #[automatically_derived]
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]
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]
impl ::core::cmp::Eq for TrieType {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_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))]
46pub enum TrieType {
47 Fast = 0,
50 Small = 1,
53}
54
55pub trait TrieValue: Copy + Eq + PartialEq + zerovec::ule::AsULE + 'static {
64 type TryFromU32Error: Display;
70 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error>;
74
75 fn to_u32(self) -> u32;
82}
83
84macro_rules! impl_primitive_trie_value {
85 ($primitive:ty, $error:ty) => {
86 impl TrieValue for $primitive {
87 type TryFromU32Error = $error;
88 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
89 Self::try_from(i)
90 }
91
92 fn to_u32(self) -> u32 {
93 self as u32
96 }
97 }
98 };
99}
100
101impl TrieValue for u8 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u8, TryFromIntError);
102impl TrieValue for u16 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u16, TryFromIntError);
103impl TrieValue for u32 {
type TryFromU32Error = Infallible;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(u32, Infallible);
104impl TrieValue for i8 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i8, TryFromIntError);
105impl TrieValue for i16 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i16, TryFromIntError);
106impl TrieValue for i32 {
type TryFromU32Error = TryFromIntError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(i32, TryFromIntError);
107impl TrieValue for char {
type TryFromU32Error = CharTryFromError;
fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
Self::try_from(i)
}
fn to_u32(self) -> u32 { self as u32 }
}impl_primitive_trie_value!(char, CharTryFromError);
108
109fn maybe_filter_value<T: TrieValue>(value: T, trie_null_value: T, null_value: T) -> T {
118 if value == trie_null_value {
119 null_value
120 } else {
121 value
122 }
123}
124
125#[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_receiver_is_total_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<'a, T: TrieValue> yoke::Yokeable<'a> for CodePointTrie<'static, T>
where T: 'static {
type Output = CodePointTrie<'a, T>;
#[inline]
fn transform(&'a self) -> &'a Self::Output { self }
#[inline]
fn transform_owned(self) -> Self::Output { self }
#[inline]
unsafe fn make(this: Self::Output) -> Self {
use core::{mem, ptr};
if true {
if !(mem::size_of::<Self::Output>() == mem::size_of::<Self>()) {
::core::panicking::panic("assertion failed: mem::size_of::<Self::Output>() == mem::size_of::<Self>()")
};
};
let ptr: *const Self = (&this as *const Self::Output).cast();
#[allow(forgetting_copy_types, clippy :: forget_copy, clippy ::
forget_non_drop, clippy :: mem_forget)]
mem::forget(this);
ptr::read(ptr)
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F) where F: 'static +
for<'b> FnOnce(&'b mut Self::Output) {
unsafe {
f(core::mem::transmute::<&'a mut Self,
&'a mut Self::Output>(self))
}
}
}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)]
133pub struct CodePointTrie<'trie, T: TrieValue> {
134 pub(crate) header: CodePointTrieHeader,
138 pub(crate) index: ZeroVec<'trie, u16>,
147 pub(crate) data: ZeroVec<'trie, T>,
157 #[zerofrom(clone)] pub(crate) error_value: T,
161}
162
163#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
172#[cfg_attr(feature = "databake", derive(databake::Bake))]
173#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
174#[derive(#[automatically_derived]
impl ::core::marker::Copy for CodePointTrieHeader { }Copy, #[automatically_derived]
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]
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]
impl ::core::cmp::Eq for CodePointTrieHeader {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<u16>;
let _: ::core::cmp::AssertParamIsEq<TrieType>;
}
}Eq, #[automatically_derived]
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<'a> yoke::Yokeable<'a> 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>(&'a mut self, f: F) where F: 'static +
for<'b> FnOnce(&'b mut Self::Output) {
f(self)
}
}Yokeable, impl<'zf> zerofrom::ZeroFrom<'zf, CodePointTrieHeader<>> for
CodePointTrieHeader<> where {
fn zero_from(this: &'zf Self) -> Self { *this }
}ZeroFrom)]
175pub struct CodePointTrieHeader {
176 pub high_start: u32,
188 pub shifted12_high_start: u16,
192 pub index3_null_offset: u16,
196 pub data_null_offset: u32,
200 pub null_value: u32,
203 pub trie_type: TrieType,
210}
211
212impl TryFrom<u8> for TrieType {
213 type Error = crate::codepointtrie::error::Error;
214
215 fn try_from(trie_type_int: u8) -> Result<TrieType, crate::codepointtrie::error::Error> {
216 match trie_type_int {
217 0 => Ok(TrieType::Fast),
218 1 => Ok(TrieType::Small),
219 _ => Err(crate::codepointtrie::error::Error::FromDeserialized {
220 reason: "Cannot parse value for trie_type",
221 }),
222 }
223 }
224}
225
226macro_rules! w(
234 ($a:tt + $b:expr) => {
237 {
238 #[allow(unused_parens)]
239 let a = $a;
240 let b = $b;
241 debug_assert!(a.checked_add(b).is_some());
242 $a.wrapping_add($b)
243 }
244 };
245 ($a:tt - $b:expr) => {
246
247 {
248 #[allow(unused_parens)]
249 let a = $a;
250 let b = $b;
251 debug_assert!(a.checked_sub(b).is_some());
252 $a.wrapping_sub($b)
253 }
254 };
255 ($a:tt * $b:expr) => {
256 {
257 #[allow(unused_parens)]
258 let a = $a;
259 let b = $b;
260 debug_assert!(a.checked_mul(b).is_some());
261 $a.wrapping_mul($b)
262 }
263 };
264);
265
266impl<'trie, T: TrieValue> CodePointTrie<'trie, T> {
267 #[doc(hidden)] pub const unsafe fn from_parts_unstable_unchecked_v1(
274 header: CodePointTrieHeader,
275 index: ZeroVec<'trie, u16>,
276 data: ZeroVec<'trie, T>,
277 error_value: T,
278 ) -> Self {
279 Self {
284 header,
285 index,
286 data,
287 error_value,
288 }
289 }
290
291 pub fn try_new(
294 header: CodePointTrieHeader,
295 index: ZeroVec<'trie, u16>,
296 data: ZeroVec<'trie, T>,
297 ) -> Result<CodePointTrie<'trie, T>, Error> {
298 let error_value = Self::validate_fields(&header, &index, &data)?;
299 let trie: CodePointTrie<'trie, T> = CodePointTrie {
301 header,
302 index,
303 data,
304 error_value,
305 };
306 Ok(trie)
307 }
308
309 pub(crate) fn validate_fields(
319 header: &CodePointTrieHeader,
320 index: &ZeroSlice<u16>,
321 data: &ZeroSlice<T>,
322 ) -> Result<T, Error> {
323 let error_value = data.last().ok_or(Error::EmptyDataVector)?;
324
325 let fast_max = match header.trie_type {
354 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
355 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
356 };
357 let max_bit_prefix = fast_max >> FAST_TYPE_SHIFT;
359 let fast_index = index
364 .get_subslice(0..(max_bit_prefix as usize) + 1)
365 .ok_or(Error::IndexTooShortForFastAccess)?;
366 let max_offset = fast_index
375 .iter()
376 .max()
377 .ok_or(Error::IndexTooShortForFastAccess)?;
378 if (max_offset) as usize + (FAST_TYPE_DATA_MASK as usize) >= data.len() {
382 return Err(Error::DataTooShortForFastAccess);
383 }
384
385 Ok(error_value)
391 }
392
393 #[inline]
395 pub fn to_typed(self) -> Typed<FastCodePointTrie<'trie, T>, SmallCodePointTrie<'trie, T>> {
396 match self.header.trie_type {
397 TrieType::Fast => Typed::Fast(FastCodePointTrie { inner: self }),
398 TrieType::Small => Typed::Small(SmallCodePointTrie { inner: self }),
399 }
400 }
401
402 #[inline]
404 pub fn as_typed_ref(
405 &self,
406 ) -> Typed<&FastCodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>> {
407 match self.header.trie_type {
411 TrieType::Fast => Typed::Fast(unsafe {
412 core::mem::transmute::<&CodePointTrie<'trie, T>, &FastCodePointTrie<'trie, T>>(self)
413 }),
414 TrieType::Small => Typed::Small(unsafe {
415 core::mem::transmute::<&CodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>>(
416 self,
417 )
418 }),
419 }
420 }
421
422 #[inline(always)] fn trie_error_val_index(&self) -> u32 {
426 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);
430 {
#[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)
431 }
432
433 fn internal_small_index(&self, code_point: u32) -> u32 {
434 let mut index1_pos: u32 = code_point >> SHIFT_1;
438 if self.header.trie_type == TrieType::Fast {
439 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!(
440 FAST_TYPE_FAST_INDEXING_MAX < code_point && code_point < self.header.high_start
441 );
442 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);
443 } else {
444 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);
445 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);
446 }
447 let index1_val = if let Some(index1_val) = self.index.get(index1_pos as usize) {
448 index1_val
449 } else {
450 return self.trie_error_val_index();
451 };
452 let index3_block_idx: u32 =
453 {
#[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);
454 let mut index3_block: u32 =
455 if let Some(index3_block) = self.index.get(index3_block_idx as usize) {
456 index3_block as u32
457 } else {
458 return self.trie_error_val_index();
459 };
460 let mut index3_pos: u32 = (code_point >> SHIFT_3) & INDEX_3_MASK;
461 let mut data_block: u32;
462 if index3_block & 0x8000 == 0 {
463 data_block =
465 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) {
466 data_block as u32
467 } else {
468 return self.trie_error_val_index();
469 };
470 } else {
471 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));
473 index3_pos &= 7;
474 data_block = if let Some(data_block) = self.index.get(index3_block as usize) {
475 data_block as u32
476 } else {
477 return self.trie_error_val_index();
478 };
479 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;
480 index3_block += 1;
481 data_block =
482 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) {
483 data_block | (index3_val as u32)
484 } else {
485 return self.trie_error_val_index();
486 };
487 }
488 {
#[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)
491 }
492
493 fn small_index(&self, code_point: u32) -> u32 {
504 if code_point >= self.header.high_start {
505 {
#[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)
506 } else {
507 self.internal_small_index(code_point) }
509 }
510
511 fn fast_index(&self, code_point: u32) -> u32 {
523 let index_array_pos: u32 = code_point >> FAST_TYPE_SHIFT;
524 let index_array_val: u16 =
525 if let Some(index_array_val) = self.index.get(index_array_pos as usize) {
526 index_array_val
527 } else {
528 return self.trie_error_val_index();
529 };
530 let masked_cp = code_point & FAST_TYPE_DATA_MASK;
531 let index_array_val = index_array_val as u32;
532 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);
533 fast_index_val
534 }
535
536 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
541 let fast_max = match self.header.trie_type {
542 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
543 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
544 };
545 if code_point <= fast_max {
546 Some(unsafe { self.get32_assuming_fast_index(code_point) })
553 } else {
554 None
557 }
558 }
559
560 #[inline(always)]
568 unsafe fn get32_assuming_fast_index(&self, code_point: u32) -> T {
569 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!(
571 code_point
572 <= match self.header.trie_type {
573 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
574 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
575 }
576 );
577
578 let bit_prefix = (code_point as usize) >> FAST_TYPE_SHIFT;
579 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());
580 let base_offset_to_data: usize = usize::from(u16::from_unaligned(*unsafe {
584 self.index.as_ule_slice().get_unchecked(bit_prefix)
585 }));
586 let bit_suffix = (code_point & FAST_TYPE_DATA_MASK) as usize;
587 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);
593 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());
594 T::from_unaligned(*unsafe { self.data.as_ule_slice().get_unchecked(offset_to_data) })
598 }
599
600 #[cold]
603 #[inline(always)]
604 fn get32_by_small_index_cold(&self, code_point: u32) -> T {
605 self.get32_by_small_index(code_point)
606 }
607
608 #[inline(never)]
621 fn get32_by_small_index(&self, code_point: u32) -> T {
622 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);
623 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!(
624 code_point
625 > match self.header.trie_type {
626 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
627 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
628 }
629 );
630 self.data
631 .get(self.small_index(code_point) as usize)
632 .unwrap_or(self.error_value)
633 }
634
635 #[inline(always)] pub fn get32(&self, code_point: u32) -> T {
649 if let Some(v) = self.get32_by_fast_index(code_point) {
650 v
651 } else if code_point <= CODE_POINT_MAX {
652 self.get32_by_small_index_cold(code_point)
653 } else {
654 self.error_value
655 }
656 }
657
658 #[inline(always)]
671 pub fn get(&self, c: char) -> T {
672 let code_point = u32::from(c);
676 if let Some(v) = self.get32_by_fast_index(code_point) {
677 v
678 } else {
679 self.get32_by_small_index_cold(code_point)
680 }
681 }
682
683 #[inline(always)]
685 pub fn get16(&self, bmp: u16) -> T {
686 let code_point = u32::from(bmp);
690 if let Some(v) = self.get32_by_fast_index(code_point) {
691 v
692 } else {
693 self.get32_by_small_index_cold(code_point)
694 }
695 }
696
697 #[inline(always)]
703 pub fn get32_supplementary(&self, supplementary: u32) -> T {
704 if true {
if !(supplementary > 0xFFFF) {
::core::panicking::panic("assertion failed: supplementary > 0xFFFF")
};
};debug_assert!(supplementary > 0xFFFF);
705 if true {
if !(supplementary <= CODE_POINT_MAX) {
::core::panicking::panic("assertion failed: supplementary <= CODE_POINT_MAX")
};
};debug_assert!(supplementary <= CODE_POINT_MAX);
706 self.get32_by_small_index(supplementary)
707 }
708
709 #[inline(always)] pub fn get32_ule(&self, code_point: u32) -> Option<&T::ULE> {
723 let fast_max = match self.header.trie_type {
728 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
729 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
730 };
731 let data_pos: u32 = if code_point <= fast_max {
732 Self::fast_index(self, code_point)
733 } else if code_point <= CODE_POINT_MAX {
734 Self::small_index(self, code_point)
735 } else {
736 self.trie_error_val_index()
737 };
738 self.data.as_ule_slice().get(data_pos as usize)
740 }
741
742 #[cfg(feature = "alloc")]
771 pub fn try_into_converted<P>(self) -> Result<CodePointTrie<'trie, P>, UleError>
772 where
773 P: TrieValue,
774 {
775 let converted_data = self.data.try_into_converted()?;
776 let error_ule = self.error_value.to_unaligned();
777 let slice = &[error_ule];
778 let error_vec = ZeroVec::<T>::new_borrowed(slice);
779 let error_converted = error_vec.try_into_converted::<P>()?;
780 #[expect(clippy::expect_used)] Ok(CodePointTrie {
782 header: self.header,
783 index: self.index,
784 data: converted_data,
785 error_value: error_converted
786 .get(0)
787 .expect("vector known to have one element"),
788 })
789 }
790
791 #[cfg(feature = "alloc")]
814 pub fn try_alloc_map_value<P, E>(
815 &self,
816 mut f: impl FnMut(T) -> Result<P, E>,
817 ) -> Result<CodePointTrie<'trie, P>, E>
818 where
819 P: TrieValue,
820 {
821 let error_converted = f(self.error_value)?;
822 let converted_data = self.data.iter().map(f).collect::<Result<ZeroVec<P>, E>>()?;
823 Ok(CodePointTrie {
824 header: self.header,
825 index: self.index.clone(),
826 data: converted_data,
827 error_value: error_converted,
828 })
829 }
830
831 pub fn get_range(&self, start: u32) -> Option<CodePointMapRange<T>> {
885 if CODE_POINT_MAX < start {
889 return None;
890 }
891 if start >= self.header.high_start {
892 let di: usize = self.data.len() - (HIGH_VALUE_NEG_DATA_OFFSET as usize);
893 let value: T = self.data.get(di)?;
894 return Some(CodePointMapRange {
895 range: start..=CODE_POINT_MAX,
896 value,
897 });
898 }
899
900 let null_value: T = T::try_from_u32(self.header.null_value).ok()?;
901
902 let mut prev_i3_block: u32 = u32::MAX; let mut prev_block: u32 = u32::MAX; let mut c: u32 = start;
905 let mut trie_value: T = self.error_value();
906 let mut value: T = self.error_value();
907 let mut have_value: bool = false;
908
909 loop {
910 let i3_block: u32;
911 let mut i3: u32;
912 let i3_block_length: u32;
913 let data_block_length: u32;
914
915 if c <= 0xffff
928 && (self.header.trie_type == TrieType::Fast || c <= SMALL_TYPE_FAST_INDEXING_MAX)
929 {
930 i3_block = 0;
931 i3 = c >> FAST_TYPE_SHIFT;
932 i3_block_length = if self.header.trie_type == TrieType::Fast {
933 BMP_INDEX_LENGTH
934 } else {
935 SMALL_INDEX_LENGTH
936 };
937 data_block_length = FAST_TYPE_DATA_BLOCK_LENGTH;
938 } else {
939 let mut i1: u32 = c >> SHIFT_1;
941 if self.header.trie_type == TrieType::Fast {
942 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);
943 i1 = i1 + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH;
944 } else {
945 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!(
946 c < self.header.high_start && self.header.high_start > SMALL_LIMIT
947 );
948 i1 += SMALL_INDEX_LENGTH;
949 }
950 let i2: u16 = self.index.get(i1 as usize)?;
951 let i3_block_idx: u32 = (i2 as u32) + ((c >> SHIFT_2) & INDEX_2_MASK);
952 i3_block = if let Some(i3b) = self.index.get(i3_block_idx as usize) {
953 i3b as u32
954 } else {
955 return None;
956 };
957 if i3_block == prev_i3_block && (c - start) >= CP_PER_INDEX_2_ENTRY {
958 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);
960 c += CP_PER_INDEX_2_ENTRY;
961
962 if c >= self.header.high_start {
963 break;
964 } else {
965 continue;
966 }
967 }
968 prev_i3_block = i3_block;
969 if i3_block == self.header.index3_null_offset as u32 {
970 if have_value {
977 if null_value != value {
978 return Some(CodePointMapRange {
979 range: start..=(c - 1),
980 value,
981 });
982 }
983 } else {
984 trie_value = T::try_from_u32(self.header.null_value).ok()?;
985 value = null_value;
986 have_value = true;
987 }
988 prev_block = self.header.data_null_offset;
989 c = (c + CP_PER_INDEX_2_ENTRY) & !(CP_PER_INDEX_2_ENTRY - 1);
990
991 if c >= self.header.high_start {
992 break;
993 } else {
994 continue;
995 }
996 }
997 i3 = (c >> SHIFT_3) & INDEX_3_MASK;
998 i3_block_length = INDEX_3_BLOCK_LENGTH;
999 data_block_length = SMALL_DATA_BLOCK_LENGTH;
1000 }
1001
1002 loop {
1004 let mut block: u32;
1005 if (i3_block & 0x8000) == 0 {
1006 block = if let Some(b) = self.index.get((i3_block + i3) as usize) {
1007 b as u32
1008 } else {
1009 return None;
1010 };
1011 } else {
1012 let mut group: u32 = (i3_block & 0x7fff) + (i3 & !7) + (i3 >> 3);
1014 let gi: u32 = i3 & 7;
1015 let gi_val: u32 = if let Some(giv) = self.index.get(group as usize) {
1016 giv.into()
1017 } else {
1018 return None;
1019 };
1020 block = (gi_val << (2 + (2 * gi))) & 0x30000;
1021 group += 1;
1022 let ggi_val: u32 = if let Some(ggiv) = self.index.get((group + gi) as usize) {
1023 ggiv as u32
1024 } else {
1025 return None;
1026 };
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 null_value != value {
1051 return Some(CodePointMapRange {
1052 range: start..=(c - 1),
1053 value,
1054 });
1055 }
1056 } else {
1057 trie_value = T::try_from_u32(self.header.null_value).ok()?;
1058 value = 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 T::try_from_u32(self.header.null_value).ok()?,
1070 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 = maybe_filter_value(
1100 trie_value_2,
1101 T::try_from_u32(self.header.null_value).ok()?,
1102 null_value,
1103 );
1104 have_value = true;
1105 }
1106
1107 c += 1;
1108 while (c & data_mask) != 0 {
1109 di += 1;
1110 trie_value_2 = self.data.get(di as usize)?;
1111 if trie_value_2 != trie_value {
1112 if maybe_filter_value(
1113 trie_value_2,
1114 T::try_from_u32(self.header.null_value).ok()?,
1115 null_value,
1116 ) != value
1117 {
1118 return Some(CodePointMapRange {
1119 range: start..=(c - 1),
1120 value,
1121 });
1122 }
1123 trie_value = trie_value_2; }
1142
1143 c += 1;
1144 }
1145 }
1146 }
1147
1148 i3 += 1;
1149 if i3 >= i3_block_length {
1150 break;
1151 }
1152 }
1153
1154 if c >= self.header.high_start {
1155 break;
1156 }
1157 }
1158
1159 if true {
if !have_value {
::core::panicking::panic("assertion failed: have_value")
};
};debug_assert!(have_value);
1160
1161 let di: u32 = self.data.len() as u32 - HIGH_VALUE_NEG_DATA_OFFSET;
1166 let high_value: T = self.data.get(di as usize)?;
1167 if maybe_filter_value(
1168 high_value,
1169 T::try_from_u32(self.header.null_value).ok()?,
1170 null_value,
1171 ) != value
1172 {
1173 c -= 1;
1174 } else {
1175 c = CODE_POINT_MAX;
1176 }
1177 Some(CodePointMapRange {
1178 range: start..=c,
1179 value,
1180 })
1181 }
1182
1183 pub fn iter_ranges(&self) -> CodePointMapRangeIterator<'_, T> {
1216 let init_range = Some(CodePointMapRange {
1217 range: u32::MAX..=u32::MAX,
1218 value: self.error_value(),
1219 });
1220 CodePointMapRangeIterator::<T> {
1221 cpt: self,
1222 cpm_range: init_range,
1223 }
1224 }
1225
1226 pub fn iter_ranges_for_value(
1248 &self,
1249 value: T,
1250 ) -> impl Iterator<Item = RangeInclusive<u32>> + '_ {
1251 self.iter_ranges()
1252 .filter(move |cpm_range| cpm_range.value == value)
1253 .map(|cpm_range| cpm_range.range)
1254 }
1255
1256 pub fn iter_ranges_mapped<'a, U: Eq + 'a>(
1278 &'a self,
1279 mut map: impl FnMut(T) -> U + Copy + 'a,
1280 ) -> impl Iterator<Item = CodePointMapRange<U>> + 'a {
1281 crate::iterator_utils::RangeListIteratorCoalescer::new(self.iter_ranges().map(
1282 move |range| CodePointMapRange {
1283 range: range.range,
1284 value: map(range.value),
1285 },
1286 ))
1287 }
1288
1289 #[cfg(feature = "alloc")]
1313 pub fn get_set_for_value(&self, value: T) -> CodePointInversionList<'static> {
1314 let value_ranges = self.iter_ranges_for_value(value);
1315 CodePointInversionList::from_iter(value_ranges)
1316 }
1317
1318 #[inline]
1320 pub fn error_value(&self) -> T {
1321 self.error_value
1322 }
1323}
1324
1325#[cfg(feature = "databake")]
1326impl<T: TrieValue + databake::Bake> databake::Bake for CodePointTrie<'_, T> {
1327 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
1328 let header = self.header.bake(env);
1329 let index = self.index.bake(env);
1330 let data = self.data.bake(env);
1331 let error_value = self.error_value.bake(env);
1332 databake::quote! { unsafe { icu_collections::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(#header, #index, #data, #error_value) } }
1333 }
1334}
1335
1336#[cfg(feature = "databake")]
1337impl<T: TrieValue + databake::Bake> databake::BakeSize for CodePointTrie<'_, T> {
1338 fn borrows_size(&self) -> usize {
1339 self.header.borrows_size() + self.index.borrows_size() + self.data.borrows_size()
1340 }
1341}
1342
1343impl<T: TrieValue + Into<u32>> CodePointTrie<'_, T> {
1344 pub fn get32_u32(&self, code_point: u32) -> u32 {
1362 self.get32(code_point).into()
1363 }
1364}
1365
1366impl<T: TrieValue> Clone for CodePointTrie<'_, T>
1367where
1368 <T as zerovec::ule::AsULE>::ULE: Clone,
1369{
1370 fn clone(&self) -> Self {
1371 CodePointTrie {
1372 header: self.header,
1373 index: self.index.clone(),
1374 data: self.data.clone(),
1375 error_value: self.error_value,
1376 }
1377 }
1378}
1379
1380#[derive(#[automatically_derived]
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]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for CodePointMapRange<T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<RangeInclusive<u32>>;
let _: ::core::cmp::AssertParamIsEq<T>;
}
}Eq, #[automatically_derived]
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]
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)]
1386pub struct CodePointMapRange<T> {
1387 pub range: RangeInclusive<u32>,
1389 pub value: T,
1391}
1392
1393pub struct CodePointMapRangeIterator<'a, T: TrieValue> {
1396 cpt: &'a CodePointTrie<'a, T>,
1397 cpm_range: Option<CodePointMapRange<T>>,
1404}
1405
1406impl<T: TrieValue> Iterator for CodePointMapRangeIterator<'_, T> {
1407 type Item = CodePointMapRange<T>;
1408
1409 fn next(&mut self) -> Option<Self::Item> {
1410 self.cpm_range = match &self.cpm_range {
1411 Some(cpmr) => {
1412 if *cpmr.range.start() == u32::MAX {
1413 self.cpt.get_range(0)
1414 } else {
1415 self.cpt.get_range(cpmr.range.end() + 1)
1416 }
1417 }
1418 None => None,
1419 };
1420 self.cpm_range.clone()
1422 }
1423}
1424
1425trait Seal {}
1431
1432#[allow(private_bounds)] pub trait TypedCodePointTrie<'trie, T: TrieValue>: Seal {
1436 const TRIE_TYPE: TrieType;
1442
1443 #[inline(always)]
1445 fn get32_u32(&self, code_point: u32) -> u32 {
1446 self.get32(code_point).to_u32()
1447 }
1448
1449 #[inline(always)]
1451 fn get16(&self, bmp: u16) -> T {
1452 let code_point = u32::from(bmp);
1456 if let Some(v) = self.get32_by_fast_index(code_point) {
1457 v
1458 } else {
1459 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1460 }
1461 }
1462
1463 #[inline(always)]
1465 fn get32_supplementary(&self, supplementary: u32) -> T {
1466 self.as_untyped_ref().get32_supplementary(supplementary)
1467 }
1468
1469 #[inline(always)]
1471 fn get(&self, c: char) -> T {
1472 let code_point = u32::from(c);
1476 if let Some(v) = self.get32_by_fast_index(code_point) {
1477 v
1478 } else {
1479 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1480 }
1481 }
1482
1483 #[inline(always)]
1485 fn get32(&self, code_point: u32) -> T {
1486 if let Some(v) = self.get32_by_fast_index(code_point) {
1487 v
1488 } else if code_point <= CODE_POINT_MAX {
1489 self.as_untyped_ref().get32_by_small_index_cold(code_point)
1490 } else {
1491 self.as_untyped_ref().error_value
1492 }
1493 }
1494
1495 #[inline(always)] fn get32_by_fast_index(&self, code_point: u32) -> Option<T> {
1500 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);
1501 let fast_max = match Self::TRIE_TYPE {
1502 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
1503 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
1504 };
1505 if code_point <= fast_max {
1506 Some(unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) })
1517 } else {
1518 None
1521 }
1522 }
1523
1524 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T>;
1526
1527 fn to_untyped(self) -> CodePointTrie<'trie, T>;
1529}
1530
1531#[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)]
1536#[repr(transparent)]
1537pub struct FastCodePointTrie<'trie, T: TrieValue> {
1538 inner: CodePointTrie<'trie, T>,
1539}
1540
1541impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for FastCodePointTrie<'trie, T> {
1542 const TRIE_TYPE: TrieType = TrieType::Fast;
1543
1544 #[inline(always)]
1546 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1547 &self.inner
1548 }
1549
1550 #[inline(always)]
1552 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1553 self.inner
1554 }
1555
1556 #[inline(always)]
1558 fn get16(&self, bmp: u16) -> T {
1559 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);
1560 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);
1561 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);
1562 let code_point = u32::from(bmp);
1563 unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) }
1572 }
1573}
1574
1575impl<'trie, T: TrieValue> Seal for FastCodePointTrie<'trie, T> {}
1576
1577impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1578 for &'trie FastCodePointTrie<'trie, T>
1579{
1580 type Error = TypedCodePointTrieError;
1581
1582 fn try_from(
1583 reference: &'trie CodePointTrie<'trie, T>,
1584 ) -> Result<&'trie FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1585 match reference.as_typed_ref() {
1586 Typed::Fast(trie) => Ok(trie),
1587 Typed::Small(_) => Err(TypedCodePointTrieError),
1588 }
1589 }
1590}
1591
1592impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for FastCodePointTrie<'trie, T> {
1593 type Error = TypedCodePointTrieError;
1594
1595 fn try_from(
1596 value: CodePointTrie<'trie, T>,
1597 ) -> Result<FastCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1598 match value.to_typed() {
1599 Typed::Fast(trie) => Ok(trie),
1600 Typed::Small(_) => Err(TypedCodePointTrieError),
1601 }
1602 }
1603}
1604
1605#[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)]
1608#[repr(transparent)]
1609pub struct SmallCodePointTrie<'trie, T: TrieValue> {
1610 inner: CodePointTrie<'trie, T>,
1611}
1612
1613impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for SmallCodePointTrie<'trie, T> {
1614 const TRIE_TYPE: TrieType = TrieType::Small;
1615
1616 #[inline(always)]
1618 fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> {
1619 &self.inner
1620 }
1621
1622 #[inline(always)]
1624 fn to_untyped(self) -> CodePointTrie<'trie, T> {
1625 self.inner
1626 }
1627}
1628
1629impl<'trie, T: TrieValue> Seal for SmallCodePointTrie<'trie, T> {}
1630
1631impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>>
1632 for &'trie SmallCodePointTrie<'trie, T>
1633{
1634 type Error = TypedCodePointTrieError;
1635
1636 fn try_from(
1637 reference: &'trie CodePointTrie<'trie, T>,
1638 ) -> Result<&'trie SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1639 match reference.as_typed_ref() {
1640 Typed::Fast(_) => Err(TypedCodePointTrieError),
1641 Typed::Small(trie) => Ok(trie),
1642 }
1643 }
1644}
1645
1646impl<'trie, T: TrieValue> TryFrom<CodePointTrie<'trie, T>> for SmallCodePointTrie<'trie, T> {
1647 type Error = TypedCodePointTrieError;
1648
1649 fn try_from(
1650 value: CodePointTrie<'trie, T>,
1651 ) -> Result<SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> {
1652 match value.to_typed() {
1653 Typed::Fast(_) => Err(TypedCodePointTrieError),
1654 Typed::Small(trie) => Ok(trie),
1655 }
1656 }
1657}
1658
1659#[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)]
1662#[non_exhaustive]
1663pub struct TypedCodePointTrieError;
1664
1665pub enum Typed<F, S> {
1668 Fast(F),
1670 Small(S),
1672}
1673
1674#[cfg(test)]
1675mod tests {
1676 use super::*;
1677 use crate::codepointtrie::planes;
1678 use alloc::vec::Vec;
1679
1680 #[test]
1681 #[cfg(feature = "serde")]
1682 fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> {
1683 let trie = crate::codepointtrie::planes::get_planes_trie();
1684 let trie_serialized: Vec<u8> = postcard::to_allocvec(&trie).unwrap();
1685
1686 const EXP_TRIE_SERIALIZED: &[u8] = &[
1688 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,
1689 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,
1690 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,
1691 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,
1692 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,
1693 2, 144, 2, 144, 2, 144, 2, 176, 2, 176, 2, 176, 2, 176, 2, 208, 2, 208, 2, 208, 2, 208,
1694 2, 240, 2, 240, 2, 240, 2, 240, 2, 16, 3, 16, 3, 16, 3, 16, 3, 48, 3, 48, 3, 48, 3, 48,
1695 3, 80, 3, 80, 3, 80, 3, 80, 3, 112, 3, 112, 3, 112, 3, 112, 3, 144, 3, 144, 3, 144, 3,
1696 144, 3, 176, 3, 176, 3, 176, 3, 176, 3, 208, 3, 208, 3, 208, 3, 208, 3, 240, 3, 240, 3,
1697 240, 3, 240, 3, 16, 4, 16, 4, 16, 4, 16, 4, 48, 4, 48, 4, 48, 4, 48, 4, 80, 4, 80, 4,
1698 80, 4, 80, 4, 112, 4, 112, 4, 112, 4, 112, 4, 0, 0, 16, 0, 32, 0, 48, 0, 64, 0, 80, 0,
1699 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,
1700 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,
1701 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 128, 0, 128, 0, 128, 0, 128,
1702 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1703 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1704 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1705 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1706 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1707 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1708 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1709 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1710 0, 160, 0, 160, 0, 160, 0, 160, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1711 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1712 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1713 0, 176, 0, 176, 0, 176, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1714 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1715 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1716 0, 192, 0, 192, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1717 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1718 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1719 0, 208, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1720 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1721 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1722 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1723 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1724 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 0,
1725 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,
1726 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,
1727 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,
1728 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,
1729 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,
1730 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,
1731 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,
1732 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,
1733 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,
1734 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,
1735 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,
1736 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,
1737 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,
1738 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,
1739 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,
1740 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,
1741 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,
1742 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 128, 0, 136, 0, 136, 0, 136, 0, 136,
1743 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,
1744 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,
1745 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,
1746 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1747 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1748 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1749 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1750 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1751 200, 0, 200, 0, 200, 0, 200, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1752 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1753 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1754 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,
1755 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,
1756 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,
1757 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,
1758 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,
1759 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,
1760 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,
1761 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1762 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1763 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1764 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1765 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1766 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1767 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1768 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1769 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1770 168, 1, 168, 1, 168, 1, 168, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1771 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1772 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1773 200, 1, 200, 1, 200, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1774 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1775 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1776 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,
1777 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,
1778 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,
1779 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,
1780 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,
1781 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,
1782 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,
1783 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1784 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1785 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1786 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,
1787 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,
1788 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,
1789 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,
1790 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,
1791 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,
1792 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,
1793 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,
1794 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,
1795 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,
1796 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
1797 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
1798 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
1799 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1800 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 0,
1801 ];
1802 assert_eq!(trie_serialized, EXP_TRIE_SERIALIZED);
1803
1804 let trie_deserialized = postcard::from_bytes::<CodePointTrie<u8>>(&trie_serialized)?;
1805
1806 assert_eq!(&trie.index, &trie_deserialized.index);
1807 assert_eq!(&trie.data, &trie_deserialized.data);
1808
1809 assert!(!trie_deserialized.index.is_owned());
1810 assert!(!trie_deserialized.data.is_owned());
1811
1812 Ok(())
1813 }
1814
1815 #[test]
1816 fn test_typed() {
1817 let untyped = planes::get_planes_trie();
1818 assert_eq!(untyped.get('\u{10000}'), 1);
1819 let small_ref = <&SmallCodePointTrie<_>>::try_from(&untyped).unwrap();
1820 assert_eq!(small_ref.get('\u{10000}'), 1);
1821 let _ = <&FastCodePointTrie<_>>::try_from(&untyped).is_err();
1822 let small = <SmallCodePointTrie<_>>::try_from(untyped).unwrap();
1823 assert_eq!(small.get('\u{10000}'), 1);
1824 }
1825
1826 #[test]
1827 fn test_get_range() {
1828 let planes_trie = planes::get_planes_trie();
1829
1830 let first_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x0);
1831 assert_eq!(
1832 first_range,
1833 Some(CodePointMapRange {
1834 range: 0x0..=0xffff,
1835 value: 0
1836 })
1837 );
1838
1839 let second_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x1_0000);
1840 assert_eq!(
1841 second_range,
1842 Some(CodePointMapRange {
1843 range: 0x10000..=0x1ffff,
1844 value: 1
1845 })
1846 );
1847
1848 let penultimate_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0xf_0000);
1849 assert_eq!(
1850 penultimate_range,
1851 Some(CodePointMapRange {
1852 range: 0xf_0000..=0xf_ffff,
1853 value: 15
1854 })
1855 );
1856
1857 let last_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x10_0000);
1858 assert_eq!(
1859 last_range,
1860 Some(CodePointMapRange {
1861 range: 0x10_0000..=0x10_ffff,
1862 value: 16
1863 })
1864 );
1865 }
1866
1867 #[test]
1868 #[allow(unused_unsafe)] fn databake() {
1870 databake::test_bake!(
1871 CodePointTrie<'static, u32>,
1872 const,
1873 unsafe {
1874 crate::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(
1875 crate::codepointtrie::CodePointTrieHeader {
1876 high_start: 1u32,
1877 shifted12_high_start: 2u16,
1878 index3_null_offset: 3u16,
1879 data_null_offset: 4u32,
1880 null_value: 5u32,
1881 trie_type: crate::codepointtrie::TrieType::Small,
1882 },
1883 zerovec::ZeroVec::new(),
1884 zerovec::ZeroVec::new(),
1885 0u32,
1886 )
1887 },
1888 icu_collections,
1889 [zerovec],
1890 );
1891 }
1892}