Skip to main content

ringbuf/traits/
consumer.rs

1use super::{
2    observer::{DelegateObserver, Observer},
3    utils::{add_mod, modulus},
4};
5use crate::utils::{move_uninit_slice, slice_as_uninit_mut, slice_assume_init_mut, slice_assume_init_ref};
6use core::{
7    iter::Chain,
8    mem::{self, MaybeUninit},
9    ptr, slice,
10};
11#[cfg(feature = "std")]
12use std::io::{self, Write};
13
14/// Consumer part of ring buffer.
15pub trait Consumer: Observer {
16    /// Set read index.
17    ///
18    /// # Safety
19    ///
20    /// Index must go only forward, never backward. It is recommended to use [`Self::advance_read_index`] instead.
21    ///
22    /// All slots with index less than `value` must be uninitialized until write index, all slots with index equal or greater - must be initialized.
23    unsafe fn set_read_index(&self, value: usize);
24
25    /// Moves `read` pointer by `count` places forward.
26    ///
27    /// # Safety
28    ///
29    /// First `count` items in occupied memory must be moved out or dropped.
30    ///
31    /// Must not be called concurrently.
32    unsafe fn advance_read_index(&self, count: usize) {
33        unsafe { self.set_read_index(add_mod(self.read_index(), count, modulus(self))) };
34    }
35
36    /// Provides a direct access to the ring buffer occupied memory.
37    /// The difference from [`Self::as_slices`] is that this method provides slices of [`MaybeUninit`], so items may be moved out of slices.
38    ///
39    /// Returns a pair of slices of stored items, the second one may be empty.
40    /// Elements with lower indices in slice are older. First slice contains older items that second one.
41    ///
42    /// # Safety
43    ///
44    /// All items are initialized. Elements must be removed starting from the beginning of first slice.
45    /// When all items are removed from the first slice then items must be removed from the beginning of the second slice.
46    ///
47    /// *This method must be followed by [`Self::advance_read_index`] call with the number of items being removed previously as argument.*
48    /// *No other mutating calls allowed before that.*
49    fn occupied_slices(&self) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
50        unsafe { self.unsafe_slices(self.read_index(), self.write_index()) }
51    }
52
53    /// Provides a direct mutable access to the ring buffer occupied memory.
54    ///
55    /// Same as [`Self::occupied_slices`].
56    ///
57    /// # Safety
58    ///
59    /// When some item is replaced with uninitialized value then it must not be read anymore.
60    unsafe fn occupied_slices_mut(&mut self) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
61        unsafe { self.unsafe_slices_mut(self.read_index(), self.write_index()) }
62    }
63
64    /// Returns a pair of slices which contain, in order, the contents of the ring buffer.
65    #[inline]
66    fn as_slices(&self) -> (&[Self::Item], &[Self::Item]) {
67        unsafe {
68            let (left, right) = self.occupied_slices();
69            (slice_assume_init_ref(left), slice_assume_init_ref(right))
70        }
71    }
72
73    /// Returns a pair of mutable slices which contain, in order, the contents of the ring buffer.
74    #[inline]
75    fn as_mut_slices(&mut self) -> (&mut [Self::Item], &mut [Self::Item]) {
76        unsafe {
77            let (left, right) = self.occupied_slices_mut();
78            (slice_assume_init_mut(left), slice_assume_init_mut(right))
79        }
80    }
81
82    /// Returns a reference to the eldest item in the ring buffer, if exists.
83    #[inline]
84    fn first(&self) -> Option<&Self::Item> {
85        self.as_slices().0.first()
86    }
87    /// Returns a mutable reference to the eldest item in the ring buffer, if exists.
88    #[inline]
89    fn first_mut(&mut self) -> Option<&mut Self::Item> {
90        self.as_mut_slices().0.first_mut()
91    }
92    /// Returns a reference to the most recent item in the ring buffer, if exists.
93    ///
94    /// *Returned item may not be actually the most recent if there is a concurrent producer activity.*
95    fn last(&self) -> Option<&Self::Item> {
96        let (first, second) = self.as_slices();
97        if second.is_empty() { first.last() } else { second.last() }
98    }
99    /// Returns a mutable reference to the most recent item in the ring buffer, if exists.
100    ///
101    /// *Returned item may not be actually the most recent if there is a concurrent producer activity.*
102    fn last_mut(&mut self) -> Option<&mut Self::Item> {
103        let (first, second) = self.as_mut_slices();
104        if second.is_empty() { first.last_mut() } else { second.last_mut() }
105    }
106
107    /// Removes the eldest item from the ring buffer and returns it.
108    ///
109    /// Returns `None` if the ring buffer is empty.
110    fn try_pop(&mut self) -> Option<Self::Item> {
111        if !self.is_empty() {
112            let elem = unsafe { self.occupied_slices().0.get_unchecked(0).assume_init_read() };
113            unsafe { self.advance_read_index(1) };
114            Some(elem)
115        } else {
116            None
117        }
118    }
119
120    /// Returns the reference to the eldest item without removing it from the buffer.
121    ///
122    /// Returns `None` if the ring buffer is empty.
123    fn try_peek(&self) -> Option<&Self::Item> {
124        if !self.is_empty() {
125            Some(unsafe { self.occupied_slices().0.get_unchecked(0).assume_init_ref() })
126        } else {
127            None
128        }
129    }
130
131    /// Copies items from the ring buffer to an uninit slice without removing them from the ring buffer.
132    ///
133    /// Returns a number of items being copied.
134    fn peek_slice_uninit(&self, elems: &mut [MaybeUninit<Self::Item>]) -> usize {
135        let (left, right) = self.occupied_slices();
136        if elems.len() < left.len() {
137            move_uninit_slice(elems, unsafe { left.get_unchecked(..elems.len()) });
138            elems.len()
139        } else {
140            let (left_elems, elems) = elems.split_at_mut(left.len());
141            move_uninit_slice(left_elems, left);
142            left.len()
143                + if elems.len() < right.len() {
144                    move_uninit_slice(elems, unsafe { right.get_unchecked(..elems.len()) });
145                    elems.len()
146                } else {
147                    move_uninit_slice(unsafe { elems.get_unchecked_mut(..right.len()) }, right);
148                    right.len()
149                }
150        }
151    }
152
153    /// Copies items from the ring buffer to a slice without removing them from the ring buffer.
154    ///
155    /// Returns a number of items being copied.
156    fn peek_slice(&self, elems: &mut [Self::Item]) -> usize
157    where
158        Self::Item: Copy,
159    {
160        self.peek_slice_uninit(unsafe { slice_as_uninit_mut(elems) })
161    }
162
163    /// Removes items from the ring buffer and writes them into an uninit slice.
164    ///
165    /// Returns count of items been removed.
166    fn pop_slice_uninit(&mut self, elems: &mut [MaybeUninit<Self::Item>]) -> usize {
167        let count = self.peek_slice_uninit(elems);
168        unsafe { self.advance_read_index(count) };
169        count
170    }
171
172    /// Removes items from the ring buffer and writes them into a slice.
173    ///
174    /// Returns count of items been removed.
175    fn pop_slice(&mut self, elems: &mut [Self::Item]) -> usize
176    where
177        Self::Item: Copy,
178    {
179        self.pop_slice_uninit(unsafe { slice_as_uninit_mut(elems) })
180    }
181
182    /// Returns an iterator that removes items one by one from the ring buffer.
183    fn pop_iter(&mut self) -> PopIter<'_, Self> {
184        PopIter::new(self)
185    }
186
187    /// Returns a front-to-back iterator containing references to items in the ring buffer.
188    ///
189    /// This iterator does not remove items out of the ring buffer.
190    fn iter(&self) -> Iter<'_, Self> {
191        let (left, right) = self.as_slices();
192        left.iter().chain(right.iter())
193    }
194
195    /// Returns a front-to-back iterator that returns mutable references to items in the ring buffer.
196    ///
197    /// This iterator does not remove items out of the ring buffer.
198    fn iter_mut(&mut self) -> IterMut<'_, Self> {
199        let (left, right) = self.as_mut_slices();
200        left.iter_mut().chain(right.iter_mut())
201    }
202
203    /// Removes and drops at most `count` items, returning the number removed.
204    ///
205    /// Without concurrent producer activity, removes exactly `min(count, self.occupied_len())` items,
206    /// where the length is measured before removal. Items inserted after the occupied range is read are left in the buffer.
207    ///
208    /// Takes constant time for item types for which [`core::mem::needs_drop`] returns false.
209    /// Otherwise, removed items are dropped in order and their slots remain occupied until destruction finishes.
210    /// If a destructor panics, that item and earlier items are removed; later items remain in the buffer.
211    ///
212    /// ```
213    /// # extern crate ringbuf;
214    /// # use ringbuf::{LocalRb, storage::Array, traits::*};
215    /// # fn main() {
216    /// let mut rb = LocalRb::<Array<i32, 8>>::default();
217    ///
218    /// assert_eq!(rb.push_iter(0..8), 8);
219    ///
220    /// assert_eq!(rb.skip(4), 4);
221    /// assert_eq!(rb.skip(8), 4);
222    /// assert_eq!(rb.skip(4), 0);
223    /// # }
224    /// ```
225    fn skip(&mut self, count: usize) -> usize {
226        if !mem::needs_drop::<Self::Item>() {
227            // No destructor can run or unwind, so release all slots at once
228            // instead of visiting each item.
229            let count = usize::min(count, self.occupied_len());
230            unsafe { self.advance_read_index(count) };
231            return count;
232        }
233
234        struct Guard<'a, C: Consumer + ?Sized> {
235            consumer: &'a mut C,
236            count: usize,
237        }
238        impl<C: Consumer + ?Sized> Drop for Guard<'_, C> {
239            fn drop(&mut self) {
240                // The slice iterator and any panicking item destructor have
241                // finished before this guard publishes the freed slots.
242                unsafe { self.consumer.advance_read_index(self.count) };
243            }
244        }
245
246        let mut guard = Guard { consumer: self, count: 0 };
247        let (left, right) = unsafe { guard.consumer.occupied_slices_mut() };
248        for elem in left.iter_mut().chain(right.iter_mut()).take(count) {
249            // Include this item if its destructor unwinds, but keep its slot
250            // occupied until destruction ends so a producer cannot reuse it.
251            guard.count += 1;
252            unsafe { ptr::drop_in_place(elem.as_mut_ptr()) };
253        }
254        guard.count
255    }
256
257    /// Removes and drops all items present when the occupied range is read.
258    ///
259    /// Returns the number of deleted items. See [`Self::skip`] for complexity and behavior when a destructor panics.
260    fn clear(&mut self) -> usize {
261        self.skip(usize::MAX)
262    }
263
264    #[cfg(feature = "std")]
265    /// Removes at most first `count` bytes from the ring buffer and writes them into a [`Write`] instance.
266    /// If `count` is `None` then as much as possible bytes will be written.
267    ///
268    /// Returns:
269    ///
270    /// + `None`: ring buffer is empty or `count` is `0`. In this case `write` isn't called at all.
271    /// + `Some(Ok(n))`: `write` succeeded. `n` is number of bytes been written. `n == 0` means that `write` also returned `0`.
272    /// + `Some(Err(e))`: `write` is failed and `e` is original error. In this case it is guaranteed that no items was written to the writer.
273    ///   To achieve this we write only one contiguous slice at once. So this call may write less than `occupied_len` items even if the writer is ready to get more.
274    fn write_into<S: Write>(&mut self, writer: &mut S, count: Option<usize>) -> Option<io::Result<usize>>
275    where
276        Self: Consumer<Item = u8>,
277    {
278        let (left, _) = self.occupied_slices();
279        let count = usize::min(count.unwrap_or(left.len()), left.len());
280        if count == 0 {
281            return None;
282        }
283        let left_init = unsafe { slice_assume_init_ref(&left[..count]) };
284
285        let write_count = match writer.write(left_init) {
286            Ok(n) => n,
287            Err(e) => return Some(Err(e)),
288        };
289        assert!(write_count <= count);
290        unsafe { self.advance_read_index(write_count) };
291        Some(Ok(write_count))
292    }
293}
294
295/// Owning ring buffer iterator.
296pub struct IntoIter<C: Consumer + ?Sized> {
297    inner: C,
298}
299
300impl<C: Consumer> IntoIter<C> {
301    pub fn new(inner: C) -> Self {
302        Self { inner }
303    }
304    pub fn into_inner(self) -> C {
305        self.inner
306    }
307}
308
309impl<C: Consumer> Iterator for IntoIter<C> {
310    type Item = C::Item;
311
312    #[inline]
313    fn next(&mut self) -> Option<Self::Item> {
314        self.inner.try_pop()
315    }
316    #[inline]
317    fn size_hint(&self) -> (usize, Option<usize>) {
318        (self.inner.occupied_len(), None)
319    }
320}
321
322/// An iterator that removes items from the ring buffer.
323///
324/// Each yielded item is removed immediately, making its slot available to the producer.
325/// Only items present when the iterator is created are yielded.
326pub struct PopIter<'a, C: Consumer + ?Sized> {
327    inner: &'a C,
328    iter: Chain<slice::Iter<'a, MaybeUninit<C::Item>>, slice::Iter<'a, MaybeUninit<C::Item>>>,
329    read: usize,
330    modulus: usize,
331    remaining: usize,
332}
333
334impl<'a, C: Consumer + ?Sized> PopIter<'a, C> {
335    /// Create an iterator.
336    pub fn new(inner: &'a mut C) -> Self {
337        let (left, right) = inner.occupied_slices();
338        Self {
339            inner,
340            iter: left.iter().chain(right),
341            read: inner.read_index(),
342            modulus: modulus(inner).get(),
343            remaining: left.len() + right.len(),
344        }
345    }
346
347    /// Does nothing: each yielded item has already been removed from the ring buffer.
348    #[deprecated(note = "each yielded item is removed immediately; remove this call")]
349    pub fn commit(&mut self) {}
350}
351
352impl<C: Consumer + ?Sized> Iterator for PopIter<'_, C> {
353    type Item = C::Item;
354
355    #[inline]
356    fn next(&mut self) -> Option<Self::Item> {
357        let item = unsafe { self.iter.next()?.assume_init_read() };
358        self.read += 1;
359        if self.read == self.modulus {
360            self.read = 0;
361        }
362        self.remaining -= 1;
363        // The slice iterator no longer accesses this item. Publish its removal before
364        // handing it to the caller, who may forget the iterator or drop the item.
365        unsafe { self.inner.set_read_index(self.read) };
366        Some(item)
367    }
368    #[inline]
369    fn size_hint(&self) -> (usize, Option<usize>) {
370        (self.remaining, Some(self.remaining))
371    }
372}
373
374impl<C: Consumer + ?Sized> ExactSizeIterator for PopIter<'_, C> {}
375
376/// Iterator over ring buffer contents.
377///
378/// *Please do not rely on actual type, it may change in future.*
379#[allow(type_alias_bounds)]
380pub type Iter<'a, C: Consumer> = Chain<slice::Iter<'a, C::Item>, slice::Iter<'a, C::Item>>;
381
382/// Mutable iterator over ring buffer contents.
383///
384/// *Please do not rely on actual type, it may change in future.*
385#[allow(type_alias_bounds)]
386pub type IterMut<'a, C: Consumer> = Chain<slice::IterMut<'a, C::Item>, slice::IterMut<'a, C::Item>>;
387
388/// Trait used for delegating producer methods.
389pub trait DelegateConsumer: DelegateObserver
390where
391    Self::Base: Consumer,
392{
393}
394impl<D: DelegateConsumer> Consumer for D
395where
396    D::Base: Consumer,
397{
398    #[inline]
399    unsafe fn set_read_index(&self, value: usize) {
400        unsafe { self.base().set_read_index(value) }
401    }
402    #[inline]
403    unsafe fn advance_read_index(&self, count: usize) {
404        unsafe { self.base().advance_read_index(count) }
405    }
406
407    #[inline]
408    fn occupied_slices(&self) -> (&[core::mem::MaybeUninit<Self::Item>], &[core::mem::MaybeUninit<Self::Item>]) {
409        self.base().occupied_slices()
410    }
411
412    #[inline]
413    unsafe fn occupied_slices_mut(&mut self) -> (&mut [core::mem::MaybeUninit<Self::Item>], &mut [core::mem::MaybeUninit<Self::Item>]) {
414        unsafe { self.base_mut().occupied_slices_mut() }
415    }
416
417    #[inline]
418    fn as_slices(&self) -> (&[Self::Item], &[Self::Item]) {
419        self.base().as_slices()
420    }
421
422    #[inline]
423    fn as_mut_slices(&mut self) -> (&mut [Self::Item], &mut [Self::Item]) {
424        self.base_mut().as_mut_slices()
425    }
426
427    #[inline]
428    fn try_pop(&mut self) -> Option<Self::Item> {
429        self.base_mut().try_pop()
430    }
431
432    #[inline]
433    fn pop_slice(&mut self, elems: &mut [Self::Item]) -> usize
434    where
435        Self::Item: Copy,
436    {
437        self.base_mut().pop_slice(elems)
438    }
439
440    #[inline]
441    fn iter(&self) -> Iter<'_, Self> {
442        self.base().iter()
443    }
444
445    #[inline]
446    fn iter_mut(&mut self) -> IterMut<'_, Self> {
447        self.base_mut().iter_mut()
448    }
449
450    #[inline]
451    fn skip(&mut self, count: usize) -> usize {
452        self.base_mut().skip(count)
453    }
454
455    #[inline]
456    fn clear(&mut self) -> usize {
457        self.base_mut().clear()
458    }
459}
460
461macro_rules! impl_consumer_traits {
462    ($type:ident $(< $( $param:tt $( : $first_bound:tt $(+ $next_bound:tt )* )? ),+ >)?) => {
463        impl $(< $( $param $( : $first_bound $(+ $next_bound )* )? ),+ >)? core::iter::IntoIterator for $type $(< $( $param ),+ >)? where Self: Sized {
464            type Item = <Self as $crate::traits::Observer>::Item;
465            type IntoIter = $crate::traits::consumer::IntoIter<Self>;
466            fn into_iter(self) -> Self::IntoIter {
467                $crate::traits::consumer::IntoIter::new(self)
468            }
469        }
470
471        #[cfg(feature = "std")]
472        impl $(< $( $param $( : $first_bound $(+ $next_bound )* )? ),+ >)? std::io::Read for $type $(< $( $param ),+ >)?
473        where
474            Self: $crate::traits::Consumer<Item = u8>,
475        {
476            fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
477                let n = self.pop_slice(buf);
478                if n == 0 {
479                    Err(std::io::ErrorKind::WouldBlock.into())
480                } else {
481                    Ok(n)
482                }
483            }
484        }
485    };
486}
487pub(crate) use impl_consumer_traits;