spinoso_string/
iter.rs

1use alloc::vec;
2use alloc::vec::Vec;
3use core::iter::FusedIterator;
4use core::slice;
5
6/// Immutable [`String`] byte slice iterator.
7///
8/// This struct is created by the [`iter`] method on a Spinoso [`String`]. See
9/// its documentation for more.
10///
11/// # Examples
12///
13/// ```
14/// # use spinoso_string::String;
15/// let s = String::utf8(b"Artichoke Ruby".to_vec());
16///
17/// let mut checksum: u32 = 0;
18/// for &byte in s.iter() {
19///     checksum += byte as u32;
20/// }
21/// assert_eq!(checksum, 1372);
22/// ```
23///
24/// [`String`]: crate::String
25/// [`iter`]: crate::String::iter
26#[derive(Debug, Clone)]
27pub struct Iter<'a>(slice::Iter<'a, u8>);
28
29impl<'a> Iter<'a> {
30    #[inline]
31    #[must_use]
32    pub(crate) fn from_slice(slice: &'a [u8]) -> Self {
33        Self(slice.iter())
34    }
35
36    /// Views the underlying data as a subslice of the original data.
37    ///
38    /// This has the same lifetime as the original slice, and so the iterator
39    /// can continue to be used while this exists.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// # use spinoso_string::String;
45    /// let s = String::utf8(b"Artichoke Ruby".to_vec());
46    ///
47    /// // Then, we get the iterator:
48    /// let mut iter = s.iter();
49    /// assert_eq!(iter.as_slice(), b"Artichoke Ruby");
50    ///
51    /// // Next, we move to the second element of the slice:
52    /// iter.next();
53    /// // Now `as_slice` returns "rtichoke Ruby":
54    /// assert_eq!(iter.as_slice(), b"rtichoke Ruby");
55    /// ```
56    #[inline]
57    #[must_use]
58    pub fn as_slice(&self) -> &'a [u8] {
59        self.0.as_slice()
60    }
61}
62
63impl<'a> AsRef<[u8]> for Iter<'a> {
64    fn as_ref(&self) -> &'a [u8] {
65        self.as_slice()
66    }
67}
68
69impl<'a> Iterator for Iter<'a> {
70    type Item = &'a u8;
71
72    #[inline]
73    fn next(&mut self) -> Option<Self::Item> {
74        self.0.next()
75    }
76
77    #[inline]
78    fn nth(&mut self, n: usize) -> Option<Self::Item> {
79        self.0.nth(n)
80    }
81
82    #[inline]
83    fn count(self) -> usize {
84        self.0.count()
85    }
86
87    #[inline]
88    fn size_hint(&self) -> (usize, Option<usize>) {
89        self.0.size_hint()
90    }
91
92    #[inline]
93    fn last(self) -> Option<Self::Item> {
94        self.0.last()
95    }
96}
97
98impl DoubleEndedIterator for Iter<'_> {
99    #[inline]
100    fn next_back(&mut self) -> Option<Self::Item> {
101        self.0.next_back()
102    }
103
104    #[inline]
105    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
106        self.0.nth_back(n)
107    }
108}
109
110impl FusedIterator for Iter<'_> {}
111
112impl ExactSizeIterator for Iter<'_> {}
113
114/// Mutable [`String`] byte iterator.
115///
116/// This struct is created by the [`iter_mut`] method on a Spinoso [`String`].
117/// See its documentation for more.
118///
119/// # Examples
120///
121/// ```
122/// # use spinoso_string::String;
123/// let mut s = String::utf8(b"Artichoke Ruby".to_vec());
124///
125/// for byte in s.iter_mut() {
126///     *byte = b'z';
127/// }
128/// assert_eq!(s, "zzzzzzzzzzzzzz");
129/// ```
130///
131/// [`String`]: crate::String
132/// [`iter_mut`]: crate::String::iter_mut
133#[derive(Debug)]
134pub struct IterMut<'a>(slice::IterMut<'a, u8>);
135
136impl<'a> IterMut<'a> {
137    #[inline]
138    #[must_use]
139    pub(crate) fn from_mut_slice(slice: &'a mut [u8]) -> Self {
140        Self(slice.iter_mut())
141    }
142
143    /// Views the underlying data as a subslice of the original data.
144    ///
145    /// To avoid creating `&mut` references that alias, this is forced to consume
146    /// the iterator.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// # use spinoso_string::String;
152    /// let mut s = String::utf8(b"Artichoke Ruby".to_vec());
153    /// {
154    ///     let mut iter = s.iter_mut();
155    ///     iter.next();
156    ///     assert_eq!(iter.into_slice(), b"rtichoke Ruby");
157    /// }
158    /// {
159    ///     let mut iter = s.iter_mut();
160    ///     *iter.next().unwrap() = b'a';
161    ///     *iter.nth(9).unwrap() = b'r';
162    /// }
163    /// assert_eq!(s, &b"artichoke ruby"[..]);
164    /// ```
165    #[inline]
166    #[must_use]
167    pub fn into_slice(self) -> &'a mut [u8] {
168        self.0.into_slice()
169    }
170}
171
172impl<'a> Iterator for IterMut<'a> {
173    type Item = &'a mut u8;
174
175    #[inline]
176    fn next(&mut self) -> Option<Self::Item> {
177        self.0.next()
178    }
179
180    #[inline]
181    fn nth(&mut self, n: usize) -> Option<Self::Item> {
182        self.0.nth(n)
183    }
184
185    #[inline]
186    fn count(self) -> usize {
187        self.0.count()
188    }
189
190    #[inline]
191    fn size_hint(&self) -> (usize, Option<usize>) {
192        self.0.size_hint()
193    }
194
195    #[inline]
196    fn last(self) -> Option<Self::Item> {
197        self.0.last()
198    }
199}
200
201impl DoubleEndedIterator for IterMut<'_> {
202    #[inline]
203    fn next_back(&mut self) -> Option<Self::Item> {
204        self.0.next_back()
205    }
206
207    #[inline]
208    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
209        self.0.nth_back(n)
210    }
211}
212
213impl FusedIterator for IterMut<'_> {}
214
215impl ExactSizeIterator for IterMut<'_> {}
216
217/// An iterator that moves out of a string.
218///
219/// This struct is created by the `into_iter` method on `String` (provided by
220/// the [`IntoIterator`] trait).
221///
222/// # Examples
223///
224/// ```
225/// use spinoso_string::String;
226///
227/// let s = String::from("hello");
228/// let iter: spinoso_string::IntoIter = s.into_iter();
229/// ```
230#[derive(Debug)]
231pub struct IntoIter(vec::IntoIter<u8>);
232
233impl IntoIter {
234    #[inline]
235    #[must_use]
236    pub(crate) fn from_vec(buf: Vec<u8>) -> Self {
237        Self(buf.into_iter())
238    }
239
240    /// Returns the remaining bytes of this iterator as a slice.
241    ///
242    /// # Examples
243    ///
244    /// ```
245    /// use spinoso_string::String;
246    ///
247    /// let s = String::from("abc");
248    /// let mut into_iter = s.into_iter();
249    /// assert_eq!(into_iter.as_slice(), &[b'a', b'b', b'c']);
250    /// let _ = into_iter.next().unwrap();
251    /// assert_eq!(into_iter.as_slice(), &[b'b', b'c']);
252    /// ```
253    #[inline]
254    #[must_use]
255    pub fn as_slice(&self) -> &[u8] {
256        self.0.as_slice()
257    }
258
259    /// Returns the remaining bytes of this iterator as a mutable slice.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// use spinoso_string::String;
265    ///
266    /// let s = String::from("abc");
267    /// let mut into_iter = s.into_iter();
268    /// assert_eq!(into_iter.as_slice(), &[b'a', b'b', b'c']);
269    /// into_iter.as_mut_slice()[2] = b'z';
270    /// assert_eq!(into_iter.next(), Some(b'a'));
271    /// assert_eq!(into_iter.next(), Some(b'b'));
272    /// assert_eq!(into_iter.next(), Some(b'z'));
273    /// assert_eq!(into_iter.next(), None);
274    /// ```
275    #[inline]
276    #[must_use]
277    pub fn as_mut_slice(&mut self) -> &mut [u8] {
278        self.0.as_mut_slice()
279    }
280}
281
282impl AsRef<[u8]> for IntoIter {
283    #[inline]
284    fn as_ref(&self) -> &[u8] {
285        self.as_slice()
286    }
287}
288
289impl Iterator for IntoIter {
290    type Item = u8;
291
292    #[inline]
293    fn next(&mut self) -> Option<Self::Item> {
294        self.0.next()
295    }
296
297    #[inline]
298    fn nth(&mut self, n: usize) -> Option<Self::Item> {
299        self.0.nth(n)
300    }
301
302    #[inline]
303    fn count(self) -> usize {
304        self.0.count()
305    }
306
307    #[inline]
308    fn size_hint(&self) -> (usize, Option<usize>) {
309        self.0.size_hint()
310    }
311
312    #[inline]
313    fn last(self) -> Option<Self::Item> {
314        self.0.last()
315    }
316}
317
318impl DoubleEndedIterator for IntoIter {
319    #[inline]
320    fn next_back(&mut self) -> Option<Self::Item> {
321        self.0.next_back()
322    }
323
324    #[inline]
325    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
326        self.0.nth_back(n)
327    }
328}
329
330impl FusedIterator for IntoIter {}
331
332impl ExactSizeIterator for IntoIter {}
333
334/// Immutable [`String`] byte iterator.
335///
336/// This struct is created by the [`bytes`] method on a Spinoso [`String`]. See
337/// its documentation for more.
338///
339/// # Examples
340///
341/// ```
342/// # use spinoso_string::String;
343/// let s = String::utf8(b"Artichoke Ruby".to_vec());
344///
345/// let mut checksum: u32 = 0;
346/// for byte in s.bytes() {
347///     checksum += byte as u32;
348/// }
349/// assert_eq!(checksum, 1372);
350/// ```
351///
352/// [`String`]: crate::String
353/// [`bytes`]: crate::String::bytes
354#[derive(Debug, Clone)]
355pub struct Bytes<'a>(slice::Iter<'a, u8>);
356
357impl<'a> From<&'a [u8]> for Bytes<'a> {
358    #[inline]
359    fn from(bytes: &'a [u8]) -> Self {
360        Self(bytes.iter())
361    }
362}
363
364impl<'a> Bytes<'a> {
365    #[inline]
366    #[must_use]
367    pub(crate) fn from_slice(slice: &'a [u8]) -> Self {
368        Self(slice.iter())
369    }
370
371    /// Views the underlying data as a subslice of the original data.
372    ///
373    /// This has the same lifetime as the original slice, and so the iterator
374    /// can continue to be used while this exists.
375    ///
376    /// # Examples
377    ///
378    /// ```
379    /// # use spinoso_string::String;
380    /// let s = String::utf8(b"Artichoke Ruby".to_vec());
381    ///
382    /// // Then, we get the iterator:
383    /// let mut iter = s.bytes();
384    /// assert_eq!(iter.as_slice(), b"Artichoke Ruby");
385    ///
386    /// // Next, we move to the second element of the slice:
387    /// iter.next();
388    /// // Now `as_slice` returns "rtichoke Ruby":
389    /// assert_eq!(iter.as_slice(), b"rtichoke Ruby");
390    /// ```
391    #[inline]
392    #[must_use]
393    pub fn as_slice(&self) -> &'a [u8] {
394        self.0.as_slice()
395    }
396}
397
398impl Iterator for Bytes<'_> {
399    type Item = u8;
400
401    #[inline]
402    fn next(&mut self) -> Option<Self::Item> {
403        self.0.next().copied()
404    }
405
406    #[inline]
407    fn nth(&mut self, n: usize) -> Option<Self::Item> {
408        self.0.nth(n).copied()
409    }
410
411    #[inline]
412    fn count(self) -> usize {
413        self.0.count()
414    }
415
416    #[inline]
417    fn size_hint(&self) -> (usize, Option<usize>) {
418        self.0.size_hint()
419    }
420
421    #[inline]
422    fn last(self) -> Option<Self::Item> {
423        self.0.last().copied()
424    }
425}
426
427impl DoubleEndedIterator for Bytes<'_> {
428    #[inline]
429    fn next_back(&mut self) -> Option<Self::Item> {
430        self.0.next_back().copied()
431    }
432
433    #[inline]
434    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
435        self.0.nth_back(n).copied()
436    }
437}
438
439impl FusedIterator for Bytes<'_> {}
440
441impl ExactSizeIterator for Bytes<'_> {}