Skip to main content

non_empty_slice/
iter.rs

1//! Various non-empty iterators over non-empty vectors and slices.
2
3cfg_select! {
4    feature = "std" => {
5        use std::vec::IntoIter;
6    }
7    feature = "alloc" => {
8        use alloc::vec::IntoIter;
9    }
10    _ => {}
11}
12
13use core::{
14    fmt,
15    iter::Map,
16    slice::{self as regular, Iter, IterMut},
17};
18
19use non_zero_size::Size;
20
21use non_empty_iter::{NonEmptyAdapter, NonEmptyIterator};
22
23use crate::slice::{NonEmptyBytes, NonEmptySlice};
24
25/// Represents non-empty by-value iterators.
26#[cfg(any(feature = "std", feature = "alloc"))]
27pub type IntoNonEmptyIter<T> = NonEmptyAdapter<IntoIter<T>>;
28
29/// Represents non-empty by-reference iterators.
30pub type NonEmptyIter<'a, T> = NonEmptyAdapter<Iter<'a, T>>;
31
32/// Represents non-empty by-mutable-reference iterators.
33pub type NonEmptyIterMut<'a, T> = NonEmptyAdapter<IterMut<'a, T>>;
34
35/// Represents functions mapping chunks to non-empty slices.
36///
37/// This is mostly an implementation detail, though it can be useful in case
38/// one needs to name the type of the iterator explicitly.
39pub type NonEmptySliceFn<'a, T> = fn(&'a [T]) -> &'a NonEmptySlice<T>;
40
41/// Represents functions mapping mutable chunks to non-empty mutable slices.
42///
43/// This is mostly an implementation detail, though it can be useful in case
44/// one needs to name the type of the iterator explicitly.
45pub type NonEmptyMutSliceFn<'a, T> = fn(&'a mut [T]) -> &'a mut NonEmptySlice<T>;
46
47/// Represents non-empty iterators over non-empty slices in (non-overlapping) chunks,
48/// starting at the beginning of the non-empty slice.
49///
50/// This `struct` is created by the [`chunks`] method on [`NonEmptySlice<T>`].
51///
52/// [`chunks`]: NonEmptySlice::chunks
53#[derive(Debug)]
54pub struct Chunks<'a, T> {
55    slice: &'a NonEmptySlice<T>,
56    size: Size,
57}
58
59impl<'a, T> Chunks<'a, T> {
60    /// Constructs [`Self`].
61    pub const fn new(slice: &'a NonEmptySlice<T>, size: Size) -> Self {
62        Self { slice, size }
63    }
64}
65
66impl<'a, T> IntoIterator for Chunks<'a, T> {
67    type Item = &'a NonEmptySlice<T>;
68
69    type IntoIter = Map<regular::Chunks<'a, T>, NonEmptySliceFn<'a, T>>;
70
71    fn into_iter(self) -> Self::IntoIter {
72        self.slice
73            .as_slice()
74            .chunks(self.size.get())
75            // SAFETY: chunks are never empty
76            .map(|chunk| unsafe { NonEmptySlice::from_slice_unchecked(chunk) })
77    }
78}
79
80unsafe impl<T> NonEmptyIterator for Chunks<'_, T> {}
81
82/// Represents non-empty iterators over non-empty slices in (non-overlapping) mutable chunks,
83/// starting at the beginning of the non-empty slice.
84///
85/// This `struct` is created by the [`chunks_mut`] method on [`NonEmptySlice<T>`].
86///
87/// [`chunks_mut`]: NonEmptySlice::chunks_mut
88#[derive(Debug)]
89pub struct ChunksMut<'a, T> {
90    slice: &'a mut NonEmptySlice<T>,
91    size: Size,
92}
93
94impl<'a, T> ChunksMut<'a, T> {
95    /// Constructs [`Self`].
96    pub const fn new(slice: &'a mut NonEmptySlice<T>, size: Size) -> Self {
97        Self { slice, size }
98    }
99}
100
101impl<'a, T> IntoIterator for ChunksMut<'a, T> {
102    type Item = &'a mut NonEmptySlice<T>;
103
104    type IntoIter = Map<regular::ChunksMut<'a, T>, NonEmptyMutSliceFn<'a, T>>;
105
106    fn into_iter(self) -> Self::IntoIter {
107        self.slice
108            .as_mut_slice()
109            .chunks_mut(self.size.get())
110            // SAFETY: chunks are never empty
111            .map(|chunk| unsafe { NonEmptySlice::from_mut_slice_unchecked(chunk) })
112    }
113}
114
115unsafe impl<T> NonEmptyIterator for ChunksMut<'_, T> {}
116
117/// Represents non-empty iterators over non-empty slices in (non-overlapping) chunks,
118/// starting at the end of the non-empty slice.
119///
120/// This `struct` is created by the [`rchunks`] method on [`NonEmptySlice<T>`].
121///
122/// [`rchunks`]: NonEmptySlice::rchunks
123#[derive(Debug)]
124pub struct RChunks<'a, T> {
125    slice: &'a NonEmptySlice<T>,
126    size: Size,
127}
128
129impl<'a, T> RChunks<'a, T> {
130    /// Constructs [`Self`].
131    pub const fn new(slice: &'a NonEmptySlice<T>, size: Size) -> Self {
132        Self { slice, size }
133    }
134}
135
136unsafe impl<T> NonEmptyIterator for RChunks<'_, T> {}
137
138impl<'a, T> IntoIterator for RChunks<'a, T> {
139    type Item = &'a NonEmptySlice<T>;
140
141    type IntoIter = Map<regular::RChunks<'a, T>, NonEmptySliceFn<'a, T>>;
142
143    fn into_iter(self) -> Self::IntoIter {
144        self.slice
145            .as_slice()
146            .rchunks(self.size.get())
147            // SAFETY: chunks are never empty
148            .map(|chunk| unsafe { NonEmptySlice::from_slice_unchecked(chunk) })
149    }
150}
151
152/// Represents non-empty iterators over non-empty slices in (non-overlapping) mutable chunks,
153/// starting at the end of the non-empty slice.
154///
155/// This `struct` is created by the [`rchunks_mut`] method on [`NonEmptySlice<T>`].
156///
157/// [`rchunks_mut`]: NonEmptySlice::rchunks_mut
158#[derive(Debug)]
159pub struct RChunksMut<'a, T> {
160    slice: &'a mut NonEmptySlice<T>,
161    size: Size,
162}
163
164impl<'a, T> RChunksMut<'a, T> {
165    /// Constructs [`Self`].
166    pub const fn new(slice: &'a mut NonEmptySlice<T>, size: Size) -> Self {
167        Self { slice, size }
168    }
169}
170
171impl<'a, T> IntoIterator for RChunksMut<'a, T> {
172    type Item = &'a mut NonEmptySlice<T>;
173
174    type IntoIter = Map<regular::RChunksMut<'a, T>, NonEmptyMutSliceFn<'a, T>>;
175
176    fn into_iter(self) -> Self::IntoIter {
177        self.slice
178            .as_mut_slice()
179            .rchunks_mut(self.size.get())
180            // SAFETY: chunks are never empty
181            .map(|chunk| unsafe { NonEmptySlice::from_mut_slice_unchecked(chunk) })
182    }
183}
184
185unsafe impl<T> NonEmptyIterator for RChunksMut<'_, T> {}
186
187/// Represents non-empty iterators over non-empty slices in (non-overlapping) chunks,
188/// starting at the beginning of the non-empty slice.
189///
190/// When the length of the non-empty slice is not divisible by the chunk size,
191/// the last chunk will be omitted.
192///
193/// This `struct` is created by the [`chunks_exact`] method on [`NonEmptySlice<T>`].
194///
195/// [`chunks_exact`]: NonEmptySlice::chunks_exact
196#[derive(Debug)]
197pub struct ChunksExact<'a, T> {
198    slice: &'a NonEmptySlice<T>,
199    size: Size,
200}
201
202impl<'a, T> ChunksExact<'a, T> {
203    /// Constructs [`Self`].
204    pub const fn new(slice: &'a NonEmptySlice<T>, size: Size) -> Self {
205        Self { slice, size }
206    }
207}
208
209impl<'a, T> IntoIterator for ChunksExact<'a, T> {
210    type Item = &'a NonEmptySlice<T>;
211
212    type IntoIter = Map<regular::ChunksExact<'a, T>, NonEmptySliceFn<'a, T>>;
213
214    fn into_iter(self) -> Self::IntoIter {
215        self.slice
216            .as_slice()
217            .chunks_exact(self.size.get())
218            // SAFETY: chunks are never empty
219            .map(|chunk| unsafe { NonEmptySlice::from_slice_unchecked(chunk) })
220    }
221}
222
223unsafe impl<T> NonEmptyIterator for ChunksExact<'_, T> {}
224
225/// Represents non-empty iterators over non-empty slices in (non-overlapping) mutable chunks,
226/// starting at the beginning of the non-empty slice.
227///
228/// When the length of the non-empty slice is not divisible by the chunk size,
229/// the last chunk will be omitted.
230///
231/// This `struct` is created by the [`chunks_exact_mut`] method on [`NonEmptySlice<T>`].
232///
233/// [`chunks_exact_mut`]: NonEmptySlice::chunks_exact_mut
234#[derive(Debug)]
235pub struct ChunksExactMut<'a, T> {
236    slice: &'a mut NonEmptySlice<T>,
237    size: Size,
238}
239
240impl<'a, T> ChunksExactMut<'a, T> {
241    /// Constructs [`Self`].
242    pub const fn new(slice: &'a mut NonEmptySlice<T>, size: Size) -> Self {
243        Self { slice, size }
244    }
245}
246
247impl<'a, T> IntoIterator for ChunksExactMut<'a, T> {
248    type Item = &'a mut NonEmptySlice<T>;
249
250    type IntoIter = Map<regular::ChunksExactMut<'a, T>, NonEmptyMutSliceFn<'a, T>>;
251
252    fn into_iter(self) -> Self::IntoIter {
253        self.slice
254            .as_mut_slice()
255            .chunks_exact_mut(self.size.get())
256            // SAFETY: chunks are never empty
257            .map(|chunk| unsafe { NonEmptySlice::from_mut_slice_unchecked(chunk) })
258    }
259}
260
261unsafe impl<T> NonEmptyIterator for ChunksExactMut<'_, T> {}
262
263/// Represents non-empty iterators over non-empty slices in (non-overlapping) chunks,
264/// starting at the end of the non-empty slice.
265///
266/// When the length of the non-empty slice is not divisible by the chunk size,
267/// the last chunk will be omitted.
268///
269/// This `struct` is created by the [`rchunks_exact`] method on [`NonEmptySlice<T>`].
270///
271/// [`rchunks_exact`]: NonEmptySlice::rchunks_exact
272#[derive(Debug)]
273pub struct RChunksExact<'a, T> {
274    slice: &'a NonEmptySlice<T>,
275    size: Size,
276}
277
278impl<'a, T> RChunksExact<'a, T> {
279    /// Constructs [`Self`].
280    pub const fn new(slice: &'a NonEmptySlice<T>, size: Size) -> Self {
281        Self { slice, size }
282    }
283}
284
285impl<'a, T> IntoIterator for RChunksExact<'a, T> {
286    type Item = &'a NonEmptySlice<T>;
287
288    type IntoIter = Map<regular::RChunksExact<'a, T>, NonEmptySliceFn<'a, T>>;
289
290    fn into_iter(self) -> Self::IntoIter {
291        self.slice
292            .as_slice()
293            .rchunks_exact(self.size.get())
294            // SAFETY: chunks are never empty
295            .map(|chunk| unsafe { NonEmptySlice::from_slice_unchecked(chunk) })
296    }
297}
298
299unsafe impl<T> NonEmptyIterator for RChunksExact<'_, T> {}
300
301/// Represents non-empty iterators over non-empty slices in (non-overlapping) mutable chunks,
302/// starting at the end of the non-empty slice.
303///
304/// When the length of the non-empty slice is not divisible by the chunk size,
305/// the last chunk will be omitted.
306///
307/// This `struct` is created by the [`rchunks_exact_mut`] method on [`NonEmptySlice<T>`].
308///
309/// [`rchunks_exact_mut`]: NonEmptySlice::rchunks_exact_mut
310#[derive(Debug)]
311pub struct RChunksExactMut<'a, T> {
312    slice: &'a mut NonEmptySlice<T>,
313    size: Size,
314}
315
316impl<'a, T> RChunksExactMut<'a, T> {
317    /// Constructs [`Self`].
318    pub const fn new(slice: &'a mut NonEmptySlice<T>, size: Size) -> Self {
319        Self { slice, size }
320    }
321}
322
323impl<'a, T> IntoIterator for RChunksExactMut<'a, T> {
324    type Item = &'a mut NonEmptySlice<T>;
325
326    type IntoIter = Map<regular::RChunksExactMut<'a, T>, NonEmptyMutSliceFn<'a, T>>;
327
328    fn into_iter(self) -> Self::IntoIter {
329        self.slice
330            .as_mut_slice()
331            .rchunks_exact_mut(self.size.get())
332            // SAFETY: chunks are never empty
333            .map(|chunk| unsafe { NonEmptySlice::from_mut_slice_unchecked(chunk) })
334    }
335}
336
337unsafe impl<T> NonEmptyIterator for RChunksExactMut<'_, T> {}
338
339/// Represents non-empty iterators over non-empty slices in (overlapping) windows.
340///
341/// This `struct` is created by the [`windows`] method on [`NonEmptySlice<T>`].
342///
343/// [`windows`]: NonEmptySlice::windows
344#[derive(Debug)]
345pub struct Windows<'a, T> {
346    slice: &'a NonEmptySlice<T>,
347    size: Size,
348}
349
350impl<'a, T> Windows<'a, T> {
351    /// Constructs [`Self`].
352    pub const fn new(slice: &'a NonEmptySlice<T>, size: Size) -> Self {
353        Self { slice, size }
354    }
355}
356
357impl<'a, T> IntoIterator for Windows<'a, T> {
358    type Item = &'a NonEmptySlice<T>;
359
360    type IntoIter = Map<regular::Windows<'a, T>, NonEmptySliceFn<'a, T>>;
361
362    fn into_iter(self) -> Self::IntoIter {
363        self.slice
364            .as_slice()
365            .windows(self.size.get())
366            // SAFETY: windows are never empty
367            .map(|window| unsafe { NonEmptySlice::from_slice_unchecked(window) })
368    }
369}
370
371unsafe impl<T> NonEmptyIterator for Windows<'_, T> {}
372
373/// Represents non-empty iterators over non-empty slices in (non-overlapping) chunks,
374/// separated by the given predicate.
375///
376/// This `struct` is created by the [`chunk_by`] method on [`NonEmptySlice<T>`].
377///
378/// [`chunk_by`]: NonEmptySlice::chunk_by
379pub struct ChunkBy<'a, T, P: FnMut(&T, &T) -> bool> {
380    slice: &'a NonEmptySlice<T>,
381    predicate: P,
382}
383
384impl<T: fmt::Debug, P: FnMut(&T, &T) -> bool> fmt::Debug for ChunkBy<'_, T, P> {
385    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
386        formatter
387            .debug_struct(stringify!(ChunkBy))
388            .field(stringify!(slice), &self.slice)
389            .finish()
390    }
391}
392
393impl<'a, T, P: FnMut(&T, &T) -> bool> ChunkBy<'a, T, P> {
394    /// Constructs [`Self`].
395    pub const fn new(slice: &'a NonEmptySlice<T>, predicate: P) -> Self {
396        Self { slice, predicate }
397    }
398}
399
400impl<'a, T, P: FnMut(&T, &T) -> bool> IntoIterator for ChunkBy<'a, T, P> {
401    type Item = &'a NonEmptySlice<T>;
402
403    type IntoIter = Map<regular::ChunkBy<'a, T, P>, NonEmptySliceFn<'a, T>>;
404
405    fn into_iter(self) -> Self::IntoIter {
406        self.slice
407            .as_slice()
408            .chunk_by(self.predicate)
409            // SAFETY: chunks are never empty
410            .map(|chunk| unsafe { NonEmptySlice::from_slice_unchecked(chunk) })
411    }
412}
413
414unsafe impl<T, P: FnMut(&T, &T) -> bool> NonEmptyIterator for ChunkBy<'_, T, P> {}
415
416/// Represents non-empty iterators over non-empty slices in (non-overlapping) mutable chunks,
417/// separated by the given predicate.
418///
419/// This `struct` is created by the [`chunk_by_mut`] method on [`NonEmptySlice<T>`].
420///
421/// [`chunk_by_mut`]: NonEmptySlice::chunk_by_mut
422pub struct ChunkByMut<'a, T, P: FnMut(&T, &T) -> bool> {
423    slice: &'a mut NonEmptySlice<T>,
424    predicate: P,
425}
426
427impl<T: fmt::Debug, P: FnMut(&T, &T) -> bool> fmt::Debug for ChunkByMut<'_, T, P> {
428    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
429        formatter
430            .debug_struct(stringify!(ChunkByMut))
431            .field(stringify!(slice), &self.slice)
432            .finish()
433    }
434}
435
436impl<'a, T, P: FnMut(&T, &T) -> bool> ChunkByMut<'a, T, P> {
437    /// Constructs [`Self`].
438    pub const fn new(slice: &'a mut NonEmptySlice<T>, predicate: P) -> Self {
439        Self { slice, predicate }
440    }
441}
442
443impl<'a, T, P: FnMut(&T, &T) -> bool> IntoIterator for ChunkByMut<'a, T, P> {
444    type Item = &'a mut NonEmptySlice<T>;
445
446    type IntoIter = Map<regular::ChunkByMut<'a, T, P>, NonEmptyMutSliceFn<'a, T>>;
447
448    fn into_iter(self) -> Self::IntoIter {
449        self.slice
450            .as_mut_slice()
451            .chunk_by_mut(self.predicate)
452            // SAFETY: chunks are never empty
453            .map(|chunk| unsafe { NonEmptySlice::from_mut_slice_unchecked(chunk) })
454    }
455}
456
457unsafe impl<T, P: FnMut(&T, &T) -> bool> NonEmptyIterator for ChunkByMut<'_, T, P> {}
458
459/// Represents non-empty iterators that produce escaped versions of provided slices,
460/// treating them as ASCII strings.
461///
462/// This `struct` is created by the [`escape_ascii`] method on [`NonEmptyBytes`].
463///
464/// [`escape_ascii`]: NonEmptyBytes::escape_ascii
465#[derive(Debug)]
466pub struct EscapeAscii<'a> {
467    bytes: &'a NonEmptyBytes,
468}
469
470impl<'a> EscapeAscii<'a> {
471    /// Constructs [`Self`].
472    #[must_use]
473    pub const fn new(bytes: &'a NonEmptyBytes) -> Self {
474        Self { bytes }
475    }
476}
477
478impl<'a> IntoIterator for EscapeAscii<'a> {
479    type Item = u8;
480
481    type IntoIter = regular::EscapeAscii<'a>;
482
483    fn into_iter(self) -> Self::IntoIter {
484        self.bytes.as_slice().escape_ascii()
485    }
486}
487
488unsafe impl NonEmptyIterator for EscapeAscii<'_> {}