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<'_> {}