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;
20#[cfg(feature = "alloc")]
21use zerovec::ule::UleError;
22use zerovec::ZeroVec;
23
24)]
41#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
42#[cfg_attr(feature = "databake", derive(databake::Bake))]
43#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
44pub enum TrieType {
45 Fast = 0,
48 Small = 1,
51}
52
53pub trait TrieValue: Copy + Eq + PartialEq + zerovec::ule::AsULE + 'static {
62 type TryFromU32Error: Display;
68 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error>;
72
73 fn to_u32(self) -> u32;
80}
81
82macro_rules! impl_primitive_trie_value {
83 ($primitive:ty, $error:ty) => {
84 impl TrieValue for $primitive {
85 type TryFromU32Error = $error;
86 fn try_from_u32(i: u32) -> Result<Self, Self::TryFromU32Error> {
87 Self::try_from(i)
88 }
89
90 fn to_u32(self) -> u32 {
91 self as u32
94 }
95 }
96 };
97}
98
99impl 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);
100impl 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);
101impl 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);
102impl 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);
103impl 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);
104impl 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);
105impl 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);
106
107fn maybe_filter_value<T: TrieValue>(value: T, trie_null_value: T, null_value: T) -> T {
116 if value == trie_null_value {
117 null_value
118 } else {
119 value
120 }
121}
122
123)]
131pub struct CodePointTrie<'trie, T: TrieValue> {
132 pub(crate) header: CodePointTrieHeader,
133 pub(crate) index: ZeroVec<'trie, u16>,
134 pub(crate) data: ZeroVec<'trie, T>,
135 #[zerofrom(clone)] pub(crate) error_value: T,
139}
140
141#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
143#[cfg_attr(feature = "databake", derive(databake::Bake))]
144#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))]
145#[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)]
146pub struct CodePointTrieHeader {
147 pub high_start: u32,
159 pub shifted12_high_start: u16,
163 pub index3_null_offset: u16,
167 pub data_null_offset: u32,
171 pub null_value: u32,
174 pub trie_type: TrieType,
177}
178
179impl TryFrom<u8> for TrieType {
180 type Error = crate::codepointtrie::error::Error;
181
182 fn try_from(trie_type_int: u8) -> Result<TrieType, crate::codepointtrie::error::Error> {
183 match trie_type_int {
184 0 => Ok(TrieType::Fast),
185 1 => Ok(TrieType::Small),
186 _ => Err(crate::codepointtrie::error::Error::FromDeserialized {
187 reason: "Cannot parse value for trie_type",
188 }),
189 }
190 }
191}
192
193macro_rules! w(
201 ($a:tt + $b:expr) => {
204 {
205 #[allow(unused_parens)]
206 let a = $a;
207 let b = $b;
208 debug_assert!(a.checked_add(b).is_some());
209 $a.wrapping_add($b)
210 }
211 };
212 ($a:tt - $b:expr) => {
213
214 {
215 #[allow(unused_parens)]
216 let a = $a;
217 let b = $b;
218 debug_assert!(a.checked_sub(b).is_some());
219 $a.wrapping_sub($b)
220 }
221 };
222 ($a:tt * $b:expr) => {
223 {
224 #[allow(unused_parens)]
225 let a = $a;
226 let b = $b;
227 debug_assert!(a.checked_mul(b).is_some());
228 $a.wrapping_mul($b)
229 }
230 };
231);
232
233impl<'trie, T: TrieValue> CodePointTrie<'trie, T> {
234 #[doc(hidden)] pub const fn from_parts(
236 header: CodePointTrieHeader,
237 index: ZeroVec<'trie, u16>,
238 data: ZeroVec<'trie, T>,
239 error_value: T,
240 ) -> Self {
241 Self {
242 header,
243 index,
244 data,
245 error_value,
246 }
247 }
248
249 pub fn try_new(
252 header: CodePointTrieHeader,
253 index: ZeroVec<'trie, u16>,
254 data: ZeroVec<'trie, T>,
255 ) -> Result<CodePointTrie<'trie, T>, Error> {
256 let error_value = data.last().ok_or(Error::EmptyDataVector)?;
269 let trie: CodePointTrie<'trie, T> = CodePointTrie {
270 header,
271 index,
272 data,
273 error_value,
274 };
275 Ok(trie)
276 }
277
278 #[inline(always)] fn trie_error_val_index(&self) -> u32 {
282 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);
286 {
#[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)
287 }
288
289 fn internal_small_index(&self, code_point: u32) -> u32 {
290 let mut index1_pos: u32 = code_point >> SHIFT_1;
294 if self.header.trie_type == TrieType::Fast {
295 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!(
296 FAST_TYPE_FAST_INDEXING_MAX < code_point && code_point < self.header.high_start
297 );
298 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);
299 } else {
300 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);
301 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);
302 }
303 let index1_val = if let Some(index1_val) = self.index.get(index1_pos as usize) {
304 index1_val
305 } else {
306 return self.trie_error_val_index();
307 };
308 let index3_block_idx: u32 =
309 {
#[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);
310 let mut index3_block: u32 =
311 if let Some(index3_block) = self.index.get(index3_block_idx as usize) {
312 index3_block as u32
313 } else {
314 return self.trie_error_val_index();
315 };
316 let mut index3_pos: u32 = (code_point >> SHIFT_3) & INDEX_3_MASK;
317 let mut data_block: u32;
318 if index3_block & 0x8000 == 0 {
319 data_block =
321 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) {
322 data_block as u32
323 } else {
324 return self.trie_error_val_index();
325 };
326 } else {
327 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));
329 index3_pos &= 7;
330 data_block = if let Some(data_block) = self.index.get(index3_block as usize) {
331 data_block as u32
332 } else {
333 return self.trie_error_val_index();
334 };
335 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;
336 index3_block += 1;
337 data_block =
338 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) {
339 data_block | (index3_val as u32)
340 } else {
341 return self.trie_error_val_index();
342 };
343 }
344 {
#[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)
347 }
348
349 fn small_index(&self, code_point: u32) -> u32 {
360 if code_point >= self.header.high_start {
361 {
#[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)
362 } else {
363 self.internal_small_index(code_point) }
365 }
366
367 #[inline(always)] fn fast_index(&self, code_point: u32) -> u32 {
380 let index_array_pos: u32 = code_point >> FAST_TYPE_SHIFT;
381 let index_array_val: u16 =
382 if let Some(index_array_val) = self.index.get(index_array_pos as usize) {
383 index_array_val
384 } else {
385 return self.trie_error_val_index();
386 };
387 let masked_cp = code_point & FAST_TYPE_DATA_MASK;
388 let index_array_val = index_array_val as u32;
389 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);
390 fast_index_val
391 }
392
393 #[inline(always)] pub fn get32(&self, code_point: u32) -> T {
407 self.get32_ule(code_point)
410 .map(|t| T::from_unaligned(*t))
411 .unwrap_or(self.error_value)
412 }
413
414 #[inline(always)]
427 pub fn get(&self, c: char) -> T {
428 self.get32(u32::from(c))
429 }
430
431 #[inline(always)] pub fn get32_ule(&self, code_point: u32) -> Option<&T::ULE> {
445 let fast_max = match self.header.trie_type {
450 TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX,
451 TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX,
452 };
453 let data_pos: u32 = if code_point <= fast_max {
454 Self::fast_index(self, code_point)
455 } else if code_point <= CODE_POINT_MAX {
456 Self::small_index(self, code_point)
457 } else {
458 self.trie_error_val_index()
459 };
460 self.data.as_ule_slice().get(data_pos as usize)
462 }
463
464 #[cfg(feature = "alloc")]
491 pub fn try_into_converted<P>(self) -> Result<CodePointTrie<'trie, P>, UleError>
492 where
493 P: TrieValue,
494 {
495 let converted_data = self.data.try_into_converted()?;
496 let error_ule = self.error_value.to_unaligned();
497 let slice = &[error_ule];
498 let error_vec = ZeroVec::<T>::new_borrowed(slice);
499 let error_converted = error_vec.try_into_converted::<P>()?;
500 #[allow(clippy::expect_used)] Ok(CodePointTrie {
502 header: self.header,
503 index: self.index,
504 data: converted_data,
505 error_value: error_converted
506 .get(0)
507 .expect("vector known to have one element"),
508 })
509 }
510
511 #[cfg(feature = "alloc")]
532 pub fn try_alloc_map_value<P, E>(
533 &self,
534 mut f: impl FnMut(T) -> Result<P, E>,
535 ) -> Result<CodePointTrie<'trie, P>, E>
536 where
537 P: TrieValue,
538 {
539 let error_converted = f(self.error_value)?;
540 let converted_data = self.data.iter().map(f).collect::<Result<ZeroVec<P>, E>>()?;
541 Ok(CodePointTrie {
542 header: self.header,
543 index: self.index.clone(),
544 data: converted_data,
545 error_value: error_converted,
546 })
547 }
548
549 pub fn get_range(&self, start: u32) -> Option<CodePointMapRange<T>> {
603 if CODE_POINT_MAX < start {
607 return None;
608 }
609 if start >= self.header.high_start {
610 let di: usize = self.data.len() - (HIGH_VALUE_NEG_DATA_OFFSET as usize);
611 let value: T = self.data.get(di)?;
612 return Some(CodePointMapRange {
613 range: start..=CODE_POINT_MAX,
614 value,
615 });
616 }
617
618 let null_value: T = T::try_from_u32(self.header.null_value).ok()?;
619
620 let mut prev_i3_block: u32 = u32::MAX; let mut prev_block: u32 = u32::MAX; let mut c: u32 = start;
623 let mut trie_value: T = self.error_value();
624 let mut value: T = self.error_value();
625 let mut have_value: bool = false;
626
627 loop {
628 let i3_block: u32;
629 let mut i3: u32;
630 let i3_block_length: u32;
631 let data_block_length: u32;
632
633 if c <= 0xffff
646 && (self.header.trie_type == TrieType::Fast || c <= SMALL_TYPE_FAST_INDEXING_MAX)
647 {
648 i3_block = 0;
649 i3 = c >> FAST_TYPE_SHIFT;
650 i3_block_length = if self.header.trie_type == TrieType::Fast {
651 BMP_INDEX_LENGTH
652 } else {
653 SMALL_INDEX_LENGTH
654 };
655 data_block_length = FAST_TYPE_DATA_BLOCK_LENGTH;
656 } else {
657 let mut i1: u32 = c >> SHIFT_1;
659 if self.header.trie_type == TrieType::Fast {
660 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);
661 i1 = i1 + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH;
662 } else {
663 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!(
664 c < self.header.high_start && self.header.high_start > SMALL_LIMIT
665 );
666 i1 += SMALL_INDEX_LENGTH;
667 }
668 let i2: u16 = self.index.get(i1 as usize)?;
669 let i3_block_idx: u32 = (i2 as u32) + ((c >> SHIFT_2) & INDEX_2_MASK);
670 i3_block = if let Some(i3b) = self.index.get(i3_block_idx as usize) {
671 i3b as u32
672 } else {
673 return None;
674 };
675 if i3_block == prev_i3_block && (c - start) >= CP_PER_INDEX_2_ENTRY {
676 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);
678 c += CP_PER_INDEX_2_ENTRY;
679
680 if c >= self.header.high_start {
681 break;
682 } else {
683 continue;
684 }
685 }
686 prev_i3_block = i3_block;
687 if i3_block == self.header.index3_null_offset as u32 {
688 if have_value {
695 if null_value != value {
696 return Some(CodePointMapRange {
697 range: start..=(c - 1),
698 value,
699 });
700 }
701 } else {
702 trie_value = T::try_from_u32(self.header.null_value).ok()?;
703 value = null_value;
704 have_value = true;
705 }
706 prev_block = self.header.data_null_offset;
707 c = (c + CP_PER_INDEX_2_ENTRY) & !(CP_PER_INDEX_2_ENTRY - 1);
708
709 if c >= self.header.high_start {
710 break;
711 } else {
712 continue;
713 }
714 }
715 i3 = (c >> SHIFT_3) & INDEX_3_MASK;
716 i3_block_length = INDEX_3_BLOCK_LENGTH;
717 data_block_length = SMALL_DATA_BLOCK_LENGTH;
718 }
719
720 loop {
722 let mut block: u32;
723 if (i3_block & 0x8000) == 0 {
724 block = if let Some(b) = self.index.get((i3_block + i3) as usize) {
725 b as u32
726 } else {
727 return None;
728 };
729 } else {
730 let mut group: u32 = (i3_block & 0x7fff) + (i3 & !7) + (i3 >> 3);
732 let gi: u32 = i3 & 7;
733 let gi_val: u32 = if let Some(giv) = self.index.get(group as usize) {
734 giv.into()
735 } else {
736 return None;
737 };
738 block = (gi_val << (2 + (2 * gi))) & 0x30000;
739 group += 1;
740 let ggi_val: u32 = if let Some(ggiv) = self.index.get((group + gi) as usize) {
741 ggiv as u32
742 } else {
743 return None;
744 };
745 block |= ggi_val;
746 }
747
748 if block == prev_block && (c - start) >= data_block_length {
756 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);
758 c += data_block_length;
759 } else {
760 let data_mask: u32 = data_block_length - 1;
761 prev_block = block;
762 if block == self.header.data_null_offset {
763 if have_value {
768 if null_value != value {
769 return Some(CodePointMapRange {
770 range: start..=(c - 1),
771 value,
772 });
773 }
774 } else {
775 trie_value = T::try_from_u32(self.header.null_value).ok()?;
776 value = null_value;
777 have_value = true;
778 }
779 c = (c + data_block_length) & !data_mask;
780 } else {
781 let mut di: u32 = block + (c & data_mask);
782 let mut trie_value_2: T = self.data.get(di as usize)?;
783 if have_value {
784 if trie_value_2 != trie_value {
785 if maybe_filter_value(
786 trie_value_2,
787 T::try_from_u32(self.header.null_value).ok()?,
788 null_value,
789 ) != value
790 {
791 return Some(CodePointMapRange {
792 range: start..=(c - 1),
793 value,
794 });
795 }
796 trie_value = trie_value_2; }
815 } else {
816 trie_value = trie_value_2;
817 value = maybe_filter_value(
818 trie_value_2,
819 T::try_from_u32(self.header.null_value).ok()?,
820 null_value,
821 );
822 have_value = true;
823 }
824
825 c += 1;
826 while (c & data_mask) != 0 {
827 di += 1;
828 trie_value_2 = self.data.get(di as usize)?;
829 if trie_value_2 != trie_value {
830 if maybe_filter_value(
831 trie_value_2,
832 T::try_from_u32(self.header.null_value).ok()?,
833 null_value,
834 ) != value
835 {
836 return Some(CodePointMapRange {
837 range: start..=(c - 1),
838 value,
839 });
840 }
841 trie_value = trie_value_2; }
860
861 c += 1;
862 }
863 }
864 }
865
866 i3 += 1;
867 if i3 >= i3_block_length {
868 break;
869 }
870 }
871
872 if c >= self.header.high_start {
873 break;
874 }
875 }
876
877 if true {
if !have_value {
::core::panicking::panic("assertion failed: have_value")
};
};debug_assert!(have_value);
878
879 let di: u32 = self.data.len() as u32 - HIGH_VALUE_NEG_DATA_OFFSET;
884 let high_value: T = self.data.get(di as usize)?;
885 if maybe_filter_value(
886 high_value,
887 T::try_from_u32(self.header.null_value).ok()?,
888 null_value,
889 ) != value
890 {
891 c -= 1;
892 } else {
893 c = CODE_POINT_MAX;
894 }
895 Some(CodePointMapRange {
896 range: start..=c,
897 value,
898 })
899 }
900
901 pub fn iter_ranges(&self) -> CodePointMapRangeIterator<T> {
934 let init_range = Some(CodePointMapRange {
935 range: u32::MAX..=u32::MAX,
936 value: self.error_value(),
937 });
938 CodePointMapRangeIterator::<T> {
939 cpt: self,
940 cpm_range: init_range,
941 }
942 }
943
944 pub fn iter_ranges_for_value(
966 &self,
967 value: T,
968 ) -> impl Iterator<Item = RangeInclusive<u32>> + '_ {
969 self.iter_ranges()
970 .filter(move |cpm_range| cpm_range.value == value)
971 .map(|cpm_range| cpm_range.range)
972 }
973
974 pub fn iter_ranges_mapped<'a, U: Eq + 'a>(
996 &'a self,
997 mut map: impl FnMut(T) -> U + Copy + 'a,
998 ) -> impl Iterator<Item = CodePointMapRange<U>> + 'a {
999 crate::iterator_utils::RangeListIteratorCoalescer::new(self.iter_ranges().map(
1000 move |range| CodePointMapRange {
1001 range: range.range,
1002 value: map(range.value),
1003 },
1004 ))
1005 }
1006
1007 #[cfg(feature = "alloc")]
1029 pub fn get_set_for_value(&self, value: T) -> CodePointInversionList<'static> {
1030 let value_ranges = self.iter_ranges_for_value(value);
1031 CodePointInversionList::from_iter(value_ranges)
1032 }
1033
1034 #[inline]
1036 pub fn error_value(&self) -> T {
1037 self.error_value
1038 }
1039}
1040
1041#[cfg(feature = "databake")]
1042impl<T: TrieValue + databake::Bake> databake::Bake for CodePointTrie<'_, T> {
1043 fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
1044 let header = self.header.bake(env);
1045 let index = self.index.bake(env);
1046 let data = self.data.bake(env);
1047 let error_value = self.error_value.bake(env);
1048 databake::quote! { icu_collections::codepointtrie::CodePointTrie::from_parts(#header, #index, #data, #error_value) }
1049 }
1050}
1051
1052#[cfg(feature = "databake")]
1053impl<T: TrieValue + databake::Bake> databake::BakeSize for CodePointTrie<'_, T> {
1054 fn borrows_size(&self) -> usize {
1055 self.header.borrows_size() + self.index.borrows_size() + self.data.borrows_size()
1056 }
1057}
1058
1059impl<T: TrieValue + Into<u32>> CodePointTrie<'_, T> {
1060 pub fn get32_u32(&self, code_point: u32) -> u32 {
1078 self.get32(code_point).into()
1079 }
1080}
1081
1082impl<T: TrieValue> Clone for CodePointTrie<'_, T>
1083where
1084 <T as zerovec::ule::AsULE>::ULE: Clone,
1085{
1086 fn clone(&self) -> Self {
1087 CodePointTrie {
1088 header: self.header,
1089 index: self.index.clone(),
1090 data: self.data.clone(),
1091 error_value: self.error_value,
1092 }
1093 }
1094}
1095
1096)]
1102pub struct CodePointMapRange<T> {
1103 pub range: RangeInclusive<u32>,
1105 pub value: T,
1107}
1108
1109pub struct CodePointMapRangeIterator<'a, T: TrieValue> {
1112 cpt: &'a CodePointTrie<'a, T>,
1113 cpm_range: Option<CodePointMapRange<T>>,
1120}
1121
1122impl<T: TrieValue> Iterator for CodePointMapRangeIterator<'_, T> {
1123 type Item = CodePointMapRange<T>;
1124
1125 fn next(&mut self) -> Option<Self::Item> {
1126 self.cpm_range = match &self.cpm_range {
1127 Some(cpmr) => {
1128 if *cpmr.range.start() == u32::MAX {
1129 self.cpt.get_range(0)
1130 } else {
1131 self.cpt.get_range(cpmr.range.end() + 1)
1132 }
1133 }
1134 None => None,
1135 };
1136 self.cpm_range.clone()
1138 }
1139}
1140
1141#[cfg(test)]
1142mod tests {
1143 use super::*;
1144 use crate::codepointtrie::planes;
1145 use alloc::vec::Vec;
1146
1147 #[test]
1148 #[cfg(feature = "serde")]
1149 fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> {
1150 let trie = crate::codepointtrie::planes::get_planes_trie();
1151 let trie_serialized: Vec<u8> = postcard::to_allocvec(&trie).unwrap();
1152
1153 const EXP_TRIE_SERIALIZED: &[u8] = &[
1155 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,
1156 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,
1157 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,
1158 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,
1159 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,
1160 2, 144, 2, 144, 2, 144, 2, 176, 2, 176, 2, 176, 2, 176, 2, 208, 2, 208, 2, 208, 2, 208,
1161 2, 240, 2, 240, 2, 240, 2, 240, 2, 16, 3, 16, 3, 16, 3, 16, 3, 48, 3, 48, 3, 48, 3, 48,
1162 3, 80, 3, 80, 3, 80, 3, 80, 3, 112, 3, 112, 3, 112, 3, 112, 3, 144, 3, 144, 3, 144, 3,
1163 144, 3, 176, 3, 176, 3, 176, 3, 176, 3, 208, 3, 208, 3, 208, 3, 208, 3, 240, 3, 240, 3,
1164 240, 3, 240, 3, 16, 4, 16, 4, 16, 4, 16, 4, 48, 4, 48, 4, 48, 4, 48, 4, 80, 4, 80, 4,
1165 80, 4, 80, 4, 112, 4, 112, 4, 112, 4, 112, 4, 0, 0, 16, 0, 32, 0, 48, 0, 64, 0, 80, 0,
1166 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,
1167 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,
1168 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 128, 0, 128, 0, 128, 0, 128,
1169 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1170 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
1171 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1172 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1173 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144,
1174 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1175 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1176 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160,
1177 0, 160, 0, 160, 0, 160, 0, 160, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1178 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1179 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176,
1180 0, 176, 0, 176, 0, 176, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1181 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1182 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192,
1183 0, 192, 0, 192, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1184 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1185 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208,
1186 0, 208, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1187 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1188 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224,
1189 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1190 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240,
1191 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 0,
1192 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,
1193 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,
1194 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,
1195 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,
1196 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,
1197 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,
1198 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,
1199 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,
1200 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,
1201 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,
1202 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,
1203 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,
1204 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,
1205 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,
1206 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,
1207 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,
1208 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,
1209 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 128, 0, 136, 0, 136, 0, 136, 0, 136,
1210 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,
1211 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,
1212 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,
1213 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1214 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0,
1215 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1216 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1217 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0,
1218 200, 0, 200, 0, 200, 0, 200, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1219 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1220 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0,
1221 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,
1222 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,
1223 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,
1224 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,
1225 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,
1226 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,
1227 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,
1228 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1229 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1230 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1,
1231 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1232 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1233 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1,
1234 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1235 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1236 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1,
1237 168, 1, 168, 1, 168, 1, 168, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1238 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1239 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1,
1240 200, 1, 200, 1, 200, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1241 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1242 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1,
1243 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,
1244 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,
1245 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,
1246 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,
1247 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,
1248 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,
1249 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,
1250 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1251 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1252 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2,
1253 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,
1254 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,
1255 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,
1256 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,
1257 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,
1258 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,
1259 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,
1260 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,
1261 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,
1262 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,
1263 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
1264 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
1265 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
1266 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1267 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 0,
1268 ];
1269 assert_eq!(trie_serialized, EXP_TRIE_SERIALIZED);
1270
1271 let trie_deserialized = postcard::from_bytes::<CodePointTrie<u8>>(&trie_serialized)?;
1272
1273 assert_eq!(&trie.index, &trie_deserialized.index);
1274 assert_eq!(&trie.data, &trie_deserialized.data);
1275
1276 assert!(!trie_deserialized.index.is_owned());
1277 assert!(!trie_deserialized.data.is_owned());
1278
1279 Ok(())
1280 }
1281
1282 #[test]
1283 fn test_get_range() {
1284 let planes_trie = planes::get_planes_trie();
1285
1286 let first_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x0);
1287 assert_eq!(
1288 first_range,
1289 Some(CodePointMapRange {
1290 range: 0x0..=0xffff,
1291 value: 0
1292 })
1293 );
1294
1295 let second_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x1_0000);
1296 assert_eq!(
1297 second_range,
1298 Some(CodePointMapRange {
1299 range: 0x10000..=0x1ffff,
1300 value: 1
1301 })
1302 );
1303
1304 let penultimate_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0xf_0000);
1305 assert_eq!(
1306 penultimate_range,
1307 Some(CodePointMapRange {
1308 range: 0xf_0000..=0xf_ffff,
1309 value: 15
1310 })
1311 );
1312
1313 let last_range: Option<CodePointMapRange<u8>> = planes_trie.get_range(0x10_0000);
1314 assert_eq!(
1315 last_range,
1316 Some(CodePointMapRange {
1317 range: 0x10_0000..=0x10_ffff,
1318 value: 16
1319 })
1320 );
1321 }
1322
1323 #[test]
1324 fn databake() {
1325 databake::test_bake!(
1326 CodePointTrie<'static, u32>,
1327 const,
1328 crate::codepointtrie::CodePointTrie::from_parts(
1329 crate::codepointtrie::CodePointTrieHeader {
1330 high_start: 1u32,
1331 shifted12_high_start: 2u16,
1332 index3_null_offset: 3u16,
1333 data_null_offset: 4u32,
1334 null_value: 5u32,
1335 trie_type: crate::codepointtrie::TrieType::Small,
1336 },
1337 zerovec::ZeroVec::new(),
1338 zerovec::ZeroVec::new(),
1339 0u32,
1340 ),
1341 icu_collections,
1342 [zerovec],
1343 );
1344 }
1345}