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
19impl<'a, A, const N: usize> Iterator for Iter<'a, A, N> {
20    type Item = &'a A;
21
22    fn next(&mut self) -> Option<Self::Item> {
23        if self.remaining == 0 {
24            None
25        } else {
26            self.remaining -= 1;
27            Some(unsafe { &*self.buffer.ptr(self.left_index.inc()) })
28        }
29    }
30
31    #[inline]
32    #[must_use]
33    fn size_hint(&self) -> (usize, Option<usize>) {
34        (self.remaining, Some(self.remaining))
35    }
36}
37
38impl<'a, A, const N: usize> DoubleEndedIterator for Iter<'a, A, N> {
39    fn next_back(&mut self) -> Option<Self::Item> {
40        if self.remaining == 0 {
41            None
42        } else {
43            self.remaining -= 1;
44            Some(unsafe { &*self.buffer.ptr(self.right_index.dec()) })
45        }
46    }
47}
48
49impl<'a, A, const N: usize> ExactSizeIterator for Iter<'a, A, N> {}
50
51impl<'a, A, const N: usize> FusedIterator for Iter<'a, A, N> {}
52
53/// A mutable reference iterator over a `RingBuffer`.
54pub struct IterMut<'a, A, const N: usize> {
55    data: *mut A,
56    left_index: RawIndex<N>,
57    right_index: RawIndex<N>,
58    remaining: usize,
59    phantom: PhantomData<&'a ()>,
60}
61
62impl<'a, A, const N: usize> IterMut<'a, A, N>
63where
64    A: 'a,
65{
66    pub(crate) fn new(buffer: &mut RingBuffer<A, N>) -> Self {
67        Self::new_slice(buffer, buffer.origin, buffer.len())
68    }
69
70    pub(crate) fn new_slice(
71        buffer: &mut RingBuffer<A, N>,
72        origin: RawIndex<N>,
73        len: usize,
74    ) -> Self {
75        Self {
76            left_index: origin,
77            right_index: origin + len,
78            remaining: len,
79            phantom: PhantomData,
80            data: buffer.data.as_mut_ptr().cast(),
81        }
82    }
83
84    unsafe fn mut_ptr(&mut self, index: RawIndex<N>) -> *mut A {
85        self.data.add(index.to_usize())
86    }
87}
88
89impl<'a, A, const N: usize> Iterator for IterMut<'a, A, N>
90where
91    A: 'a,
92{
93    type Item = &'a mut A;
94
95    fn next(&mut self) -> Option<Self::Item> {
96        if self.remaining == 0 {
97            None
98        } else {
99            self.remaining -= 1;
100            let index = self.left_index.inc();
101            Some(unsafe { &mut *self.mut_ptr(index) })
102        }
103    }
104
105    #[inline]
106    #[must_use]
107    fn size_hint(&self) -> (usize, Option<usize>) {
108        (self.remaining, Some(self.remaining))
109    }
110}
111
112impl<'a, A, const N: usize> DoubleEndedIterator for IterMut<'a, A, N>
113where
114    A: 'a,
115{
116    fn next_back(&mut self) -> Option<Self::Item> {
117        if self.remaining == 0 {
118            None
119        } else {
120            self.remaining -= 1;
121            let index = self.right_index.dec();
122            Some(unsafe { &mut *self.mut_ptr(index) })
123        }
124    }
125}
126
127impl<'a, A, const N: usize> ExactSizeIterator for IterMut<'a, A, N> where A: 'a {}
128
129impl<'a, A, const N: usize> FusedIterator for IterMut<'a, A, N> where A: 'a {}
130
131/// A draining iterator over a `RingBuffer`.
132pub struct Drain<'a, A, const N: usize> {
133    pub(crate) buffer: &'a mut RingBuffer<A, N>,
134}
135
136impl<'a, A: 'a, const N: usize> Iterator for Drain<'a, A, N> {
137    type Item = A;
138
139    #[inline]
140    fn next(&mut self) -> Option<Self::Item> {
141        self.buffer.pop_front()
142    }
143
144    #[inline]
145    #[must_use]
146    fn size_hint(&self) -> (usize, Option<usize>) {
147        (self.buffer.len(), Some(self.buffer.len()))
148    }
149}
150
151impl<'a, A: 'a, const N: usize> DoubleEndedIterator for Drain<'a, A, N> {
152    #[inline]
153    fn next_back(&mut self) -> Option<Self::Item> {
154        self.buffer.pop_back()
155    }
156}
157
158impl<'a, A: 'a, const N: usize> ExactSizeIterator for Drain<'a, A, N> {}
159
160impl<'a, A: 'a, const N: usize> FusedIterator for Drain<'a, A, N> {}
161
162/// A consuming iterator over a `RingBuffer`.
163pub struct OwnedIter<A, const N: usize> {
164    pub(crate) buffer: RingBuffer<A, N>,
165}
166
167impl<A, const N: usize> Iterator for OwnedIter<A, N> {
168    type Item = A;
169
170    #[inline]
171    fn next(&mut self) -> Option<Self::Item> {
172        self.buffer.pop_front()
173    }
174
175    #[inline]
176    #[must_use]
177    fn size_hint(&self) -> (usize, Option<usize>) {
178        (self.buffer.len(), Some(self.buffer.len()))
179    }
180}
181
182impl<A, const N: usize> DoubleEndedIterator for OwnedIter<A, N> {
183    #[inline]
184    fn next_back(&mut self) -> Option<Self::Item> {
185        self.buffer.pop_back()
186    }
187}
188
189impl<A, const N: usize> ExactSizeIterator for OwnedIter<A, N> {}
190
191impl<A, const N: usize> FusedIterator for OwnedIter<A, N> {}