1use core::iter::FusedIterator;
6use core::marker::PhantomData;
7
8use crate::codepointtrie::AbstractCodePointTrie;
9use crate::codepointtrie::TrieValue;
10
11pub trait WithTrie<'trie, T, V>
15where
16 V: TrieValue,
17 T: AbstractCodePointTrie<'trie, V>,
18{
19 fn trie(&self) -> &'trie T;
21}
22
23#[derive(Debug)]
25pub struct CharsWithTrie<'slice, 'trie, T, V>
26where
27 V: TrieValue,
28 T: AbstractCodePointTrie<'trie, V>,
29{
30 delegate: core::slice::Iter<'slice, u8>,
31 trie: &'trie T,
32 phantom: PhantomData<V>,
33}
34
35impl<'slice, 'trie, T, V> CharsWithTrie<'slice, 'trie, T, V>
36where
37 V: TrieValue,
38 T: AbstractCodePointTrie<'trie, V>,
39{
40 #[inline]
42 pub fn new(s: &'slice str, trie: &'trie T) -> Self {
43 Self {
44 delegate: s.as_bytes().iter(),
45 trie,
46 phantom: PhantomData,
47 }
48 }
49
50 #[inline]
52 pub fn as_str(&self) -> &'slice str {
53 unsafe { core::str::from_utf8_unchecked(self.delegate.as_slice()) }
57 }
58}
59
60impl<'slice, 'trie, T, V> Clone for CharsWithTrie<'slice, 'trie, T, V>
61where
62 V: TrieValue,
63 T: AbstractCodePointTrie<'trie, V>,
64{
65 #[inline]
66 fn clone(&self) -> Self {
67 Self {
68 delegate: self.delegate.clone(),
69 trie: self.trie,
70 phantom: PhantomData,
71 }
72 }
73}
74
75impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for CharsWithTrie<'slice, 'trie, T, V>
76where
77 V: TrieValue,
78 T: AbstractCodePointTrie<'trie, V>,
79{
80 #[inline]
81 fn trie(&self) -> &'trie T {
82 self.trie
83 }
84}
85
86impl<'slice, 'trie, T, V> Iterator for CharsWithTrie<'slice, 'trie, T, V>
87where
88 V: TrieValue,
89 T: AbstractCodePointTrie<'trie, V>,
90{
91 type Item = (char, V);
92
93 #[inline]
94 fn next(&mut self) -> Option<Self::Item> {
95 let lead = *self.delegate.next()?;
96 if lead < 0x80 {
97 return Some((char::from(lead), unsafe { self.trie.ascii(lead) }));
100 }
101 if lead < 0xE0 {
104 let trail = *unsafe { self.delegate.next().unwrap_unchecked() };
108 let high_five = u32::from(lead & 0b11_111);
109 let low_six = u32::from(trail & 0b111_111);
110 let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
113 let c = unsafe { char::from_u32_unchecked((high_five << 6) | low_six) };
118 return Some((c, v));
119 }
120 if lead < 0xF0 {
121 let second = *unsafe { self.delegate.next().unwrap_unchecked() };
125 let third = *unsafe { self.delegate.next().unwrap_unchecked() };
126 let high_ten = (u32::from(lead & 0b1111) << 6) | u32::from(second & 0b111_111);
127 let low_six = u32::from(third & 0b111_111);
128 let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
131 let c = unsafe { char::from_u32_unchecked((high_ten << 6) | low_six) };
136 return Some((c, v));
137 }
138 let second = *unsafe { self.delegate.next().unwrap_unchecked() };
142 let third = *unsafe { self.delegate.next().unwrap_unchecked() };
143 let fourth = *unsafe { self.delegate.next().unwrap_unchecked() };
144 let c = unsafe {
149 char::from_u32_unchecked(
150 (u32::from(lead & 0b111) << 18)
151 | (u32::from(second & 0b111_111) << 12)
152 | (u32::from(third & 0b111_111) << 6)
153 | u32::from(fourth & 0b111_111),
154 )
155 };
156 Some((c, self.trie.supplementary(c as u32)))
157 }
158
159 #[inline]
160 fn count(self) -> usize {
161 self.as_str().chars().count()
162 }
163
164 #[inline]
165 fn size_hint(&self) -> (usize, Option<usize>) {
166 self.as_str().chars().size_hint()
167 }
168
169 #[inline]
170 fn last(mut self) -> Option<Self::Item> {
171 self.next_back()
172 }
173
174 }
176
177impl<'slice, 'trie, T, V> DoubleEndedIterator for CharsWithTrie<'slice, 'trie, T, V>
178where
179 V: TrieValue,
180 T: AbstractCodePointTrie<'trie, V>,
181{
182 #[inline]
183 fn next_back(&mut self) -> Option<Self::Item> {
184 let last = *self.delegate.next_back()?;
185 if last < 0x80 {
186 return Some((char::from(last), unsafe { self.trie.ascii(last) }));
189 }
190 let second_last = *unsafe { self.delegate.next_back().unwrap_unchecked() };
194 if second_last >= 0b1100_0000 {
195 let high_five = u32::from(second_last & 0b11_111);
197 let low_six = u32::from(last & 0b111_111);
198 let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
201 let c = unsafe { char::from_u32_unchecked((high_five << 6) | low_six) };
206 return Some((c, v));
207 }
208 let third_last = *unsafe { self.delegate.next_back().unwrap_unchecked() };
212 if third_last >= 0b1100_0000 {
213 let high_ten =
215 (u32::from(third_last & 0b1111) << 6) | u32::from(second_last & 0b111_111);
216 let low_six = u32::from(last & 0b111_111);
217 let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
220 let c = unsafe { char::from_u32_unchecked((high_ten << 6) | low_six) };
225 return Some((c, v));
226 }
227 let lead = *unsafe { self.delegate.next_back().unwrap_unchecked() };
231 let c = unsafe {
236 char::from_u32_unchecked(
237 (u32::from(lead & 0b111) << 18)
238 | (u32::from(third_last & 0b111_111) << 12)
239 | (u32::from(second_last & 0b111_111) << 6)
240 | u32::from(last & 0b111_111),
241 )
242 };
243 Some((c, self.trie.supplementary(c as u32)))
244 }
245}
246
247impl<'slice, 'trie, T, V> FusedIterator for CharsWithTrie<'slice, 'trie, T, V>
248where
249 V: TrieValue,
250 T: AbstractCodePointTrie<'trie, V>,
251{
252}
253#[derive(Debug)]
257pub struct CharIndicesWithTrie<'slice, 'trie, T, V>
258where
259 V: TrieValue,
260 T: AbstractCodePointTrie<'trie, V>,
261{
262 offset: usize,
263 delegate: CharsWithTrie<'slice, 'trie, T, V>,
264}
265
266impl<'slice, 'trie, T, V> CharIndicesWithTrie<'slice, 'trie, T, V>
267where
268 V: TrieValue,
269 T: AbstractCodePointTrie<'trie, V>,
270{
271 #[inline]
273 pub fn new(s: &'slice str, trie: &'trie T) -> Self {
274 Self {
275 offset: 0,
276 delegate: CharsWithTrie::new(s, trie),
277 }
278 }
279
280 #[inline]
282 pub fn as_str(&self) -> &'slice str {
283 self.delegate.as_str()
284 }
285}
286
287impl<'slice, 'trie, T, V> Clone for CharIndicesWithTrie<'slice, 'trie, T, V>
288where
289 V: TrieValue,
290 T: AbstractCodePointTrie<'trie, V>,
291{
292 #[inline]
293 fn clone(&self) -> Self {
294 Self {
295 offset: self.offset,
296 delegate: self.delegate.clone(),
297 }
298 }
299}
300
301impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for CharIndicesWithTrie<'slice, 'trie, T, V>
302where
303 V: TrieValue,
304 T: AbstractCodePointTrie<'trie, V>,
305{
306 #[inline]
307 fn trie(&self) -> &'trie T {
308 self.delegate.trie()
309 }
310}
311
312impl<'slice, 'trie, T, V> Iterator for CharIndicesWithTrie<'slice, 'trie, T, V>
313where
314 V: TrieValue,
315 T: AbstractCodePointTrie<'trie, V>,
316{
317 type Item = (usize, char, V);
318
319 #[inline]
320 fn next(&mut self) -> Option<Self::Item> {
321 let old_len = self.as_str().len();
322 let (c, v) = self.delegate.next()?;
323 let old_offset = self.offset;
324 self.offset += old_len - self.as_str().len();
325 Some((old_offset, c, v))
326 }
327
328 #[inline]
329 fn count(self) -> usize {
330 self.as_str().chars().count()
331 }
332
333 #[inline]
334 fn size_hint(&self) -> (usize, Option<usize>) {
335 self.as_str().chars().size_hint()
336 }
337
338 #[inline]
339 fn last(mut self) -> Option<Self::Item> {
340 self.next_back()
341 }
342
343 }
345
346impl<'slice, 'trie, T, V> DoubleEndedIterator for CharIndicesWithTrie<'slice, 'trie, T, V>
347where
348 V: TrieValue,
349 T: AbstractCodePointTrie<'trie, V>,
350{
351 #[inline]
352 fn next_back(&mut self) -> Option<Self::Item> {
353 let (c, v) = self.delegate.next_back()?;
354 Some((self.offset + self.as_str().len(), c, v))
355 }
356}
357
358impl<'slice, 'trie, T, V> FusedIterator for CharIndicesWithTrie<'slice, 'trie, T, V>
359where
360 V: TrieValue,
361 T: AbstractCodePointTrie<'trie, V>,
362{
363}
364
365pub trait CharsWithTrieEx<'slice, 'trie, T, V>
369where
370 V: TrieValue,
371 T: AbstractCodePointTrie<'trie, V>,
372{
373 fn chars_with_trie(&'slice self, trie: &'trie T) -> CharsWithTrie<'slice, 'trie, T, V>;
375
376 fn char_indices_with_trie(
378 &'slice self,
379 trie: &'trie T,
380 ) -> CharIndicesWithTrie<'slice, 'trie, T, V>;
381}
382
383impl<'slice, 'trie, T, V> CharsWithTrieEx<'slice, 'trie, T, V> for str
384where
385 V: TrieValue,
386 T: AbstractCodePointTrie<'trie, V>,
387{
388 #[inline]
390 fn chars_with_trie(&'slice self, trie: &'trie T) -> CharsWithTrie<'slice, 'trie, T, V> {
391 CharsWithTrie::new(self, trie)
392 }
393
394 #[inline]
396 fn char_indices_with_trie(
397 &'slice self,
398 trie: &'trie T,
399 ) -> CharIndicesWithTrie<'slice, 'trie, T, V> {
400 CharIndicesWithTrie::new(self, trie)
401 }
402}
403
404#[derive(Debug)]
412pub struct CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
413where
414 V: TrieValue + Default,
415 T: AbstractCodePointTrie<'trie, V>,
416{
417 delegate: core::slice::Iter<'slice, u8>,
418 trie: &'trie T,
419 phantom: PhantomData<V>,
420}
421
422impl<'slice, 'trie, T, V> CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
423where
424 V: TrieValue + Default,
425 T: AbstractCodePointTrie<'trie, V>,
426{
427 #[inline]
429 pub fn new(s: &'slice str, trie: &'trie T) -> Self {
430 Self {
431 delegate: s.as_bytes().iter(),
432 trie,
433 phantom: PhantomData,
434 }
435 }
436
437 #[inline]
439 pub fn as_str(&self) -> &'slice str {
440 unsafe { core::str::from_utf8_unchecked(self.delegate.as_slice()) }
444 }
445}
446
447impl<'slice, 'trie, T, V> Clone for CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
448where
449 V: TrieValue + Default,
450 T: AbstractCodePointTrie<'trie, V>,
451{
452 #[inline]
453 fn clone(&self) -> Self {
454 Self {
455 delegate: self.delegate.clone(),
456 trie: self.trie,
457 phantom: PhantomData,
458 }
459 }
460}
461
462impl<'slice, 'trie, T, V> WithTrie<'trie, T, V>
463 for CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
464where
465 V: TrieValue + Default,
466 T: AbstractCodePointTrie<'trie, V>,
467{
468 #[inline]
469 fn trie(&self) -> &'trie T {
470 self.trie
471 }
472}
473
474impl<'slice, 'trie, T, V> Iterator for CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
475where
476 V: TrieValue + Default,
477 T: AbstractCodePointTrie<'trie, V>,
478{
479 type Item = (char, V);
480
481 #[inline]
482 fn next(&mut self) -> Option<Self::Item> {
483 let lead = *self.delegate.next()?;
484 if lead < 0x80 {
485 return Some((char::from(lead), V::default()));
488 }
489 if lead < 0xE0 {
492 let trail = *unsafe { self.delegate.next().unwrap_unchecked() };
496 let high_five = u32::from(lead & 0b11_111);
497 let low_six = u32::from(trail & 0b111_111);
498 let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
501 let c = unsafe { char::from_u32_unchecked((high_five << 6) | low_six) };
506 return Some((c, v));
507 }
508 if lead < 0xF0 {
509 let second = *unsafe { self.delegate.next().unwrap_unchecked() };
513 let third = *unsafe { self.delegate.next().unwrap_unchecked() };
514 let high_ten = (u32::from(lead & 0b1111) << 6) | u32::from(second & 0b111_111);
515 let low_six = u32::from(third & 0b111_111);
516 let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
519 let c = unsafe { char::from_u32_unchecked((high_ten << 6) | low_six) };
524 return Some((c, v));
525 }
526 let second = *unsafe { self.delegate.next().unwrap_unchecked() };
530 let third = *unsafe { self.delegate.next().unwrap_unchecked() };
531 let fourth = *unsafe { self.delegate.next().unwrap_unchecked() };
532 let c = unsafe {
537 char::from_u32_unchecked(
538 (u32::from(lead & 0b111) << 18)
539 | (u32::from(second & 0b111_111) << 12)
540 | (u32::from(third & 0b111_111) << 6)
541 | u32::from(fourth & 0b111_111),
542 )
543 };
544 Some((c, self.trie.supplementary(c as u32)))
545 }
546
547 #[inline]
548 fn count(self) -> usize {
549 self.as_str().chars().count()
550 }
551
552 #[inline]
553 fn size_hint(&self) -> (usize, Option<usize>) {
554 self.as_str().chars().size_hint()
555 }
556
557 #[inline]
558 fn last(mut self) -> Option<Self::Item> {
559 self.next_back()
560 }
561
562 }
564
565impl<'slice, 'trie, T, V> DoubleEndedIterator for CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
566where
567 V: TrieValue + Default,
568 T: AbstractCodePointTrie<'trie, V>,
569{
570 #[inline]
571 fn next_back(&mut self) -> Option<Self::Item> {
572 let last = *self.delegate.next_back()?;
573 if last < 0x80 {
574 return Some((char::from(last), V::default()));
577 }
578 let second_last = *unsafe { self.delegate.next_back().unwrap_unchecked() };
582 if second_last >= 0b1100_0000 {
583 let high_five = u32::from(second_last & 0b11_111);
585 let low_six = u32::from(last & 0b111_111);
586 let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
589 let c = unsafe { char::from_u32_unchecked((high_five << 6) | low_six) };
594 return Some((c, v));
595 }
596 let third_last = *unsafe { self.delegate.next_back().unwrap_unchecked() };
600 if third_last >= 0b1100_0000 {
601 let high_ten =
603 (u32::from(third_last & 0b1111) << 6) | u32::from(second_last & 0b111_111);
604 let low_six = u32::from(last & 0b111_111);
605 let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
608 let c = unsafe { char::from_u32_unchecked((high_ten << 6) | low_six) };
613 return Some((c, v));
614 }
615 let lead = *unsafe { self.delegate.next_back().unwrap_unchecked() };
619 let c = unsafe {
624 char::from_u32_unchecked(
625 (u32::from(lead & 0b111) << 18)
626 | (u32::from(third_last & 0b111_111) << 12)
627 | (u32::from(second_last & 0b111_111) << 6)
628 | u32::from(last & 0b111_111),
629 )
630 };
631 Some((c, self.trie.supplementary(c as u32)))
632 }
633}
634
635impl<'slice, 'trie, T, V> FusedIterator for CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
636where
637 V: TrieValue + Default,
638 T: AbstractCodePointTrie<'trie, V>,
639{
640}
641#[derive(Debug)]
645pub struct CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
646where
647 V: TrieValue + Default,
648 T: AbstractCodePointTrie<'trie, V>,
649{
650 offset: usize,
651 delegate: CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>,
652}
653
654impl<'slice, 'trie, T, V> CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
655where
656 V: TrieValue + Default,
657 T: AbstractCodePointTrie<'trie, V>,
658{
659 #[inline]
661 pub fn new(s: &'slice str, trie: &'trie T) -> Self {
662 Self {
663 offset: 0,
664 delegate: CharsWithTrieDefaultForAscii::new(s, trie),
665 }
666 }
667
668 #[inline]
670 pub fn as_str(&self) -> &'slice str {
671 self.delegate.as_str()
672 }
673}
674
675impl<'slice, 'trie, T, V> Clone for CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
676where
677 V: TrieValue + Default,
678 T: AbstractCodePointTrie<'trie, V>,
679{
680 #[inline]
681 fn clone(&self) -> Self {
682 Self {
683 offset: self.offset,
684 delegate: self.delegate.clone(),
685 }
686 }
687}
688
689impl<'slice, 'trie, T, V> WithTrie<'trie, T, V>
690 for CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
691where
692 V: TrieValue + Default,
693 T: AbstractCodePointTrie<'trie, V>,
694{
695 #[inline]
696 fn trie(&self) -> &'trie T {
697 self.delegate.trie()
698 }
699}
700
701impl<'slice, 'trie, T, V> Iterator for CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
702where
703 V: TrieValue + Default,
704 T: AbstractCodePointTrie<'trie, V>,
705{
706 type Item = (usize, char, V);
707
708 #[inline]
709 fn next(&mut self) -> Option<Self::Item> {
710 let old_len = self.as_str().len();
711 let (c, v) = self.delegate.next()?;
712 let old_offset = self.offset;
713 self.offset += old_len - self.as_str().len();
714 Some((old_offset, c, v))
715 }
716
717 #[inline]
718 fn count(self) -> usize {
719 self.as_str().chars().count()
720 }
721
722 #[inline]
723 fn size_hint(&self) -> (usize, Option<usize>) {
724 self.as_str().chars().size_hint()
725 }
726
727 #[inline]
728 fn last(mut self) -> Option<Self::Item> {
729 self.next_back()
730 }
731
732 }
734
735impl<'slice, 'trie, T, V> DoubleEndedIterator
736 for CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
737where
738 V: TrieValue + Default,
739 T: AbstractCodePointTrie<'trie, V>,
740{
741 #[inline]
742 fn next_back(&mut self) -> Option<Self::Item> {
743 let (c, v) = self.delegate.next_back()?;
744 Some((self.offset + self.as_str().len(), c, v))
745 }
746}
747
748impl<'slice, 'trie, T, V> FusedIterator for CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
749where
750 V: TrieValue + Default,
751 T: AbstractCodePointTrie<'trie, V>,
752{
753}
754
755pub trait CharsWithTrieDefaultForAsciiEx<'slice, 'trie, T, V>
759where
760 V: TrieValue + Default,
761 T: AbstractCodePointTrie<'trie, V>,
762{
763 fn chars_with_trie_default_for_ascii(
765 &'slice self,
766 trie: &'trie T,
767 ) -> CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>;
768
769 fn char_indices_with_trie_default_for_ascii(
771 &'slice self,
772 trie: &'trie T,
773 ) -> CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>;
774}
775
776impl<'slice, 'trie, T, V> CharsWithTrieDefaultForAsciiEx<'slice, 'trie, T, V> for str
777where
778 V: TrieValue + Default,
779 T: AbstractCodePointTrie<'trie, V>,
780{
781 #[inline]
783 fn chars_with_trie_default_for_ascii(
784 &'slice self,
785 trie: &'trie T,
786 ) -> CharsWithTrieDefaultForAscii<'slice, 'trie, T, V> {
787 CharsWithTrieDefaultForAscii::new(self, trie)
788 }
789
790 #[inline]
792 fn char_indices_with_trie_default_for_ascii(
793 &'slice self,
794 trie: &'trie T,
795 ) -> CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V> {
796 CharIndicesWithTrieDefaultForAscii::new(self, trie)
797 }
798}
799
800#[derive(Debug)]
804pub struct Latin1CharsWithTrie<'slice, 'trie, T, V>
805where
806 V: TrieValue,
807 T: AbstractCodePointTrie<'trie, V>,
808{
809 delegate: core::slice::Iter<'slice, u8>,
810 trie: &'trie T,
811 phantom: PhantomData<V>,
812}
813
814impl<'slice, 'trie, T, V> Latin1CharsWithTrie<'slice, 'trie, T, V>
815where
816 V: TrieValue,
817 T: AbstractCodePointTrie<'trie, V>,
818{
819 #[inline]
821 pub fn new(s: &'slice [u8], trie: &'trie T) -> Self {
822 Self {
823 delegate: s.iter(),
824 trie,
825 phantom: PhantomData,
826 }
827 }
828
829 #[inline]
831 pub fn as_slice(&self) -> &'slice [u8] {
832 self.delegate.as_slice()
833 }
834}
835
836impl<'slice, 'trie, T, V> Clone for Latin1CharsWithTrie<'slice, 'trie, T, V>
837where
838 V: TrieValue,
839 T: AbstractCodePointTrie<'trie, V>,
840{
841 #[inline]
842 fn clone(&self) -> Self {
843 Self {
844 delegate: self.delegate.clone(),
845 trie: self.trie,
846 phantom: PhantomData,
847 }
848 }
849}
850
851impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for Latin1CharsWithTrie<'slice, 'trie, T, V>
852where
853 V: TrieValue,
854 T: AbstractCodePointTrie<'trie, V>,
855{
856 #[inline]
857 fn trie(&self) -> &'trie T {
858 self.trie
859 }
860}
861
862impl<'slice, 'trie, T, V> Iterator for Latin1CharsWithTrie<'slice, 'trie, T, V>
863where
864 V: TrieValue,
865 T: AbstractCodePointTrie<'trie, V>,
866{
867 type Item = (char, V);
868
869 #[inline]
870 fn next(&mut self) -> Option<Self::Item> {
871 let b = *self.delegate.next()?;
872 Some((char::from(b), self.trie.latin1(b)))
873 }
874
875 #[inline]
876 fn count(self) -> usize {
877 self.delegate.count()
878 }
879
880 #[inline]
881 fn size_hint(&self) -> (usize, Option<usize>) {
882 self.delegate.size_hint()
883 }
884
885 #[inline]
886 fn last(mut self) -> Option<Self::Item> {
887 self.next_back()
888 }
889
890 }
892
893impl<'slice, 'trie, T, V> DoubleEndedIterator for Latin1CharsWithTrie<'slice, 'trie, T, V>
894where
895 V: TrieValue,
896 T: AbstractCodePointTrie<'trie, V>,
897{
898 #[inline]
899 fn next_back(&mut self) -> Option<Self::Item> {
900 let b = *self.delegate.next_back()?;
901 Some((char::from(b), self.trie.latin1(b)))
902 }
903}
904
905impl<'slice, 'trie, T, V> FusedIterator for Latin1CharsWithTrie<'slice, 'trie, T, V>
906where
907 V: TrieValue,
908 T: AbstractCodePointTrie<'trie, V>,
909{
910}
911
912#[derive(Debug)]
916pub struct Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
917where
918 V: TrieValue,
919 T: AbstractCodePointTrie<'trie, V>,
920{
921 offset: usize,
922 delegate: core::slice::Iter<'slice, u8>,
923 trie: &'trie T,
924 phantom: PhantomData<V>,
925}
926
927impl<'slice, 'trie, T, V> Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
928where
929 V: TrieValue,
930 T: AbstractCodePointTrie<'trie, V>,
931{
932 #[inline]
934 pub fn new(s: &'slice [u8], trie: &'trie T) -> Self {
935 Self {
936 offset: 0,
937 delegate: s.iter(),
938 trie,
939 phantom: PhantomData,
940 }
941 }
942
943 #[inline]
945 pub fn as_slice(&self) -> &'slice [u8] {
946 self.delegate.as_slice()
947 }
948}
949
950impl<'slice, 'trie, T, V> Clone for Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
951where
952 V: TrieValue,
953 T: AbstractCodePointTrie<'trie, V>,
954{
955 #[inline]
956 fn clone(&self) -> Self {
957 Self {
958 offset: self.offset,
959 delegate: self.delegate.clone(),
960 trie: self.trie,
961 phantom: PhantomData,
962 }
963 }
964}
965
966impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
967where
968 V: TrieValue,
969 T: AbstractCodePointTrie<'trie, V>,
970{
971 #[inline]
972 fn trie(&self) -> &'trie T {
973 self.trie
974 }
975}
976
977impl<'slice, 'trie, T, V> Iterator for Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
978where
979 V: TrieValue,
980 T: AbstractCodePointTrie<'trie, V>,
981{
982 type Item = (usize, char, V);
983
984 #[inline]
985 fn next(&mut self) -> Option<Self::Item> {
986 let b = *self.delegate.next()?;
987 let old_offset = self.offset;
988 self.offset += 1;
989 Some((old_offset, char::from(b), self.trie.latin1(b)))
990 }
991
992 #[inline]
993 fn count(self) -> usize {
994 self.delegate.count()
995 }
996
997 #[inline]
998 fn size_hint(&self) -> (usize, Option<usize>) {
999 self.delegate.size_hint()
1000 }
1001
1002 #[inline]
1003 fn last(mut self) -> Option<Self::Item> {
1004 self.next_back()
1005 }
1006
1007 }
1009
1010impl<'slice, 'trie, T, V> DoubleEndedIterator for Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
1011where
1012 V: TrieValue,
1013 T: AbstractCodePointTrie<'trie, V>,
1014{
1015 #[inline]
1016 fn next_back(&mut self) -> Option<Self::Item> {
1017 let b = *self.delegate.next_back()?;
1018 Some((
1019 self.offset + self.as_slice().len(),
1020 char::from(b),
1021 self.trie.latin1(b),
1022 ))
1023 }
1024}
1025
1026impl<'slice, 'trie, T, V> FusedIterator for Latin1CharIndicesWithTrie<'slice, 'trie, T, V>
1027where
1028 V: TrieValue,
1029 T: AbstractCodePointTrie<'trie, V>,
1030{
1031}
1032
1033pub trait Latin1CharsWithTrieEx<'slice, 'trie, T, V>
1037where
1038 V: TrieValue,
1039 T: AbstractCodePointTrie<'trie, V>,
1040{
1041 fn latin1_chars_with_trie(
1044 &'slice self,
1045 trie: &'trie T,
1046 ) -> Latin1CharsWithTrie<'slice, 'trie, T, V>;
1047
1048 fn latin1_char_indices_with_trie(
1051 &'slice self,
1052 trie: &'trie T,
1053 ) -> Latin1CharIndicesWithTrie<'slice, 'trie, T, V>;
1054}
1055
1056impl<'slice, 'trie, T, V> Latin1CharsWithTrieEx<'slice, 'trie, T, V> for [u8]
1057where
1058 V: TrieValue,
1059 T: AbstractCodePointTrie<'trie, V>,
1060{
1061 #[inline]
1064 fn latin1_chars_with_trie(
1065 &'slice self,
1066 trie: &'trie T,
1067 ) -> Latin1CharsWithTrie<'slice, 'trie, T, V> {
1068 Latin1CharsWithTrie::new(self, trie)
1069 }
1070
1071 #[inline]
1074 fn latin1_char_indices_with_trie(
1075 &'slice self,
1076 trie: &'trie T,
1077 ) -> Latin1CharIndicesWithTrie<'slice, 'trie, T, V> {
1078 Latin1CharIndicesWithTrie::new(self, trie)
1079 }
1080}
1081
1082#[derive(Debug)]
1087pub struct CharIterWithTrie<'trie, T, V, I>
1088where
1089 V: TrieValue,
1090 T: AbstractCodePointTrie<'trie, V>,
1091 I: Iterator<Item = char>,
1092{
1093 delegate: I,
1094 trie: &'trie T,
1095 phantom: PhantomData<V>,
1096}
1097
1098impl<'trie, T, V, I> CharIterWithTrie<'trie, T, V, I>
1099where
1100 V: TrieValue,
1101 T: AbstractCodePointTrie<'trie, V>,
1102 I: Iterator<Item = char>,
1103{
1104 #[inline]
1106 pub fn new(iter: I, trie: &'trie T) -> Self {
1107 Self {
1108 delegate: iter,
1109 trie,
1110 phantom: PhantomData,
1111 }
1112 }
1113}
1114
1115impl<'trie, T, V, I> WithTrie<'trie, T, V> for CharIterWithTrie<'trie, T, V, I>
1116where
1117 V: TrieValue,
1118 T: AbstractCodePointTrie<'trie, V>,
1119 I: Iterator<Item = char>,
1120{
1121 #[inline]
1122 fn trie(&self) -> &'trie T {
1123 self.trie
1124 }
1125}
1126
1127impl<'trie, T, V, I> Iterator for CharIterWithTrie<'trie, T, V, I>
1128where
1129 V: TrieValue,
1130 T: AbstractCodePointTrie<'trie, V>,
1131 I: Iterator<Item = char>,
1132{
1133 type Item = (char, V);
1134
1135 #[inline]
1136 fn next(&mut self) -> Option<Self::Item> {
1137 let c = self.delegate.next()?;
1138 Some((c, self.trie.scalar(c)))
1139 }
1140
1141 #[inline]
1142 fn count(self) -> usize {
1143 self.delegate.count()
1144 }
1145
1146 #[inline]
1147 fn size_hint(&self) -> (usize, Option<usize>) {
1148 self.delegate.size_hint()
1149 }
1150
1151 }
1155
1156impl<'trie, T, V, I> DoubleEndedIterator for CharIterWithTrie<'trie, T, V, I>
1157where
1158 V: TrieValue,
1159 T: AbstractCodePointTrie<'trie, V>,
1160 I: DoubleEndedIterator<Item = char>,
1161{
1162 #[inline]
1163 fn next_back(&mut self) -> Option<Self::Item> {
1164 let c = self.delegate.next_back()?;
1165 Some((c, self.trie.scalar(c)))
1166 }
1167}
1168
1169impl<'trie, T, V, I> FusedIterator for CharIterWithTrie<'trie, T, V, I>
1170where
1171 V: TrieValue,
1172 T: AbstractCodePointTrie<'trie, V>,
1173 I: FusedIterator<Item = char>,
1174{
1175}
1176
1177#[cfg(test)]
1178mod tests {
1179 use super::*;
1180
1181 #[test]
1182 fn test_forward() {
1183 let trie = crate::codepointtrie::planes::get_planes_trie();
1184 let s = "abäαあ🥳𧉧";
1185 let mut iter = s.chars_with_trie(&trie);
1186 assert_eq!(iter.next(), Some(('a', 0)));
1187 assert_eq!(iter.next(), Some(('b', 0)));
1188 assert_eq!(iter.next(), Some(('ä', 0)));
1189 assert_eq!(iter.next(), Some(('α', 0)));
1190 assert_eq!(iter.next(), Some(('あ', 0)));
1191 assert_eq!(iter.next(), Some(('🥳', 1)));
1192 assert_eq!(iter.next(), Some(('𧉧', 2)));
1193 assert_eq!(iter.next(), None);
1194 }
1195
1196 #[test]
1197 fn test_backwards() {
1198 let trie = crate::codepointtrie::planes::get_planes_trie();
1199 let s = "abäαあ🥳𧉧";
1200 let mut iter = s.chars_with_trie(&trie);
1201 assert_eq!(iter.next_back(), Some(('𧉧', 2)));
1202 assert_eq!(iter.next_back(), Some(('🥳', 1)));
1203 assert_eq!(iter.next_back(), Some(('あ', 0)));
1204 assert_eq!(iter.next_back(), Some(('α', 0)));
1205 assert_eq!(iter.next_back(), Some(('ä', 0)));
1206 assert_eq!(iter.next_back(), Some(('b', 0)));
1207 assert_eq!(iter.next_back(), Some(('a', 0)));
1208 assert_eq!(iter.next(), None);
1209 }
1210
1211 #[test]
1212 fn test_indices_forward() {
1213 let trie = crate::codepointtrie::planes::get_planes_trie();
1214 let s = "abäαあ🥳𧉧";
1215 let mut iter = s.char_indices_with_trie(&trie);
1216 assert_eq!(iter.next(), Some((0, 'a', 0)));
1217 assert_eq!(iter.next(), Some((1, 'b', 0)));
1218 assert_eq!(iter.next(), Some((2, 'ä', 0)));
1219 assert_eq!(iter.next(), Some((4, 'α', 0)));
1220 assert_eq!(iter.next(), Some((6, 'あ', 0)));
1221 assert_eq!(iter.next(), Some((9, '🥳', 1)));
1222 assert_eq!(iter.next(), Some((13, '𧉧', 2)));
1223 assert_eq!(iter.next(), None);
1224 }
1225
1226 #[test]
1227 fn test_indices_backwards() {
1228 let trie = crate::codepointtrie::planes::get_planes_trie();
1229 let s = "abäαあ🥳𧉧";
1230 let mut iter = s.char_indices_with_trie(&trie);
1231 assert_eq!(iter.next_back(), Some((13, '𧉧', 2)));
1232 assert_eq!(iter.next_back(), Some((9, '🥳', 1)));
1233 assert_eq!(iter.next_back(), Some((6, 'あ', 0)));
1234 assert_eq!(iter.next_back(), Some((4, 'α', 0)));
1235 assert_eq!(iter.next_back(), Some((2, 'ä', 0)));
1236 assert_eq!(iter.next_back(), Some((1, 'b', 0)));
1237 assert_eq!(iter.next_back(), Some((0, 'a', 0)));
1238 assert_eq!(iter.next(), None);
1239 }
1240}