1use crate::byte_phf::PerfectByteHashMap;
207use crate::cursor::AsciiProbeResult;
208use crate::helpers::*;
209use crate::options::*;
210use crate::varint::read_varint_meta2;
211use crate::varint::read_varint_meta3;
212
213#[cfg(feature = "alloc")]
214use alloc::string::String;
215
216#[inline]
224fn get_branch(mut trie: &[u8], i: usize, n: usize, mut w: usize) -> &[u8] {
225 let mut p = 0usize;
226 let mut q = 0usize;
227 loop {
228 let indices;
229 (indices, trie) = trie.debug_split_at(n - 1);
230 p = (p << 8)
231 + if i == 0 {
232 0
233 } else {
234 *indices.get(i - 1).debug_unwrap_or(&0) as usize
235 };
236 q = match indices.get(i) {
237 Some(x) => (q << 8) + *x as usize,
238 None => trie.len(),
239 };
240 if w == 0 {
241 break;
242 }
243 w -= 1;
244 }
245 trie.get(p..q).debug_unwrap_or(&[])
246}
247
248#[inline]
250fn get_branch_w0(mut trie: &[u8], i: usize, n: usize) -> &[u8] {
251 let indices;
252 (indices, trie) = trie.debug_split_at(n - 1);
253 let p = if i == 0 {
254 0
255 } else {
256 *indices.get(i - 1).debug_unwrap_or(&0) as usize
257 };
258 let q = match indices.get(i) {
259 Some(x) => *x as usize,
260 None => trie.len(),
261 };
262 trie.get(p..q).debug_unwrap_or(&[])
263}
264
265enum NodeType {
267 Ascii,
269 Span,
271 Value,
273 Branch,
275}
276
277impl core::fmt::Debug for NodeType {
278 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
279 use NodeType::*;
280 f.write_str(match *self {
281 Ascii => "a",
282 Span => "s",
283 Value => "v",
284 Branch => "m",
285 })
286 }
287}
288
289#[inline]
290fn byte_type(b: u8) -> NodeType {
291 match b & 0b11100000 {
292 0b10000000 => NodeType::Value,
293 0b10100000 => NodeType::Span,
294 0b11000000 => NodeType::Branch,
295 0b11100000 => NodeType::Branch,
296 _ => NodeType::Ascii,
297 }
298}
299
300#[inline]
301pub(crate) fn get_parameterized<T: ZeroTrieWithOptions + ?Sized>(
302 mut trie: &[u8],
303 mut ascii: &[u8],
304) -> Option<usize> {
305 loop {
306 let (b, x, i, search);
307 (b, trie) = trie.split_first()?;
308 let byte_type = byte_type(*b);
309 (x, trie) = match byte_type {
310 NodeType::Ascii => (0, trie),
311 NodeType::Span => {
312 if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.ascii_mode {
AsciiMode::BinarySpans => true,
_ => false,
}matches!(T::OPTIONS.ascii_mode, AsciiMode::BinarySpans) {
313 read_varint_meta3(*b, trie)
314 } else {
315 if true {
if !false {
{
::core::panicking::panic_fmt(format_args!("Span node found in ASCII trie!"));
}
};
};debug_assert!(false, "Span node found in ASCII trie!");
316 return None;
317 }
318 }
319 NodeType::Value => read_varint_meta3(*b, trie),
320 NodeType::Branch => read_varint_meta2(*b, trie),
321 };
322 if let Some((c, temp)) = ascii.split_first() {
323 if #[allow(non_exhaustive_omitted_patterns)] match byte_type {
NodeType::Ascii => true,
_ => false,
}matches!(byte_type, NodeType::Ascii) {
324 let is_match = if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.case_sensitivity {
CaseSensitivity::IgnoreCase => true,
_ => false,
}matches!(T::OPTIONS.case_sensitivity, CaseSensitivity::IgnoreCase)
325 {
326 b.eq_ignore_ascii_case(c)
327 } else {
328 b == c
329 };
330 if is_match {
331 ascii = temp;
333 continue;
334 } else {
335 return None;
337 }
338 }
339 if #[allow(non_exhaustive_omitted_patterns)] match byte_type {
NodeType::Value => true,
_ => false,
}matches!(byte_type, NodeType::Value) {
340 continue;
342 }
343 if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.ascii_mode {
AsciiMode::BinarySpans => true,
_ => false,
}matches!(T::OPTIONS.ascii_mode, AsciiMode::BinarySpans)
344 && #[allow(non_exhaustive_omitted_patterns)] match byte_type {
NodeType::Span => true,
_ => false,
}matches!(byte_type, NodeType::Span)
345 {
346 let (trie_span, ascii_span);
347 (trie_span, trie) = trie.debug_split_at(x);
348 (ascii_span, ascii) = ascii.split_at_checked(x)?;
349 if trie_span == ascii_span {
350 continue;
352 } else {
353 return None;
355 }
356 }
357 let (x, w) = if x >= 256 { (x & 0xff, x >> 8) } else { (x, 0) };
359 let w = if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.capacity_mode {
CapacityMode::Extended => true,
_ => false,
}matches!(T::OPTIONS.capacity_mode, CapacityMode::Extended) {
360 w
361 } else {
362 if true {
if !(w <= 3) {
{
::core::panicking::panic_fmt(format_args!("get: w > 3 but we assume w <= 3"));
}
};
};debug_assert!(w <= 3, "get: w > 3 but we assume w <= 3");
364 w & 0x3
365 };
366 let x = if x == 0 { 256 } else { x };
367 if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.phf_mode {
PhfMode::BinaryOnly => true,
_ => false,
}matches!(T::OPTIONS.phf_mode, PhfMode::BinaryOnly) || x < 16 {
368 (search, trie) = trie.debug_split_at(x);
370 let bsearch_result =
371 if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.case_sensitivity {
CaseSensitivity::IgnoreCase => true,
_ => false,
}matches!(T::OPTIONS.case_sensitivity, CaseSensitivity::IgnoreCase) {
372 search.binary_search_by_key(&c.to_ascii_lowercase(), |x| {
373 x.to_ascii_lowercase()
374 })
375 } else {
376 search.binary_search(c)
377 };
378 i = bsearch_result.ok()?;
379 } else {
380 (search, trie) = trie.debug_split_at(x * 2 + 1);
382 i = PerfectByteHashMap::from_store(search).get(*c)?;
383 }
384 trie = if w == 0 {
385 get_branch_w0(trie, i, x)
386 } else {
387 get_branch(trie, i, x, w)
388 };
389 ascii = temp;
390 continue;
391 } else {
392 if #[allow(non_exhaustive_omitted_patterns)] match byte_type {
NodeType::Value => true,
_ => false,
}matches!(byte_type, NodeType::Value) {
393 return Some(x);
395 }
396 return None;
397 }
398 }
399}
400
401#[inline]
415pub(crate) fn step_parameterized<T: ZeroTrieWithOptions + ?Sized>(
416 trie: &mut &[u8],
417 c: u8,
418) -> Option<u8> {
419 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.ascii_mode
{
AsciiMode::AsciiOnly => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("Spans not yet implemented in step function"));
}
};
};debug_assert!(
423 matches!(T::OPTIONS.ascii_mode, AsciiMode::AsciiOnly),
424 "Spans not yet implemented in step function"
425 );
426 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.phf_mode {
PhfMode::BinaryOnly => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("PHF not yet implemented in step function"));
}
};
};debug_assert!(
428 matches!(T::OPTIONS.phf_mode, PhfMode::BinaryOnly),
429 "PHF not yet implemented in step function"
430 );
431 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.capacity_mode
{
CapacityMode::Normal => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("Extended capacity not yet implemented in step function"));
}
};
};debug_assert!(
433 matches!(T::OPTIONS.capacity_mode, CapacityMode::Normal),
434 "Extended capacity not yet implemented in step function"
435 );
436 let (mut b, x, search);
437 loop {
438 (b, *trie) = match trie.split_first() {
439 Some(v) => v,
440 None => {
441 return None;
443 }
444 };
445 match byte_type(*b) {
446 NodeType::Ascii => {
447 let is_match = if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.case_sensitivity {
CaseSensitivity::IgnoreCase => true,
_ => false,
}matches!(T::OPTIONS.case_sensitivity, CaseSensitivity::IgnoreCase)
448 {
449 b.eq_ignore_ascii_case(&c)
450 } else {
451 *b == c
452 };
453 if is_match {
454 return Some(*b);
456 } else {
457 *trie = &[];
459 return None;
460 }
461 }
462 NodeType::Branch => {
463 (x, *trie) = read_varint_meta2(*b, trie);
465 break;
466 }
467 NodeType::Span => {
468 if true {
if !false {
{
::core::panicking::panic_fmt(format_args!("Span node found in ASCII trie!"));
}
};
};debug_assert!(false, "Span node found in ASCII trie!");
471 return None;
472 }
473 NodeType::Value => {
474 (_, *trie) = read_varint_meta3(*b, trie);
476 continue;
477 }
478 };
479 }
480 let (x, w) = if x >= 256 { (x & 0xff, x >> 8) } else { (x, 0) };
482 if true {
if !(w <= 3) {
{
::core::panicking::panic_fmt(format_args!("get: w > 3 but we assume w <= 3"));
}
};
};debug_assert!(w <= 3, "get: w > 3 but we assume w <= 3");
484 let w = w & 0x3;
485 let x = if x == 0 { 256 } else { x };
486 (search, *trie) = trie.debug_split_at(x);
488 let bsearch_result = if #[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.case_sensitivity {
CaseSensitivity::IgnoreCase => true,
_ => false,
}matches!(T::OPTIONS.case_sensitivity, CaseSensitivity::IgnoreCase) {
489 search.binary_search_by_key(&c.to_ascii_lowercase(), |x| x.to_ascii_lowercase())
490 } else {
491 search.binary_search(&c)
492 };
493 match bsearch_result {
494 Ok(i) => {
495 *trie = if w == 0 {
497 get_branch_w0(trie, i, x)
498 } else {
499 get_branch(trie, i, x, w)
500 };
501 Some(search[i])
502 }
503 Err(_) => {
504 *trie = &[];
506 None
507 }
508 }
509}
510
511#[inline]
517pub(crate) fn probe_parameterized<T: ZeroTrieWithOptions + ?Sized>(
518 trie: &mut &[u8],
519 index: usize,
520) -> Option<AsciiProbeResult> {
521 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.ascii_mode
{
AsciiMode::AsciiOnly => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("Spans not yet implemented in step function"));
}
};
};debug_assert!(
525 matches!(T::OPTIONS.ascii_mode, AsciiMode::AsciiOnly),
526 "Spans not yet implemented in step function"
527 );
528 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.phf_mode {
PhfMode::BinaryOnly => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("PHF not yet implemented in step function"));
}
};
};debug_assert!(
530 matches!(T::OPTIONS.phf_mode, PhfMode::BinaryOnly),
531 "PHF not yet implemented in step function"
532 );
533 if true {
if !#[allow(non_exhaustive_omitted_patterns)] match T::OPTIONS.capacity_mode
{
CapacityMode::Normal => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("Extended capacity not yet implemented in step function"));
}
};
};debug_assert!(
535 matches!(T::OPTIONS.capacity_mode, CapacityMode::Normal),
536 "Extended capacity not yet implemented in step function"
537 );
538 let (mut b, x, search);
539 loop {
540 (b, *trie) = match trie.split_first() {
541 Some(v) => v,
542 None => {
543 return None;
545 }
546 };
547 match byte_type(*b) {
548 NodeType::Ascii => {
549 if index > 0 {
550 *trie = &[];
551 return None;
552 }
553 return Some(AsciiProbeResult {
554 byte: *b,
555 total_siblings: 1,
556 });
557 }
558 NodeType::Branch => {
559 (x, *trie) = read_varint_meta2(*b, trie);
561 break;
562 }
563 NodeType::Span => {
564 if true {
if !false {
{
::core::panicking::panic_fmt(format_args!("Span node found in ASCII trie!"));
}
};
};debug_assert!(false, "Span node found in ASCII trie!");
567 return None;
568 }
569 NodeType::Value => {
570 (_, *trie) = read_varint_meta3(*b, trie);
572 continue;
573 }
574 };
575 }
576 let (x, w) = if x >= 256 { (x & 0xff, x >> 8) } else { (x, 0) };
578 if true {
if !u8::try_from(x).is_ok() {
::core::panicking::panic("assertion failed: u8::try_from(x).is_ok()")
};
};debug_assert!(u8::try_from(x).is_ok());
579 let total_siblings = x as u8;
580 if true {
if !(w <= 3) {
{
::core::panicking::panic_fmt(format_args!("get: w > 3 but we assume w <= 3"));
}
};
};debug_assert!(w <= 3, "get: w > 3 but we assume w <= 3");
582 let w = w & 0x3;
583 let x = if x == 0 { 256 } else { x };
584 if index >= x {
585 *trie = &[];
586 return None;
587 }
588 (search, *trie) = trie.debug_split_at(x);
589 *trie = if w == 0 {
590 get_branch_w0(trie, index, x)
591 } else {
592 get_branch(trie, index, x, w)
593 };
594 Some(AsciiProbeResult {
595 byte: search[index],
596 total_siblings,
597 })
598}
599
600pub(crate) fn take_value(trie: &mut &[u8]) -> Option<usize> {
606 let (b, new_trie) = trie.split_first()?;
607 match byte_type(*b) {
608 NodeType::Ascii | NodeType::Span | NodeType::Branch => None,
609 NodeType::Value => {
610 let x;
611 (x, *trie) = read_varint_meta3(*b, new_trie);
612 Some(x)
613 }
614 }
615}
616
617#[cfg(feature = "alloc")]
618use alloc::vec::Vec;
619
620#[cfg(feature = "alloc")]
622#[derive(Debug)]
623pub struct ZeroTrieIterator<'a> {
624 use_phf: bool,
626 state: Vec<(&'a [u8], Vec<u8>, usize)>,
631}
632
633#[cfg(feature = "alloc")]
634impl<'a> ZeroTrieIterator<'a> {
635 pub(crate) fn new<S: AsRef<[u8]> + ?Sized>(store: &'a S, use_phf: bool) -> Self {
636 ZeroTrieIterator {
637 use_phf,
638 state: alloc::vec![(store.as_ref(), alloc::vec![], 0)],
639 }
640 }
641}
642
643#[cfg(feature = "alloc")]
644impl Iterator for ZeroTrieIterator<'_> {
645 type Item = (Vec<u8>, usize);
646 fn next(&mut self) -> Option<Self::Item> {
647 let (mut trie, mut string, mut branch_idx);
648 (trie, string, branch_idx) = self.state.pop()?;
649 loop {
650 let (b, x, span, search);
651 let return_trie = trie;
652 (b, trie) = match trie.split_first() {
653 Some(tpl) => tpl,
654 None => {
655 (trie, string, branch_idx) = self.state.pop()?;
658 continue;
659 }
660 };
661 let byte_type = byte_type(*b);
662 if matches!(byte_type, NodeType::Ascii) {
663 string.push(*b);
664 continue;
665 }
666 (x, trie) = match byte_type {
667 NodeType::Ascii => (0, trie),
668 NodeType::Span | NodeType::Value => read_varint_meta3(*b, trie),
669 NodeType::Branch => read_varint_meta2(*b, trie),
670 };
671 if matches!(byte_type, NodeType::Span) {
672 (span, trie) = trie.debug_split_at(x);
673 string.extend(span);
674 continue;
675 }
676 if matches!(byte_type, NodeType::Value) {
677 let retval = string.clone();
678 self.state.push((trie, string, 0));
680 return Some((retval, x));
681 }
682 let (x, w) = if x >= 256 { (x & 0xff, x >> 8) } else { (x, 0) };
684 let x = if x == 0 { 256 } else { x };
685 if branch_idx + 1 < x {
686 self.state
688 .push((return_trie, string.clone(), branch_idx + 1));
689 }
690 let byte = if x < 16 || !self.use_phf {
691 (search, trie) = trie.debug_split_at(x);
693 debug_unwrap!(search.get(branch_idx), return None)
694 } else {
695 (search, trie) = trie.debug_split_at(x * 2 + 1);
697 debug_unwrap!(search.get(branch_idx + x + 1), return None)
698 };
699 string.push(*byte);
700 trie = if w == 0 {
701 get_branch_w0(trie, branch_idx, x)
702 } else {
703 get_branch(trie, branch_idx, x, w)
704 };
705 branch_idx = 0;
706 }
707 }
708}
709
710#[cfg(feature = "alloc")]
711pub(crate) fn get_iter_phf<S: AsRef<[u8]> + ?Sized>(store: &S) -> ZeroTrieIterator<'_> {
712 ZeroTrieIterator::new(store, true)
713}
714
715#[cfg(feature = "alloc")]
718#[allow(clippy::type_complexity)]
719pub(crate) fn get_iter_ascii_or_panic<S: AsRef<[u8]> + ?Sized>(
720 store: &S,
721) -> core::iter::Map<ZeroTrieIterator<'_>, fn((Vec<u8>, usize)) -> (String, usize)> {
722 ZeroTrieIterator::new(store, false).map(|(k, v)| {
723 #[allow(clippy::unwrap_used)] let ascii_str = String::from_utf8(k).unwrap();
725 (ascii_str, v)
726 })
727}