imbl_sized_chunks/ring_buffer/
iter.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use core::iter::FusedIterator;
6use core::marker::PhantomData;
7
8use super::{index::RawIndex, RingBuffer};
9use array_ops::HasLength;
10
11/// A reference iterator over a `RingBuffer`.
12pub struct Iter<'a, A, const N: usize> {
13    pub(crate) buffer: &'a RingBuffer<A, N>,
14    pub(crate) left_index: RawIndex<N>,
15    pub(crate) right_index: RawIndex<N>,
16    pub(crate) remaining: usize,
17}
18
19// Implement Clone instead of deriving, because we want to be Clone even if A isn't.
20impl<'a, A, const N: usize> Clone for Iter<'a, A, N> {
21    fn clone(&self) -> Self {
22        Iter { ..*self }
23    }
24}
25
26impl<'a, A, const N: usize> Iterator for Iter<'a, A, N> {
27    type Item = &'a A;
28
29    fn next(&mut self) -> Option<Self::Item> {
30        if self.remaining == 0 {
31            None
32        } else {
33            self.remaining -= 1;
34            Some(unsafe { &*self.buffer.ptr(self.left_index.inc()) })
35        }
36    }
37
38    #[inline]
39    #[must_use]
40    fn size_hint(&self) -> (usize, Option<usize>) {
41        (self.remaining, Some(self.remaining))
42    }
43}
44
45impl<'a, A, const N: usize> DoubleEndedIterator for Iter<'a, A, N> {
46    fn next_back(&mut self) -> Option<Self::Item> {
47        if self.remaining == 0 {
48            None
49        } else {
50            self.remaining -= 1;
51            Some(unsafe { &*self.buffer.ptr(self.right_index.dec()) })
52        }
53    }
54}
55
56impl<'a, A, const N: usize> ExactSizeIterator for Iter<'a, A, N> {}
57
58impl<'a, A, const N: usize> FusedIterator for Iter<'a, A, N> {}
59
60/// A mutable reference iterator over a `RingBuffer`.
61pub struct IterMut<'a, A, const N: usize> {
62    data: *mut A,
63    left_index: RawIndex<N>,
64    right_index: RawIndex<N>,
65    remaining: usize,
66    phantom: PhantomData<&'a ()>,
67}
68
69impl<'a, A, const N: usize> IterMut<'a, A, N>
70where
71    A: 'a,
72{
73    pub(crate) fn new(buffer: &mut RingBuffer<A, N>) -> Self {
74        Self::new_slice(buffer, buffer.origin, buffer.len())
75    }
76
77    pub(crate) fn new_slice(
78        buffer: &mut RingBuffer<A, N>,
79        origin: RawIndex<N>,
80        len: usize,
81    ) -> Self {
82        Self {
83            left_index: origin,
84            right_index: origin + len,
85            remaining: len,
86            phantom: PhantomData,
87            data: buffer.data.as_mut_ptr().cast(),
88        }
89    }
90
91    unsafe fn mut_ptr(&mut self, index: RawIndex<N>) -> *mut A {
92        self.data.add(index.to_usize())
93    }
94}
95
96impl<'a, A, const N: usize> Iterator for IterMut<'a, A, N>
97where
98    A: 'a,
99{
100    type Item = &'a mut A;
101
102    fn next(&mut self) -> Option<Self::Item> {
103        if self.remaining == 0 {
104            None
105        } else {
106            self.remaining -= 1;
107            let index = self.left_index.inc();
108            Some(unsafe { &mut *self.mut_ptr(index) })
109        }
110    }
111
112    #[inline]
113    #[must_use]
114    fn size_hint(&self) -> (usize, Option<usize>) {
115        (self.remaining, Some(self.remaining))
116    }
117}
118
119impl<'a, A, const N: usize> DoubleEndedIterator for IterMut<'a, A, N>
120where
121    A: 'a,
122{
123    fn next_back(&mut self) -> Option<Self::Item> {
124        if self.remaining == 0 {
125            None
126        } else {
127            self.remaining -= 1;
128            let index = self.right_index.dec();
129            Some(unsafe { &mut *self.mut_ptr(index) })
130        }
131    }
132}
133
134impl<'a, A, const N: usize> ExactSizeIterator for IterMut<'a, A, N> where A: 'a {}
135
136impl<'a, A, const N: usize> FusedIterator for IterMut<'a, A, N> where A: 'a {}
137
138/// A draining iterator over a `RingBuffer`.
139pub struct Drain<'a, A, const N: usize> {
140    pub(crate) buffer: &'a mut RingBuffer<A, N>,
141}
142
143impl<'a, A: 'a, const N: usize> Iterator for Drain<'a, A, N> {
144    type Item = A;
145
146    #[inline]
147    fn next(&mut self) -> Option<Self::Item> {
148        self.buffer.pop_front()
149    }
150
151    #[inline]
152    #[must_use]
153    fn size_hint(&self) -> (usize, Option<usize>) {
154        (self.buffer.len(), Some(self.buffer.len()))
155    }
156}
157
158impl<'a, A: 'a, const N: usize> DoubleEndedIterator for Drain<'a, A, N> {
159    #[inline]
160    fn next_back(&mut self) -> Option<Self::Item> {
161        self.buffer.pop_back()
162    }
163}
164
165impl<'a, A: 'a, const N: usize> ExactSizeIterator for Drain<'a, A, N> {}
166
167impl<'a, A: 'a, const N: usize> FusedIterator for Drain<'a, A, N> {}
168
169/// A consuming iterator over a `RingBuffer`.
170pub struct OwnedIter<A, const N: usize> {
171    pub(crate) buffer: RingBuffer<A, N>,
172}
173
174impl<A, const N: usize> Iterator for OwnedIter<A, N> {
175    type Item = A;
176
177    #[inline]
178    fn next(&mut self) -> Option<Self::Item> {
179        self.buffer.pop_front()
180    }
181
182    #[inline]
183    #[must_use]
184    fn size_hint(&self) -> (usize, Option<usize>) {
185        (self.buffer.len(), Some(self.buffer.len()))
186    }
187}
188
189impl<A, const N: usize> DoubleEndedIterator for OwnedIter<A, N> {
190    #[inline]
191    fn next_back(&mut self) -> Option<Self::Item> {
192        self.buffer.pop_back()
193    }
194}
195
196impl<A, const N: usize> ExactSizeIterator for OwnedIter<A, N> {}
197
198impl<A, const N: usize> FusedIterator for OwnedIter<A, N> {}