zalgo_codec_common/zalgo_string/
iterators.rs1use crate::{decode_byte_pair, ZalgoString};
2use core::iter::FusedIterator;
3
4#[derive(Debug, Clone)]
9#[must_use = "iterators are lazy and do nothing unless consumed"]
10pub struct DecodedBytes<'a>(core::str::Bytes<'a>);
11
12impl<'a> DecodedBytes<'a> {
13 #[inline]
14 pub(crate) fn new(zs: &'a ZalgoString) -> Self {
15 Self(zs.as_combining_chars().bytes())
16 }
17}
18
19impl Iterator for DecodedBytes<'_> {
20 type Item = u8;
21 #[inline]
22 fn next(&mut self) -> Option<Self::Item> {
23 self.0
24 .next()
25 .zip(self.0.next())
26 .map(|(odd, even)| decode_byte_pair(odd, even))
27 }
28
29 #[inline]
30 fn size_hint(&self) -> (usize, Option<usize>) {
31 let left = self.0.size_hint().0 / 2;
32 (left, Some(left))
33 }
34
35 #[inline]
36 fn nth(&mut self, n: usize) -> Option<Self::Item> {
37 self.0
38 .nth(2 * n)
39 .zip(self.0.next())
40 .map(|(odd, even)| decode_byte_pair(odd, even))
41 }
42
43 #[inline]
44 fn last(mut self) -> Option<Self::Item> {
45 self.0
46 .len()
47 .checked_sub(2)
49 .and_then(|l| {
50 self.0
51 .nth(l)
53 .zip(self.0.next())
55 .map(|(odd, even)| decode_byte_pair(odd, even))
57 })
58 }
59
60 #[inline]
61 fn count(self) -> usize {
62 self.0.count() / 2
63 }
64}
65
66impl DoubleEndedIterator for DecodedBytes<'_> {
67 #[inline]
68 fn next_back(&mut self) -> Option<Self::Item> {
69 self.0
70 .next_back()
71 .zip(self.0.next_back())
72 .map(|(even, odd)| decode_byte_pair(odd, even))
73 }
74}
75
76impl FusedIterator for DecodedBytes<'_> {}
77impl ExactSizeIterator for DecodedBytes<'_> {}
78
79#[derive(Debug, Clone)]
84#[must_use = "iterators are lazy and do nothing unless consumed"]
85pub struct DecodedChars<'a>(DecodedBytes<'a>);
86
87impl<'a> DecodedChars<'a> {
88 pub(crate) fn new(zs: &'a ZalgoString) -> Self {
89 Self(zs.decoded_bytes())
90 }
91}
92
93impl Iterator for DecodedChars<'_> {
94 type Item = char;
95 #[inline]
96 fn next(&mut self) -> Option<Self::Item> {
97 self.0.next().map(char::from)
98 }
99
100 #[inline]
101 fn size_hint(&self) -> (usize, Option<usize>) {
102 self.0.size_hint()
103 }
104
105 #[inline]
106 fn nth(&mut self, n: usize) -> Option<Self::Item> {
107 self.0.nth(n).map(char::from)
108 }
109
110 #[inline]
111 fn count(self) -> usize {
112 self.0.count()
113 }
114
115 #[inline]
116 fn last(self) -> Option<Self::Item> {
117 self.0.last().map(char::from)
118 }
119}
120
121impl DoubleEndedIterator for DecodedChars<'_> {
122 #[inline]
123 fn next_back(&mut self) -> Option<Self::Item> {
124 self.0.next_back().map(char::from)
125 }
126}
127
128impl FusedIterator for DecodedChars<'_> {}
129impl ExactSizeIterator for DecodedChars<'_> {}