widestring/ustr/
iter.rs

1use crate::{
2    error::{DecodeUtf16Error, DecodeUtf32Error},
3    iter::{DecodeUtf16, DecodeUtf16Lossy, DecodeUtf32, DecodeUtf32Lossy},
4};
5#[allow(unused_imports)]
6use core::{
7    iter::{Copied, DoubleEndedIterator, ExactSizeIterator, FusedIterator},
8    slice::Iter,
9};
10
11/// An iterator over UTF-16 decoded [`char`][prim@char]s of a string slice.
12///
13/// This struct is created by the `chars` method on strings. See its documentation for more.
14#[derive(Clone)]
15pub struct CharsUtf16<'a> {
16    inner: DecodeUtf16<Copied<Iter<'a, u16>>>,
17}
18
19impl<'a> CharsUtf16<'a> {
20    pub(crate) fn new(s: &'a [u16]) -> Self {
21        Self {
22            inner: crate::decode_utf16(s.iter().copied()),
23        }
24    }
25}
26
27impl Iterator for CharsUtf16<'_> {
28    type Item = Result<char, DecodeUtf16Error>;
29
30    #[inline]
31    fn next(&mut self) -> Option<Self::Item> {
32        self.inner.next()
33    }
34
35    #[inline]
36    fn size_hint(&self) -> (usize, Option<usize>) {
37        self.inner.size_hint()
38    }
39}
40
41impl FusedIterator for CharsUtf16<'_> {}
42
43impl DoubleEndedIterator for CharsUtf16<'_> {
44    #[inline]
45    fn next_back(&mut self) -> Option<Self::Item> {
46        self.inner.next_back()
47    }
48}
49
50impl core::fmt::Debug for CharsUtf16<'_> {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        crate::debug_fmt_utf16_iter(self.clone(), f)
53    }
54}
55
56/// An iterator over UTF-32 decoded [`char`][prim@char]s of a string slice.
57///
58/// This struct is created by the `chars` method on strings. See its documentation for more.
59#[derive(Clone)]
60pub struct CharsUtf32<'a> {
61    inner: DecodeUtf32<Copied<Iter<'a, u32>>>,
62}
63
64impl<'a> CharsUtf32<'a> {
65    pub(crate) fn new(s: &'a [u32]) -> Self {
66        Self {
67            inner: crate::decode_utf32(s.iter().copied()),
68        }
69    }
70}
71
72impl Iterator for CharsUtf32<'_> {
73    type Item = Result<char, DecodeUtf32Error>;
74
75    #[inline]
76    fn next(&mut self) -> Option<Self::Item> {
77        self.inner.next()
78    }
79
80    #[inline]
81    fn size_hint(&self) -> (usize, Option<usize>) {
82        self.inner.size_hint()
83    }
84}
85
86impl FusedIterator for CharsUtf32<'_> {}
87
88impl DoubleEndedIterator for CharsUtf32<'_> {
89    #[inline]
90    fn next_back(&mut self) -> Option<Self::Item> {
91        self.inner.next_back()
92    }
93}
94
95impl ExactSizeIterator for CharsUtf32<'_> {
96    #[inline]
97    fn len(&self) -> usize {
98        self.inner.len()
99    }
100}
101
102impl core::fmt::Debug for CharsUtf32<'_> {
103    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104        crate::debug_fmt_utf32_iter(self.clone(), f)
105    }
106}
107
108/// A lossy iterator over UTF-16 decoded [`char`][prim@char]s of a string slice.
109///
110/// This struct is created by the `chars_lossy` method on strings. See its documentation for more.
111#[derive(Clone)]
112pub struct CharsLossyUtf16<'a> {
113    iter: DecodeUtf16Lossy<Copied<Iter<'a, u16>>>,
114}
115
116impl<'a> CharsLossyUtf16<'a> {
117    pub(crate) fn new(s: &'a [u16]) -> Self {
118        Self {
119            iter: crate::decode_utf16_lossy(s.iter().copied()),
120        }
121    }
122}
123
124impl Iterator for CharsLossyUtf16<'_> {
125    type Item = char;
126
127    #[inline]
128    fn next(&mut self) -> Option<Self::Item> {
129        self.iter.next()
130    }
131
132    #[inline]
133    fn size_hint(&self) -> (usize, Option<usize>) {
134        self.iter.size_hint()
135    }
136}
137
138impl FusedIterator for CharsLossyUtf16<'_> {}
139
140impl DoubleEndedIterator for CharsLossyUtf16<'_> {
141    #[inline]
142    fn next_back(&mut self) -> Option<Self::Item> {
143        self.iter.next_back()
144    }
145}
146
147impl core::fmt::Debug for CharsLossyUtf16<'_> {
148    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149        crate::debug_fmt_char_iter(self.clone(), f)
150    }
151}
152
153/// A lossy iterator over UTF-32 decoded [`char`][prim@char]s of a string slice.
154///
155/// This struct is created by the `chars_lossy` method on strings. See its documentation for more.
156#[derive(Clone)]
157pub struct CharsLossyUtf32<'a> {
158    iter: DecodeUtf32Lossy<Copied<Iter<'a, u32>>>,
159}
160
161impl<'a> CharsLossyUtf32<'a> {
162    pub(crate) fn new(s: &'a [u32]) -> Self {
163        Self {
164            iter: crate::decode_utf32_lossy(s.iter().copied()),
165        }
166    }
167}
168
169impl Iterator for CharsLossyUtf32<'_> {
170    type Item = char;
171
172    #[inline]
173    fn next(&mut self) -> Option<Self::Item> {
174        self.iter.next()
175    }
176
177    #[inline]
178    fn size_hint(&self) -> (usize, Option<usize>) {
179        self.iter.size_hint()
180    }
181}
182
183impl FusedIterator for CharsLossyUtf32<'_> {}
184
185impl DoubleEndedIterator for CharsLossyUtf32<'_> {
186    #[inline]
187    fn next_back(&mut self) -> Option<Self::Item> {
188        self.iter.next_back()
189    }
190}
191
192impl ExactSizeIterator for CharsLossyUtf32<'_> {
193    #[inline]
194    fn len(&self) -> usize {
195        self.iter.len()
196    }
197}
198
199impl core::fmt::Debug for CharsLossyUtf32<'_> {
200    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
201        crate::debug_fmt_char_iter(self.clone(), f)
202    }
203}
204
205/// An iterator over the decoded [`char`][prim@char]s of a string slice, and their positions.
206///
207/// This struct is created by the `char_indices` method on strings. See its documentation for
208/// more.
209#[derive(Debug, Clone)]
210pub struct CharIndicesUtf16<'a> {
211    forward_offset: usize,
212    back_offset: usize,
213    iter: CharsUtf16<'a>,
214}
215
216impl<'a> CharIndicesUtf16<'a> {
217    pub(crate) fn new(s: &'a [u16]) -> Self {
218        Self {
219            forward_offset: 0,
220            back_offset: s.len(),
221            iter: CharsUtf16::new(s),
222        }
223    }
224
225    /// Returns the position of the next character, or the length of the underlying string if
226    /// there are no more characters.
227    #[inline]
228    pub fn offset(&self) -> usize {
229        self.forward_offset
230    }
231}
232
233impl Iterator for CharIndicesUtf16<'_> {
234    type Item = (usize, Result<char, DecodeUtf16Error>);
235
236    fn next(&mut self) -> Option<Self::Item> {
237        match self.iter.next() {
238            Some(Ok(c)) => {
239                let idx = self.forward_offset;
240                self.forward_offset += c.len_utf16();
241                Some((idx, Ok(c)))
242            }
243            Some(Err(e)) => {
244                let idx = self.forward_offset;
245                self.forward_offset += 1;
246                Some((idx, Err(e)))
247            }
248            None => None,
249        }
250    }
251
252    #[inline]
253    fn size_hint(&self) -> (usize, Option<usize>) {
254        self.iter.size_hint()
255    }
256}
257
258impl FusedIterator for CharIndicesUtf16<'_> {}
259
260impl DoubleEndedIterator for CharIndicesUtf16<'_> {
261    #[inline]
262    fn next_back(&mut self) -> Option<Self::Item> {
263        match self.iter.next_back() {
264            Some(Ok(c)) => {
265                self.back_offset -= c.len_utf16();
266                Some((self.back_offset, Ok(c)))
267            }
268            Some(Err(e)) => {
269                self.back_offset -= 1;
270                Some((self.back_offset, Err(e)))
271            }
272            None => None,
273        }
274    }
275}
276
277/// An iterator over the decoded [`char`][prim@char]s of a string slice, and their positions.
278///
279/// This struct is created by the `char_indices` method on strings. See its documentation for
280/// more.
281#[derive(Debug, Clone)]
282pub struct CharIndicesUtf32<'a> {
283    forward_offset: usize,
284    back_offset: usize,
285    iter: CharsUtf32<'a>,
286}
287
288impl<'a> CharIndicesUtf32<'a> {
289    pub(crate) fn new(s: &'a [u32]) -> Self {
290        Self {
291            forward_offset: 0,
292            back_offset: s.len(),
293            iter: CharsUtf32::new(s),
294        }
295    }
296
297    /// Returns the position of the next character, or the length of the underlying string if
298    /// there are no more characters.
299    #[inline]
300    pub fn offset(&self) -> usize {
301        self.forward_offset
302    }
303}
304
305impl Iterator for CharIndicesUtf32<'_> {
306    type Item = (usize, Result<char, DecodeUtf32Error>);
307
308    fn next(&mut self) -> Option<Self::Item> {
309        match self.iter.next() {
310            Some(Ok(c)) => {
311                let idx = self.forward_offset;
312                self.forward_offset += 1;
313                Some((idx, Ok(c)))
314            }
315            Some(Err(e)) => {
316                let idx = self.forward_offset;
317                self.forward_offset += 1;
318                Some((idx, Err(e)))
319            }
320            None => None,
321        }
322    }
323
324    #[inline]
325    fn size_hint(&self) -> (usize, Option<usize>) {
326        self.iter.size_hint()
327    }
328}
329
330impl FusedIterator for CharIndicesUtf32<'_> {}
331
332impl DoubleEndedIterator for CharIndicesUtf32<'_> {
333    #[inline]
334    fn next_back(&mut self) -> Option<Self::Item> {
335        match self.iter.next_back() {
336            Some(Ok(c)) => {
337                self.back_offset -= 1;
338                Some((self.back_offset, Ok(c)))
339            }
340            Some(Err(e)) => {
341                self.back_offset -= 1;
342                Some((self.back_offset, Err(e)))
343            }
344            None => None,
345        }
346    }
347}
348
349impl ExactSizeIterator for CharIndicesUtf32<'_> {
350    #[inline]
351    fn len(&self) -> usize {
352        self.iter.len()
353    }
354}
355
356/// A lossy iterator over the [`char`][prim@char]s of a string slice, and their positions.
357///
358/// This struct is created by the `char_indices_lossy` method on strings. See its documentation
359/// for more.
360#[derive(Debug, Clone)]
361pub struct CharIndicesLossyUtf16<'a> {
362    forward_offset: usize,
363    back_offset: usize,
364    iter: CharsLossyUtf16<'a>,
365}
366
367impl<'a> CharIndicesLossyUtf16<'a> {
368    pub(crate) fn new(s: &'a [u16]) -> Self {
369        Self {
370            forward_offset: 0,
371            back_offset: s.len(),
372            iter: CharsLossyUtf16::new(s),
373        }
374    }
375
376    /// Returns the position of the next character, or the length of the underlying string if
377    /// there are no more characters.
378    #[inline]
379    pub fn offset(&self) -> usize {
380        self.forward_offset
381    }
382}
383
384impl Iterator for CharIndicesLossyUtf16<'_> {
385    type Item = (usize, char);
386
387    #[inline]
388    fn next(&mut self) -> Option<Self::Item> {
389        match self.iter.next() {
390            Some(c) => {
391                let idx = self.forward_offset;
392                self.forward_offset += c.len_utf16();
393                Some((idx, c))
394            }
395            None => None,
396        }
397    }
398
399    #[inline]
400    fn size_hint(&self) -> (usize, Option<usize>) {
401        self.iter.size_hint()
402    }
403}
404
405impl FusedIterator for CharIndicesLossyUtf16<'_> {}
406
407impl DoubleEndedIterator for CharIndicesLossyUtf16<'_> {
408    #[inline]
409    fn next_back(&mut self) -> Option<Self::Item> {
410        match self.iter.next_back() {
411            Some(c) => {
412                self.back_offset -= c.len_utf16();
413                Some((self.back_offset, c))
414            }
415            None => None,
416        }
417    }
418}
419
420/// A lossy iterator over the [`char`][prim@char]s of a string slice, and their positions.
421///
422/// This struct is created by the `char_indices_lossy` method on strings. See its documentation
423/// for more.
424#[derive(Debug, Clone)]
425pub struct CharIndicesLossyUtf32<'a> {
426    forward_offset: usize,
427    back_offset: usize,
428    iter: CharsLossyUtf32<'a>,
429}
430
431impl<'a> CharIndicesLossyUtf32<'a> {
432    pub(crate) fn new(s: &'a [u32]) -> Self {
433        Self {
434            forward_offset: 0,
435            back_offset: s.len(),
436            iter: CharsLossyUtf32::new(s),
437        }
438    }
439
440    /// Returns the position of the next character, or the length of the underlying string if
441    /// there are no more characters.
442    #[inline]
443    pub fn offset(&self) -> usize {
444        self.forward_offset
445    }
446}
447
448impl Iterator for CharIndicesLossyUtf32<'_> {
449    type Item = (usize, char);
450
451    #[inline]
452    fn next(&mut self) -> Option<Self::Item> {
453        match self.iter.next() {
454            Some(c) => {
455                let idx = self.forward_offset;
456                self.forward_offset += 1;
457                Some((idx, c))
458            }
459            None => None,
460        }
461    }
462
463    #[inline]
464    fn size_hint(&self) -> (usize, Option<usize>) {
465        self.iter.size_hint()
466    }
467}
468
469impl FusedIterator for CharIndicesLossyUtf32<'_> {}
470
471impl DoubleEndedIterator for CharIndicesLossyUtf32<'_> {
472    #[inline]
473    fn next_back(&mut self) -> Option<Self::Item> {
474        match self.iter.next_back() {
475            Some(c) => {
476                self.back_offset -= 1;
477                Some((self.back_offset, c))
478            }
479            None => None,
480        }
481    }
482}
483
484impl ExactSizeIterator for CharIndicesLossyUtf32<'_> {
485    #[inline]
486    fn len(&self) -> usize {
487        self.iter.len()
488    }
489}