icu_collections/char16trie/
trie.rs1use zerofrom::ZeroFrom;
6use zerovec::{ZeroSlice, ZeroVec};
7
8const MAX_BRANCH_LINEAR_SUB_NODE_LENGTH: usize = 5;
16
17const MIN_LINEAR_MATCH: u16 = 0x30;
19const MAX_LINEAR_MATCH_LENGTH: u16 = 0x10;
20
21const MIN_VALUE_LEAD: u16 = MIN_LINEAR_MATCH + MAX_LINEAR_MATCH_LENGTH; const NODE_TYPE_MASK: u16 = MIN_VALUE_LEAD - 1; const VALUE_IS_FINAL: u16 = 0x8000;
29
30const MAX_ONE_UNIT_VALUE: u16 = 0x3fff;
32
33const MIN_TWO_UNIT_VALUE_LEAD: u16 = MAX_ONE_UNIT_VALUE + 1; const MAX_ONE_UNIT_NODE_VALUE: u16 = 0xff;
36
37const MIN_TWO_UNIT_NODE_VALUE_LEAD: u16 = MIN_VALUE_LEAD + ((MAX_ONE_UNIT_NODE_VALUE + 1) << 6); const THREE_UNIT_NODE_VALUE_LEAD: u16 = 0x7fc0;
40
41const THREE_UNIT_VALUE_LEAD: u16 = 0x7fff;
42
43const MAX_ONE_UNIT_DELTA: u16 = 0xfbff;
45const MIN_TWO_UNIT_DELTA_LEAD: u16 = MAX_ONE_UNIT_DELTA + 1; const THREE_UNIT_DELTA_LEAD: u16 = 0xffff;
47
48fn skip_value(pos: usize, lead: u16) -> usize {
49 if lead < MIN_TWO_UNIT_VALUE_LEAD {
50 pos
51 } else if lead < THREE_UNIT_VALUE_LEAD {
52 pos + 1
53 } else {
54 pos + 2
55 }
56}
57
58fn skip_node_value(pos: usize, lead: u16) -> usize {
59 if lead < MIN_TWO_UNIT_NODE_VALUE_LEAD {
60 pos
61 } else if lead < THREE_UNIT_NODE_VALUE_LEAD {
62 pos + 1
63 } else {
64 pos + 2
65 }
66}
67
68#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
79#[cfg_attr(feature = "databake", derive(databake::Bake))]
80#[cfg_attr(feature = "databake", databake(path = icu_collections::char16trie))]
81#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<'data> ::core::clone::Clone for Char16Trie<'data> {
#[inline]
fn clone(&self) -> Char16Trie<'data> {
Char16Trie { data: ::core::clone::Clone::clone(&self.data) }
}
}Clone, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<'data> ::core::fmt::Debug for Char16Trie<'data> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Char16Trie",
"data", &&self.data)
}
}Debug, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<'data> ::core::cmp::PartialEq for Char16Trie<'data> {
#[inline]
fn eq(&self, other: &Char16Trie<'data>) -> bool {
self.data == other.data
}
}PartialEq, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl<'data> ::core::cmp::Eq for Char16Trie<'data> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ZeroVec<'data, u16>>;
}
}Eq, impl<'zf, 'zf_inner> zerofrom::ZeroFrom<'zf, Char16Trie<'zf_inner>> for
Char16Trie<'zf> where {
fn zero_from(this: &'zf Char16Trie<'zf_inner>) -> Self {
match *this {
Char16Trie { data: ref __binding_0 } => {
Char16Trie {
data: <ZeroVec<'zf, u16> as
zerofrom::ZeroFrom<'zf,
ZeroVec<'zf_inner, u16>>>::zero_from(__binding_0),
}
}
}
}
}ZeroFrom)]
82#[allow(clippy::exhaustive_structs)] pub struct Char16Trie<'data> {
84 #[cfg_attr(feature = "serde", serde(borrow))]
86 #[doc(hidden)] pub data: ZeroVec<'data, u16>,
88}
89
90impl<'data> Char16Trie<'data> {
91 #[inline]
93 pub fn new(data: ZeroVec<'data, u16>) -> Self {
94 Self { data }
95 }
96
97 #[inline]
99 pub fn iter(&self) -> Char16TrieIterator<'_> {
100 Char16TrieIterator::new(&self.data)
101 }
102}
103
104#[derive(#[automatically_derived]
impl<'a> ::core::clone::Clone for Char16TrieIterator<'a> {
#[inline]
fn clone(&self) -> Char16TrieIterator<'a> {
Char16TrieIterator {
trie: ::core::clone::Clone::clone(&self.trie),
pos: ::core::clone::Clone::clone(&self.pos),
remaining_match_length: ::core::clone::Clone::clone(&self.remaining_match_length),
}
}
}Clone, #[automatically_derived]
impl<'a> ::core::fmt::Debug for Char16TrieIterator<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Char16TrieIterator", "trie", &self.trie, "pos", &self.pos,
"remaining_match_length", &&self.remaining_match_length)
}
}Debug)]
106pub struct Char16TrieIterator<'a> {
107 trie: &'a ZeroSlice<u16>,
109 pos: Option<usize>,
111 remaining_match_length: Option<usize>,
114}
115
116#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::clone::Clone for TrieResult {
#[inline]
fn clone(&self) -> TrieResult {
let _: ::core::clone::AssertParamIsClone<i32>;
*self
}
}Clone, #[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::marker::Copy for TrieResult { }Copy, #[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::fmt::Debug for TrieResult {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
TrieResult::NoMatch =>
::core::fmt::Formatter::write_str(f, "NoMatch"),
TrieResult::NoValue =>
::core::fmt::Formatter::write_str(f, "NoValue"),
TrieResult::FinalValue(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"FinalValue", &__self_0),
TrieResult::Intermediate(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Intermediate", &__self_0),
}
}
}Debug, #[automatically_derived]
#[allow(clippy::exhaustive_enums)]
impl ::core::cmp::PartialEq for TrieResult {
#[inline]
fn eq(&self, other: &TrieResult) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TrieResult::FinalValue(__self_0),
TrieResult::FinalValue(__arg1_0)) => __self_0 == __arg1_0,
(TrieResult::Intermediate(__self_0),
TrieResult::Intermediate(__arg1_0)) => __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
118#[allow(clippy::exhaustive_enums)]
119pub enum TrieResult {
120 NoMatch,
124 NoValue,
127 FinalValue(i32),
131 Intermediate(i32),
135}
136
137fn u16_lead(supplementary: i32) -> u16 {
142 (((supplementary) >> 10) + 0xd7c0) as u16
143}
144
145fn u16_tail(supplementary: i32) -> u16 {
150 (((supplementary) & 0x3ff) | 0xdc00) as u16
151}
152
153macro_rules! trie_unwrap {
157 ($option:expr) => {
158 match $option {
159 Some(x) => x,
160 None => {
161 debug_assert!(false);
163 return TrieResult::NoMatch;
164 }
165 }
166 };
167}
168
169impl<'a> Char16TrieIterator<'a> {
170 #[inline]
172 pub fn new(trie: &'a ZeroSlice<u16>) -> Self {
173 Self {
174 trie,
175 pos: Some(0),
176 remaining_match_length: None,
177 }
178 }
179
180 pub fn next(&mut self, c: char) -> TrieResult {
201 if (c as u32) <= 0xffff {
202 self.next16(c as u16)
203 } else {
204 match self.next16(u16_lead(c as i32)) {
205 TrieResult::NoValue | TrieResult::Intermediate(_) => {
206 self.next16(u16_tail(c as i32))
207 }
208 _ => TrieResult::NoMatch,
209 }
210 }
211 }
212
213 pub fn next32(&mut self, c: u32) -> TrieResult {
234 if c <= 0xffff {
235 self.next16(c as u16)
236 } else {
237 match self.next16(u16_lead(c as i32)) {
238 TrieResult::NoValue | TrieResult::Intermediate(_) => {
239 self.next16(u16_tail(c as i32))
240 }
241 _ => TrieResult::NoMatch,
242 }
243 }
244 }
245
246 pub fn next16(&mut self, c: u16) -> TrieResult {
267 let mut pos = match self.pos {
268 Some(p) => p,
269 None => return TrieResult::NoMatch,
270 };
271 if let Some(length) = self.remaining_match_length {
272 if c == match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) {
274 pos += 1;
275 self.pos = Some(pos);
276 if length == 0 {
277 self.remaining_match_length = None;
278 let node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
279 if node >= MIN_VALUE_LEAD {
280 return self.value_result(pos);
281 }
282 } else {
283 self.remaining_match_length = Some(length - 1);
284 }
285 return TrieResult::NoValue;
286 }
287 self.stop();
288 TrieResult::NoMatch
289 } else {
290 self.next_impl(pos, c)
291 }
292 }
293
294 fn branch_next(&mut self, pos: usize, length: usize, in_unit: u16) -> TrieResult {
295 let mut pos = pos;
296 let mut length = length;
297 if length == 0 {
298 length = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) as usize;
299 pos += 1;
300 }
301 length += 1;
302
303 while length > MAX_BRANCH_LINEAR_SUB_NODE_LENGTH {
306 if in_unit < match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) {
307 length >>= 1;
308 pos = match self.jump_by_delta(pos + 1) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.jump_by_delta(pos + 1));
309 } else {
310 length = length - (length >> 1);
311 pos = match self.skip_delta(pos + 1) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.skip_delta(pos + 1));
312 }
313 }
314 loop {
318 if in_unit == match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) {
319 pos += 1;
320 let mut node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
321 if node & VALUE_IS_FINAL != 0 {
322 self.pos = Some(pos);
323 return self.value_result(pos);
324 }
325 pos += 1;
327
328 if node < MIN_TWO_UNIT_VALUE_LEAD {
329 pos += node as usize;
330 } else if node < THREE_UNIT_VALUE_LEAD {
331 pos += (((node - MIN_TWO_UNIT_VALUE_LEAD) as u32) << 16) as usize
332 | match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) as usize;
333 pos += 1;
334 } else {
335 pos += ((match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) as usize) << 16)
336 | match self.trie.get(pos + 1) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos + 1)) as usize;
337 pos += 2;
338 }
339 node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
340 self.pos = Some(pos);
341
342 if node >= MIN_VALUE_LEAD {
343 return self.value_result(pos);
344 }
345 return TrieResult::NoValue;
346 }
347 length -= 1;
348 pos = match self.skip_value(pos + 1) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.skip_value(pos + 1));
349 if length <= 1 {
350 break;
351 }
352 }
353
354 if in_unit == match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) {
355 pos += 1;
356 self.pos = Some(pos);
357 let node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
358 if node >= MIN_VALUE_LEAD {
359 return self.value_result(pos);
360 }
361 TrieResult::NoValue
362 } else {
363 self.stop();
364 TrieResult::NoMatch
365 }
366 }
367
368 fn next_impl(&mut self, pos: usize, in_unit: u16) -> TrieResult {
369 let mut node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
370 let mut pos = pos + 1;
371 loop {
372 if node < MIN_LINEAR_MATCH {
373 return self.branch_next(pos, node as usize, in_unit);
374 } else if node < MIN_VALUE_LEAD {
375 let length = node - MIN_LINEAR_MATCH;
377 if in_unit == match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos)) {
378 pos += 1;
379 if length == 0 {
380 self.remaining_match_length = None;
381 self.pos = Some(pos);
382 node = match self.trie.get(pos) {
Some(x) => x,
None => {
if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};
return TrieResult::NoMatch;
}
}trie_unwrap!(self.trie.get(pos));
383 if node >= MIN_VALUE_LEAD {
384 return self.value_result(pos);
385 }
386 return TrieResult::NoValue;
387 }
388 self.remaining_match_length = Some(length as usize - 1);
389 self.pos = Some(pos);
390 return TrieResult::NoValue;
391 }
392 break;
394 } else if (node & VALUE_IS_FINAL) != 0 {
395 break;
397 } else {
398 pos = skip_node_value(pos, node);
400 node &= NODE_TYPE_MASK;
401 }
402 }
403 self.stop();
404 TrieResult::NoMatch
405 }
406
407 fn stop(&mut self) {
408 self.pos = None;
409 }
410
411 #[inline(always)] fn jump_by_delta(&self, pos: usize) -> Option<usize> {
413 let delta = self.trie.get(pos)?;
414 let v = if delta < MIN_TWO_UNIT_DELTA_LEAD {
415 pos + 1 + delta as usize
417 } else if delta == THREE_UNIT_DELTA_LEAD {
418 let delta =
419 ((self.trie.get(pos + 1)? as usize) << 16) | (self.trie.get(pos + 2)? as usize);
420 pos + delta + 3
421 } else {
422 let delta = (((delta - MIN_TWO_UNIT_DELTA_LEAD) as usize) << 16)
423 | (self.trie.get(pos + 1)? as usize);
424 pos + delta + 2
425 };
426 Some(v)
427 }
428
429 #[inline(always)] fn skip_value(&self, pos: usize) -> Option<usize> {
431 let lead_unit = self.trie.get(pos)?;
432 Some(skip_value(pos + 1, lead_unit & 0x7fff))
433 }
434
435 #[inline(always)] fn skip_delta(&self, pos: usize) -> Option<usize> {
437 let delta = self.trie.get(pos)?;
438 let v = if delta < MIN_TWO_UNIT_DELTA_LEAD {
439 pos + 1
440 } else if delta == THREE_UNIT_DELTA_LEAD {
441 pos + 3
442 } else {
443 pos + 2
444 };
445 Some(v)
446 }
447
448 fn value_result(&self, pos: usize) -> TrieResult {
449 match self.get_value(pos) {
450 Some(result) => result,
451 None => {
452 if true {
if !false { ::core::panicking::panic("assertion failed: false") };
};debug_assert!(false);
454 TrieResult::NoMatch
455 }
456 }
457 }
458
459 #[inline(always)] fn get_value(&self, pos: usize) -> Option<TrieResult> {
461 let lead_unit = self.trie.get(pos)?;
462 if lead_unit & VALUE_IS_FINAL == VALUE_IS_FINAL {
463 self.read_value(pos + 1, lead_unit & 0x7fff)
464 .map(TrieResult::FinalValue)
465 } else {
466 self.read_node_value(pos + 1, lead_unit)
467 .map(TrieResult::Intermediate)
468 }
469 }
470
471 #[inline(always)] fn read_value(&self, pos: usize, lead_unit: u16) -> Option<i32> {
473 let v = if lead_unit < MIN_TWO_UNIT_VALUE_LEAD {
474 lead_unit.into()
475 } else if lead_unit < THREE_UNIT_VALUE_LEAD {
476 (((lead_unit - MIN_TWO_UNIT_VALUE_LEAD) as i32) << 16) | self.trie.get(pos)? as i32
477 } else {
478 ((self.trie.get(pos)? as i32) << 16) | self.trie.get(pos + 1)? as i32
479 };
480 Some(v)
481 }
482
483 #[inline(always)] fn read_node_value(&self, pos: usize, lead_unit: u16) -> Option<i32> {
485 let v = if lead_unit < (MIN_TWO_UNIT_NODE_VALUE_LEAD) {
486 ((lead_unit >> 6) - 1).into()
487 } else if lead_unit < THREE_UNIT_NODE_VALUE_LEAD {
488 ((((lead_unit & 0x7fc0) - MIN_TWO_UNIT_NODE_VALUE_LEAD) as i32) << 10)
489 | self.trie.get(pos)? as i32
490 } else {
491 ((self.trie.get(pos)? as i32) << 16) | self.trie.get(pos + 1)? as i32
492 };
493 Some(v)
494 }
495}