diff --git a/README.md b/README.md index e31c1bf..2c438e1 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ The ringbuffer crate provides safe fixed size circular buffers (ringbuffers) in Implementations for three kinds of ringbuffers, with a mostly similar API are provided: -| type | description | -|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`AllocRingBuffer`][1] | Ringbuffer allocated on the heap at runtime. This ringbuffer is still fixed size. This requires alloc and the alloc feature. | -| [`GrowableAllocRingBuffer`][2] | Ringbuffer allocated on the heap at runtime. This ringbuffer can grow in size, and is implemented as an `alloc::VecDeque` internally. This requires alloc and the alloc feature. | -| [`ConstGenericRingBuffer`][3] | Ringbuffer which uses const generics to allocate on the stack. | +| type | description | +|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`AllocRingBuffer`][1] | Ringbuffer allocated on the heap at runtime. This ringbuffer is still fixed size. This requires the alloc feature. | +| [`GrowableAllocRingBuffer`][2] | Ringbuffer allocated on the heap at runtime. This ringbuffer can grow in size, and is implemented as an `alloc::VecDeque` internally. This requires the alloc feature. | +| [`ConstGenericRingBuffer`][3] | Ringbuffer which uses const generics to allocate on the stack. | All of these ringbuffers also implement the [RingBuffer][4] trait for their shared API surface. @@ -25,7 +25,8 @@ MSRV: Rust 1.59 # Usage ```rust -use ringbuffer::{AllocRingBuffer, RingBuffer, RingBufferExt, RingBufferWrite}; +use ringbuffer::{AllocRingBuffer, RingBuffer}; + fn main() { let mut buffer = AllocRingBuffer::with_capacity(2); diff --git a/benches/bench.rs b/benches/bench.rs index 8d843b7..aad03d3 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,8 +1,7 @@ -#![cfg(not(tarpaulin))] use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion}; -use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, RingBufferExt, RingBufferWrite}; +use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, RingBuffer}; -fn benchmark_push, F: Fn() -> T>(b: &mut Bencher, new: F) { +fn benchmark_push, F: Fn() -> T>(b: &mut Bencher, new: F) { b.iter(|| { let mut rb = new(); @@ -15,7 +14,7 @@ fn benchmark_push, F: Fn() -> T>(b: &mut Bencher, new: F) }) } -fn benchmark_push_dequeue, F: Fn() -> T>(b: &mut Bencher, new: F) { +fn benchmark_push_dequeue, F: Fn() -> T>(b: &mut Bencher, new: F) { b.iter(|| { let mut rb = new(); @@ -49,7 +48,7 @@ fn benchmark_push_dequeue, F: Fn() -> T>(b: &mut Bencher, }) } -fn benchmark_various, F: Fn() -> T>(b: &mut Bencher, new: F) { +fn benchmark_various, F: Fn() -> T>(b: &mut Bencher, new: F) { b.iter(|| { let mut rb = new(); diff --git a/src/lib.rs b/src/lib.rs index 1e9466a..87eb237 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,8 @@ extern crate alloc; #[macro_use] pub(crate) mod ringbuffer_trait; -use core::usize; -pub use ringbuffer_trait::{RingBuffer, RingBufferExt, RingBufferRead, RingBufferWrite}; +pub use ringbuffer_trait::RingBuffer; #[cfg(feature = "alloc")] mod with_alloc; @@ -55,17 +54,14 @@ mod tests { use std::vec; use std::vec::Vec; - use crate::{ - AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer, - RingBufferExt, RingBufferRead, RingBufferWrite, - }; + use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer}; #[test] fn run_test_neg_index() { //! Test for issue #43 const capacity: usize = 8; - fn test_neg_index(mut b: impl RingBufferExt) { + fn test_neg_index(mut b: impl RingBuffer) { for i in 0..capacity + 2 { b.push(i); assert_eq!(b.get(-1), Some(&i)); @@ -115,7 +111,7 @@ mod tests { #[test] fn run_test_len() { - fn test_len(mut b: impl RingBufferWrite) { + fn test_len(mut b: impl RingBuffer) { assert_eq!(0, b.len()); b.push(1); assert_eq!(1, b.len()); @@ -130,7 +126,7 @@ mod tests { #[test] fn run_test_len_wrap() { - fn test_len_wrap(mut b: impl RingBufferWrite) { + fn test_len_wrap(mut b: impl RingBuffer) { assert_eq!(0, b.len()); b.push(1); assert_eq!(1, b.len()); @@ -159,7 +155,7 @@ mod tests { #[test] fn run_test_clear() { - fn test_clear(mut b: impl RingBufferExt) { + fn test_clear(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -176,7 +172,7 @@ mod tests { #[test] fn run_test_empty() { - fn test_empty(mut b: impl RingBufferExt) { + fn test_empty(mut b: impl RingBuffer) { assert!(b.is_empty()); b.push(1); b.push(2); @@ -195,7 +191,7 @@ mod tests { #[test] fn run_test_iter() { - fn test_iter(mut b: impl RingBufferExt) { + fn test_iter(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -222,7 +218,7 @@ mod tests { #[test] fn run_test_into_iter() { - fn test_iter(mut b: impl RingBufferExt) { + fn test_iter(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -250,7 +246,7 @@ mod tests { #[cfg(feature = "alloc")] #[test] fn run_test_iter_with_lifetimes() { - fn test_iter<'a>(string: &'a str, mut b: impl RingBufferExt<&'a str>) { + fn test_iter<'a>(string: &'a str, mut b: impl RingBuffer<&'a str>) { b.push(&string[0..1]); b.push(&string[1..2]); b.push(&string[2..3]); @@ -272,7 +268,7 @@ mod tests { #[test] fn run_test_double_iter() { - fn test_double_iter(mut b: impl RingBufferExt) { + fn test_double_iter(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -295,7 +291,7 @@ mod tests { #[test] fn run_test_iter_wrap() { - fn test_iter_wrap(mut b: impl RingBufferExt) { + fn test_iter_wrap(mut b: impl RingBuffer) { b.push(1); b.push(2); // Wrap @@ -326,7 +322,7 @@ mod tests { #[test] fn run_test_iter_mut() { - fn test_iter_mut(mut b: impl RingBufferExt) { + fn test_iter_mut(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -345,7 +341,7 @@ mod tests { #[test] fn test_iter_mut_wrap() { - fn run_test_iter_mut_wrap(mut b: impl RingBufferExt) { + fn run_test_iter_mut_wrap(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -376,7 +372,7 @@ mod tests { #[test] fn test_iter_mut_miri_fail() { - fn run_test_iter_mut_wrap(mut b: impl RingBufferExt) { + fn run_test_iter_mut_wrap(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -410,7 +406,7 @@ mod tests { #[test] fn run_test_to_vec() { - fn test_to_vec(mut b: impl RingBufferExt) { + fn test_to_vec(mut b: impl RingBuffer) { b.push(1); b.push(2); b.push(3); @@ -425,7 +421,7 @@ mod tests { #[test] fn run_test_to_vec_wrap() { - fn test_to_vec_wrap(mut b: impl RingBufferExt) { + fn test_to_vec_wrap(mut b: impl RingBuffer) { b.push(1); b.push(2); // Wrap @@ -449,7 +445,7 @@ mod tests { #[test] fn run_test_index() { - fn test_index(mut b: impl RingBufferExt) { + fn test_index(mut b: impl RingBuffer) { b.push(2); assert_eq!(b[0], 2) } @@ -461,7 +457,7 @@ mod tests { #[test] fn run_test_index_mut() { - fn test_index_mut(mut b: impl RingBufferExt) { + fn test_index_mut(mut b: impl RingBuffer) { b.push(2); assert_eq!(b[0], 2); @@ -478,7 +474,7 @@ mod tests { #[test] fn run_test_peek_some() { - fn test_peek_some(mut b: impl RingBufferExt) { + fn test_peek_some(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -492,7 +488,7 @@ mod tests { #[test] fn run_test_peek_none() { - fn test_peek_none(b: impl RingBufferExt) { + fn test_peek_none(b: impl RingBuffer) { assert_eq!(b.peek(), None); } @@ -503,7 +499,7 @@ mod tests { #[test] fn run_test_get_relative() { - fn test_get_relative(mut b: impl RingBufferExt) { + fn test_get_relative(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -528,7 +524,7 @@ mod tests { #[test] fn run_test_wrapping_get_relative() { - fn test_wrapping_get_relative(mut b: impl RingBufferExt) { + fn test_wrapping_get_relative(mut b: impl RingBuffer) { b.push(0); b.push(1); b.push(2); @@ -561,7 +557,7 @@ mod tests { #[test] fn run_test_get_relative_zero_length() { - fn test_get_relative_zero_length(b: impl RingBufferExt) { + fn test_get_relative_zero_length(b: impl RingBuffer) { assert!(b.get(1).is_none()); } @@ -572,7 +568,7 @@ mod tests { #[test] fn run_test_get_relative_mut() { - fn test_get_relative_mut(mut b: impl RingBufferExt) { + fn test_get_relative_mut(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -596,7 +592,7 @@ mod tests { #[test] fn run_test_wrapping_get_relative_mut() { - fn test_wrapping_get_relative_mut(mut b: impl RingBufferExt) { + fn test_wrapping_get_relative_mut(mut b: impl RingBuffer) { b.push(0); b.push(1); b.push(2); @@ -634,7 +630,7 @@ mod tests { #[test] fn run_test_get_relative_mut_zero_length() { - fn test_get_relative_mut_zero_length(mut b: impl RingBufferExt) { + fn test_get_relative_mut_zero_length(mut b: impl RingBuffer) { assert!(b.get_mut(1).is_none()); } @@ -646,7 +642,7 @@ mod tests { #[test] #[allow(deprecated)] fn run_test_get_absolute() { - fn test_get_absolute(mut b: impl RingBufferExt) { + fn test_get_absolute(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -667,7 +663,7 @@ mod tests { #[test] fn run_test_from_iterator() { - fn test_from_iterator + FromIterator>() { + fn test_from_iterator + FromIterator>() { let b: T = std::iter::repeat(1).take(1024).collect(); assert_eq!(b.len(), 1024); assert_eq!(b.to_vec(), vec![1; 1024]) @@ -679,7 +675,7 @@ mod tests { #[test] fn run_test_from_iterator_wrap() { - fn test_from_iterator_wrap + FromIterator>() { + fn test_from_iterator_wrap + FromIterator>() { let b: T = std::iter::repeat(1).take(8000).collect(); assert_eq!(b.len(), b.capacity()); assert_eq!(b.to_vec(), vec![1; b.capacity()]) @@ -691,7 +687,7 @@ mod tests { #[test] fn run_test_get_relative_negative() { - fn test_get_relative_negative(mut b: impl RingBufferExt) { + fn test_get_relative_negative(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -715,7 +711,7 @@ mod tests { #[test] fn run_test_contains() { - fn test_contains(mut b: impl RingBufferExt) { + fn test_contains(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -730,7 +726,7 @@ mod tests { #[test] fn run_test_is_full() { - fn test_is_full(mut b: impl RingBufferExt) { + fn test_is_full(mut b: impl RingBuffer) { assert!(!b.is_full()); b.push(1); assert!(!b.is_full()); @@ -745,7 +741,7 @@ mod tests { #[test] fn run_test_front_some() { - fn test_front_some(mut b: impl RingBufferExt) { + fn test_front_some(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -759,7 +755,7 @@ mod tests { #[test] fn run_test_front_none() { - fn test_front_none(b: impl RingBufferExt) { + fn test_front_none(b: impl RingBuffer) { assert_eq!(b.front(), None); } @@ -770,7 +766,7 @@ mod tests { #[test] fn run_test_back_some() { - fn test_back_some(mut b: impl RingBufferExt) { + fn test_back_some(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -784,7 +780,7 @@ mod tests { #[test] fn run_test_back_none() { - fn test_back_none(b: impl RingBufferExt) { + fn test_back_none(b: impl RingBuffer) { assert_eq!(b.back(), None); } @@ -795,7 +791,7 @@ mod tests { #[test] fn run_test_front_some_mut() { - fn test_front_some_mut(mut b: impl RingBufferExt) { + fn test_front_some_mut(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -809,7 +805,7 @@ mod tests { #[test] fn run_test_front_none_mut() { - fn test_front_none_mut(mut b: impl RingBufferExt) { + fn test_front_none_mut(mut b: impl RingBuffer) { assert_eq!(b.front_mut(), None); } @@ -820,7 +816,7 @@ mod tests { #[test] fn run_test_back_some_mut() { - fn test_back_some_mut(mut b: impl RingBufferExt) { + fn test_back_some_mut(mut b: impl RingBuffer) { b.push(1); b.push(2); @@ -834,7 +830,7 @@ mod tests { #[test] fn run_test_back_none_mut() { - fn test_back_none_mut(mut b: impl RingBufferExt) { + fn test_back_none_mut(mut b: impl RingBuffer) { assert_eq!(b.back_mut(), None); } @@ -845,7 +841,7 @@ mod tests { #[test] fn run_test_dequeue() { - fn run_test_dequeue(mut b: impl RingBufferExt) { + fn run_test_dequeue(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -866,7 +862,7 @@ mod tests { #[test] fn run_test_skip() { - fn test_skip(mut b: impl RingBufferExt) { + fn test_skip(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -885,7 +881,7 @@ mod tests { #[test] fn run_test_skip_2() { - fn test_skip2(mut rb: impl RingBufferExt) { + fn test_skip2(mut rb: impl RingBuffer) { rb.skip(); rb.skip(); rb.skip(); @@ -903,7 +899,7 @@ mod tests { #[test] fn run_test_push_dequeue_push() { - fn test_push_dequeue_push(mut b: impl RingBufferExt) { + fn test_push_dequeue_push(mut b: impl RingBuffer) { b.push(0); b.push(1); @@ -926,7 +922,7 @@ mod tests { #[test] fn run_test_enqueue_dequeue_push() { - fn test_enqueue_dequeue_push(mut b: impl RingBufferExt) { + fn test_enqueue_dequeue_push(mut b: impl RingBuffer) { b.enqueue(0); b.enqueue(1); @@ -949,7 +945,7 @@ mod tests { #[test] fn large_negative_index() { - fn test_large_negative_index(mut b: impl RingBufferExt) { + fn test_large_negative_index(mut b: impl RingBuffer) { b.push(1); b.push(2); assert_eq!(b.get(1), Some(&2)); @@ -966,7 +962,7 @@ mod tests { #[test] fn large_negative_index_mut() { - fn test_large_negative_index(mut b: impl RingBufferExt) { + fn test_large_negative_index(mut b: impl RingBuffer) { b.push(1); b.push(2); assert_eq!(b.get_mut(1), Some(&mut 2)); @@ -983,7 +979,7 @@ mod tests { #[test] fn run_test_push_dequeue_push_full() { - fn test_push_dequeue_push_full(mut b: impl RingBufferExt) { + fn test_push_dequeue_push_full(mut b: impl RingBuffer) { b.push(0); b.push(1); b.push(2); @@ -1027,7 +1023,7 @@ mod tests { #[test] fn run_test_push_dequeue_push_full_get() { - fn test_push_dequeue_push_full_get(mut b: impl RingBufferExt) { + fn test_push_dequeue_push_full_get(mut b: impl RingBuffer) { b.push(0); b.push(1); b.push(2); @@ -1090,7 +1086,7 @@ mod tests { #[cfg_attr(miri, ignore)] // this test takes far too long with Miri enabled fn run_test_push_dequeue_push_full_get_rep() { - fn test_push_dequeue_push_full_get_rep(mut rb: impl RingBufferExt) { + fn test_push_dequeue_push_full_get_rep(mut rb: impl RingBuffer) { for _ in 0..100_000 { rb.push(1); rb.push(2); @@ -1119,7 +1115,7 @@ mod tests { #[test] fn run_test_clone() { - fn test_clone(mut rb: impl RingBufferExt + Clone + Eq + Debug) { + fn test_clone(mut rb: impl RingBuffer + Clone + Eq + Debug) { rb.push(42); rb.push(32); rb.push(22); @@ -1143,7 +1139,7 @@ mod tests { #[test] fn run_test_default_fill() { - fn test_default_fill(mut rb: impl RingBufferExt) { + fn test_default_fill(mut rb: impl RingBuffer) { for i in 0..rb.capacity() { for _ in 0..i { rb.push(1); @@ -1183,7 +1179,7 @@ mod tests { #[test] fn run_next_back_test() { - fn next_back_test(mut rb: impl RingBufferExt) { + fn next_back_test(mut rb: impl RingBuffer) { for i in 1..=4 { rb.push(i); } @@ -1203,7 +1199,7 @@ mod tests { #[test] fn run_next_back_test_mut() { - fn next_back_test_mut(mut rb: impl RingBufferExt) { + fn next_back_test_mut(mut rb: impl RingBuffer) { for i in 1..=4 { rb.push(i); } @@ -1222,7 +1218,7 @@ mod tests { } #[test] fn run_test_fill() { - fn test_fill(mut rb: impl RingBufferExt) { + fn test_fill(mut rb: impl RingBuffer) { for i in 0..rb.capacity() { for _ in 0..i { rb.push(1); diff --git a/src/ringbuffer_trait.rs b/src/ringbuffer_trait.rs index e6e21fa..2d494a6 100644 --- a/src/ringbuffer_trait.rs +++ b/src/ringbuffer_trait.rs @@ -11,8 +11,16 @@ use alloc::vec::Vec; /// This trait is not object safe, so can't be used dynamically. However it is possible to /// define a generic function over types implementing `RingBuffer`. /// -/// Most actual functionality of ringbuffers is contained in the extension traits [`RingBufferExt`], [`RingBufferRead`] and [`RingBufferWrite`] -pub trait RingBuffer: Sized { +/// # Safety +/// Implementing this implies that the ringbuffer upholds some safety +/// guarantees, such as returning a different value from `get_mut` any +/// for every different index passed in. See the exact requirements +/// in the safety comment on the next function of the mutable Iterator +/// implementation, since these safety guarantees are necessary for +/// [`iter_mut`](RingBuffer::iter_mut) to work +pub unsafe trait RingBuffer: + Sized + IntoIterator + Extend + Index + IndexMut +{ /// Returns the length of the internal buffer. /// This length grows up to the capacity and then stops growing. /// This is because when the length is reached, new items are appended at the start. @@ -49,23 +57,15 @@ pub trait RingBuffer: Sized { /// Safety: ONLY SAFE WHEN self is a *mut to to an implementor of RingBuffer #[doc(hidden)] unsafe fn ptr_capacity(rb: *const Self) -> usize; -} -/// Defines behaviour for ringbuffers which allow for writing to the end of them (as a queue). -/// For arbitrary buffer access however, [`RingBufferExt`] is necessary. -pub trait RingBufferWrite: RingBuffer + Extend { /// Pushes a value onto the buffer. Cycles around if capacity is reached. fn push(&mut self, value: T); - /// alias for [`push`](RingBufferWrite::push), forming a more natural counterpart to [`dequeue`](RingBufferRead::dequeue) + /// alias for [`push`](RingBuffer::push), forming a more natural counterpart to [`dequeue`](RingBuffer::dequeue) fn enqueue(&mut self, value: T) { self.push(value); } -} -/// Defines behaviour for ringbuffers which allow for reading from the start of them (as a queue). -/// For arbitrary buffer access however, [`RingBufferExt`] is necessary. -pub trait RingBufferRead: RingBuffer + IntoIterator { /// dequeues the top item off the ringbuffer, and moves this item out. fn dequeue(&mut self) -> Option; @@ -80,9 +80,9 @@ pub trait RingBufferRead: RingBuffer + IntoIterator { /// dequeueing elements as they are iterated over. /// /// ``` - /// use ringbuffer::{AllocRingBuffer, RingBufferWrite, RingBufferRead, RingBuffer}; + /// use ringbuffer::{AllocRingBuffer, RingBuffer}; /// - /// let mut rb = AllocRingBuffer::with_capacity(16); + /// let mut rb = AllocRingBuffer::new(16); /// for i in 0..8 { /// rb.push(i); /// } @@ -101,21 +101,7 @@ pub trait RingBufferRead: RingBuffer + IntoIterator { fn drain(&mut self) -> RingBufferDrainingIterator { RingBufferDrainingIterator::new(self) } -} -/// Defines behaviour for ringbuffers which allow them to be used as a general purpose buffer. -/// With this trait, arbitrary access of elements in the buffer is possible. -/// -/// # Safety -/// Implementing this implies that the ringbuffer upholds some safety -/// guarantees, such as returning a different value from `get_mut` any -/// for every different index passed in. See the exact requirements -/// in the safety comment on the next function of the mutable Iterator -/// implementation, since these safety guarantees are necessary for -/// [`iter_mut`](RingBufferExt::iter_mut) to work -pub unsafe trait RingBufferExt: - RingBuffer + RingBufferRead + RingBufferWrite + Index + IndexMut -{ /// Sets every element in the ringbuffer to the value returned by f. fn fill_with T>(&mut self, f: F); @@ -150,8 +136,8 @@ pub unsafe trait RingBufferExt: unsafe { Self::ptr_get_mut(self, index).map(|i| &mut *i) } } - /// same as [`get_mut`](RingBufferExt::get_mut) but on raw pointers. - /// Safety: ONLY SAFE WHEN self is a *mut to to an implementor of RingBufferExt + /// same as [`get_mut`](RingBuffer::get_mut) but on raw pointers. + /// Safety: ONLY SAFE WHEN self is a *mut to to an implementor of RingBuffer #[doc(hidden)] unsafe fn ptr_get_mut(rb: *mut Self, index: isize) -> Option<*mut T>; @@ -235,21 +221,21 @@ pub unsafe trait RingBufferExt: } mod iter { - use crate::{RingBufferExt, RingBufferRead}; + use crate::RingBuffer; use core::iter::FusedIterator; use core::marker::PhantomData; use core::ptr::NonNull; - /// `RingBufferIterator` holds a reference to a `RingBufferExt` and iterates over it. `index` is the + /// `RingBufferIterator` holds a reference to a `RingBuffer` and iterates over it. `index` is the /// current iterator position. - pub struct RingBufferIterator<'rb, T, RB: RingBufferExt> { + pub struct RingBufferIterator<'rb, T, RB: RingBuffer> { obj: &'rb RB, len: usize, index: usize, phantom: PhantomData, } - impl<'rb, T, RB: RingBufferExt> RingBufferIterator<'rb, T, RB> { + impl<'rb, T, RB: RingBuffer> RingBufferIterator<'rb, T, RB> { #[inline] pub fn new(obj: &'rb RB) -> Self { Self { @@ -261,7 +247,7 @@ mod iter { } } - impl<'rb, T: 'rb, RB: RingBufferExt> Iterator for RingBufferIterator<'rb, T, RB> { + impl<'rb, T: 'rb, RB: RingBuffer> Iterator for RingBufferIterator<'rb, T, RB> { type Item = &'rb T; #[inline] @@ -280,11 +266,11 @@ mod iter { } } - impl<'rb, T: 'rb, RB: RingBufferExt> FusedIterator for RingBufferIterator<'rb, T, RB> {} + impl<'rb, T: 'rb, RB: RingBuffer> FusedIterator for RingBufferIterator<'rb, T, RB> {} - impl<'rb, T: 'rb, RB: RingBufferExt> ExactSizeIterator for RingBufferIterator<'rb, T, RB> {} + impl<'rb, T: 'rb, RB: RingBuffer> ExactSizeIterator for RingBufferIterator<'rb, T, RB> {} - impl<'rb, T: 'rb, RB: RingBufferExt> DoubleEndedIterator for RingBufferIterator<'rb, T, RB> { + impl<'rb, T: 'rb, RB: RingBuffer> DoubleEndedIterator for RingBufferIterator<'rb, T, RB> { #[inline] fn next_back(&mut self) -> Option { if self.len > 0 && self.index < self.len { @@ -297,19 +283,19 @@ mod iter { } } - /// `RingBufferMutIterator` holds a reference to a `RingBufferExt` and iterates over it. `index` is the + /// `RingBufferMutIterator` holds a reference to a `RingBuffer` and iterates over it. `index` is the /// current iterator position. /// /// WARNING: NEVER ACCESS THE `obj` FIELD OUTSIDE OF NEXT. It's private on purpose, and /// can technically be accessed in the same module. However, this breaks the safety of `next()` - pub struct RingBufferMutIterator<'rb, T, RB: RingBufferExt> { + pub struct RingBufferMutIterator<'rb, T, RB: RingBuffer> { obj: NonNull, index: usize, len: usize, phantom: PhantomData<&'rb mut T>, } - impl<'rb, T, RB: RingBufferExt> RingBufferMutIterator<'rb, T, RB> { + impl<'rb, T, RB: RingBuffer> RingBufferMutIterator<'rb, T, RB> { pub fn new(obj: &'rb mut RB) -> Self { Self { len: obj.len(), @@ -320,14 +306,11 @@ mod iter { } } - impl<'rb, T: 'rb, RB: RingBufferExt + 'rb> FusedIterator for RingBufferMutIterator<'rb, T, RB> {} + impl<'rb, T: 'rb, RB: RingBuffer + 'rb> FusedIterator for RingBufferMutIterator<'rb, T, RB> {} - impl<'rb, T: 'rb, RB: RingBufferExt + 'rb> ExactSizeIterator - for RingBufferMutIterator<'rb, T, RB> - { - } + impl<'rb, T: 'rb, RB: RingBuffer + 'rb> ExactSizeIterator for RingBufferMutIterator<'rb, T, RB> {} - impl<'rb, T: 'rb, RB: RingBufferExt + 'rb> DoubleEndedIterator + impl<'rb, T: 'rb, RB: RingBuffer + 'rb> DoubleEndedIterator for RingBufferMutIterator<'rb, T, RB> { #[inline] @@ -342,7 +325,7 @@ mod iter { } } - impl<'rb, T, RB: RingBufferExt + 'rb> Iterator for RingBufferMutIterator<'rb, T, RB> { + impl<'rb, T, RB: RingBuffer + 'rb> Iterator for RingBufferMutIterator<'rb, T, RB> { type Item = &'rb mut T; fn next(&mut self) -> Option { @@ -361,13 +344,13 @@ mod iter { } } - /// `RingBufferMutIterator` holds a reference to a `RingBufferRead` and iterates over it. - pub struct RingBufferDrainingIterator<'rb, T, RB: RingBufferRead> { + /// `RingBufferMutIterator` holds a reference to a `RingBuffer` and iterates over it. + pub struct RingBufferDrainingIterator<'rb, T, RB: RingBuffer> { obj: &'rb mut RB, phantom: PhantomData, } - impl<'rb, T, RB: RingBufferRead> RingBufferDrainingIterator<'rb, T, RB> { + impl<'rb, T, RB: RingBuffer> RingBufferDrainingIterator<'rb, T, RB> { #[inline] pub fn new(obj: &'rb mut RB) -> Self { Self { @@ -377,7 +360,7 @@ mod iter { } } - impl<'rb, T, RB: RingBufferRead> Iterator for RingBufferDrainingIterator<'rb, T, RB> { + impl<'rb, T, RB: RingBuffer> Iterator for RingBufferDrainingIterator<'rb, T, RB> { type Item = T; fn next(&mut self) -> Option { @@ -389,13 +372,13 @@ mod iter { } } - /// `RingBufferIntoIterator` holds a `RingBufferRead` and iterates over it. - pub struct RingBufferIntoIterator> { + /// `RingBufferIntoIterator` holds a `RingBuffer` and iterates over it. + pub struct RingBufferIntoIterator> { obj: RB, phantom: PhantomData, } - impl> RingBufferIntoIterator { + impl> RingBufferIntoIterator { #[inline] pub fn new(obj: RB) -> Self { Self { @@ -405,7 +388,7 @@ mod iter { } } - impl> Iterator for RingBufferIntoIterator { + impl> Iterator for RingBufferIntoIterator { type Item = T; #[inline] @@ -434,7 +417,7 @@ macro_rules! impl_ringbuffer { }; } -/// Implement various functions on implementors of [`RingBufferExt`]. +/// Implement various functions on implementors of [`RingBuffer`]. /// This is to avoid duplicate code. macro_rules! impl_ringbuffer_ext { ($get_unchecked: ident, $get_unchecked_mut: ident, $readptr: ident, $writeptr: ident, $mask: expr) => { diff --git a/src/with_alloc/alloc_ringbuffer.rs b/src/with_alloc/alloc_ringbuffer.rs index f3e5d82..0636c9a 100644 --- a/src/with_alloc/alloc_ringbuffer.rs +++ b/src/with_alloc/alloc_ringbuffer.rs @@ -1,8 +1,6 @@ use core::ops::{Index, IndexMut}; -use crate::ringbuffer_trait::{ - RingBuffer, RingBufferExt, RingBufferIntoIterator, RingBufferRead, RingBufferWrite, -}; +use crate::ringbuffer_trait::{RingBuffer, RingBufferIntoIterator}; extern crate alloc; @@ -61,15 +59,15 @@ impl RingbufferSize for NonPowerOfTwo { } } -/// The `AllocRingBuffer` is a `RingBufferExt` which is based on a Vec. This means it allocates at runtime +/// The `AllocRingBuffer` is a `RingBuffer` which is based on a Vec. This means it allocates at runtime /// on the heap, and therefore needs the [`alloc`] crate. This struct and therefore the dependency on /// alloc can be disabled by disabling the `alloc` (default) feature. /// /// # Example /// ``` -/// use ringbuffer::{AllocRingBuffer, RingBuffer, RingBufferExt, RingBufferWrite}; +/// use ringbuffer::{AllocRingBuffer, RingBuffer}; /// -/// let mut buffer = AllocRingBuffer::with_capacity(2); +/// let mut buffer = AllocRingBuffer::new(2); /// /// // First entry of the buffer is now 5. /// buffer.push(5); @@ -224,28 +222,6 @@ impl PartialEq for AllocRingBuffer impl Eq for AllocRingBuffer {} -unsafe impl RingBufferExt for AllocRingBuffer { - impl_ringbuffer_ext!( - get_unchecked, - get_unchecked_mut, - readptr, - writeptr, - SIZE::mask - ); - - #[inline] - fn fill_with T>(&mut self, mut f: F) { - self.clear(); - - self.readptr = 0; - self.writeptr = self.capacity; - - for i in 0..self.capacity { - unsafe { ptr::write(get_unchecked_mut(self, i), f()) }; - } - } -} - impl IntoIterator for AllocRingBuffer { type Item = T; type IntoIter = RingBufferIntoIterator; @@ -255,23 +231,6 @@ impl IntoIterator for AllocRingBuffer { } } -impl RingBufferRead for AllocRingBuffer { - fn dequeue(&mut self) -> Option { - if self.is_empty() { - None - } else { - let index = SIZE::mask(self.capacity, self.readptr); - let res = unsafe { get_unchecked_mut(self, index) }; - self.readptr += 1; - - // Safety: the fact that we got this maybeuninit from the buffer (with mask) means that - // it's initialized. If it wasn't the is_empty call would have caught it. Values - // are always initialized when inserted so this is safe. - unsafe { Some(ptr::read(res)) } - } - } -} - impl Extend for AllocRingBuffer { fn extend>(&mut self, iter: A) { let iter = iter.into_iter(); @@ -282,7 +241,14 @@ impl Extend for AllocRingBuffer { } } -impl RingBufferWrite for AllocRingBuffer { +unsafe impl RingBuffer for AllocRingBuffer { + #[inline] + unsafe fn ptr_capacity(rb: *const Self) -> usize { + (*rb).capacity + } + + impl_ringbuffer!(readptr, writeptr); + #[inline] fn push(&mut self, value: T) { if self.is_full() { @@ -312,15 +278,41 @@ impl RingBufferWrite for AllocRingBuffer { self.writeptr += 1; } -} -impl RingBuffer for AllocRingBuffer { - #[inline] - unsafe fn ptr_capacity(rb: *const Self) -> usize { - (*rb).capacity + fn dequeue(&mut self) -> Option { + if self.is_empty() { + None + } else { + let index = SIZE::mask(self.capacity, self.readptr); + let res = unsafe { get_unchecked_mut(self, index) }; + self.readptr += 1; + + // Safety: the fact that we got this maybeuninit from the buffer (with mask) means that + // it's initialized. If it wasn't the is_empty call would have caught it. Values + // are always initialized when inserted so this is safe. + unsafe { Some(ptr::read(res)) } + } } - impl_ringbuffer!(readptr, writeptr); + impl_ringbuffer_ext!( + get_unchecked, + get_unchecked_mut, + readptr, + writeptr, + SIZE::mask + ); + + #[inline] + fn fill_with T>(&mut self, mut f: F) { + self.clear(); + + self.readptr = 0; + self.writeptr = self.capacity; + + for i in 0..self.capacity { + unsafe { ptr::write(get_unchecked_mut(self, i), f()) }; + } + } } impl AllocRingBuffer { @@ -444,7 +436,7 @@ impl IndexMut for AllocRingBuffer { #[cfg(test)] mod tests { use crate::with_alloc::alloc_ringbuffer::RingbufferSize; - use crate::{AllocRingBuffer, RingBuffer, RingBufferExt, RingBufferRead, RingBufferWrite}; + use crate::{AllocRingBuffer, RingBuffer}; // just test that this compiles #[test] diff --git a/src/with_alloc/vecdeque.rs b/src/with_alloc/vecdeque.rs index b469320..cb81519 100644 --- a/src/with_alloc/vecdeque.rs +++ b/src/with_alloc/vecdeque.rs @@ -1,6 +1,6 @@ use crate::ringbuffer_trait::RingBufferIntoIterator; use crate::with_alloc::alloc_ringbuffer::RingbufferSize; -use crate::{AllocRingBuffer, RingBuffer, RingBufferExt, RingBufferRead, RingBufferWrite}; +use crate::{AllocRingBuffer, RingBuffer}; use alloc::collections::VecDeque; use core::ops::{Deref, DerefMut, Index, IndexMut}; @@ -142,16 +142,6 @@ impl GrowableAllocRingBuffer { } } -impl RingBuffer for GrowableAllocRingBuffer { - unsafe fn ptr_len(rb: *const Self) -> usize { - (*rb).0.len() - } - - unsafe fn ptr_capacity(rb: *const Self) -> usize { - (*rb).0.capacity() - } -} - impl IntoIterator for GrowableAllocRingBuffer { type Item = T; type IntoIter = RingBufferIntoIterator; @@ -161,45 +151,23 @@ impl IntoIterator for GrowableAllocRingBuffer { } } -impl RingBufferRead for GrowableAllocRingBuffer { - fn dequeue(&mut self) -> Option { - self.pop_front() - } -} - -impl RingBufferWrite for GrowableAllocRingBuffer { - fn push(&mut self, value: T) { - self.push_back(value); - } -} - -impl Extend for GrowableAllocRingBuffer { - fn extend>(&mut self, iter: I) { - self.0.extend(iter); +unsafe impl RingBuffer for GrowableAllocRingBuffer { + unsafe fn ptr_len(rb: *const Self) -> usize { + (*rb).0.len() } -} - -impl Index for GrowableAllocRingBuffer { - type Output = T; - fn index(&self, index: isize) -> &Self::Output { - self.get(index).expect("index out of bounds") + unsafe fn ptr_capacity(rb: *const Self) -> usize { + (*rb).0.capacity() } -} -impl IndexMut for GrowableAllocRingBuffer { - fn index_mut(&mut self, index: isize) -> &mut Self::Output { - self.get_mut(index).expect("index out of bounds") + fn dequeue(&mut self) -> Option { + self.pop_front() } -} -impl FromIterator for GrowableAllocRingBuffer { - fn from_iter>(iter: I) -> Self { - Self(VecDeque::from_iter(iter)) + fn push(&mut self, value: T) { + self.push_back(value); } -} -unsafe impl RingBufferExt for GrowableAllocRingBuffer { fn fill_with T>(&mut self, mut f: F) { self.clear(); let initial_capacity = self.0.capacity(); @@ -254,3 +222,29 @@ unsafe impl RingBufferExt for GrowableAllocRingBuffer { unimplemented!() } } + +impl Extend for GrowableAllocRingBuffer { + fn extend>(&mut self, iter: I) { + self.0.extend(iter); + } +} + +impl Index for GrowableAllocRingBuffer { + type Output = T; + + fn index(&self, index: isize) -> &Self::Output { + self.get(index).expect("index out of bounds") + } +} + +impl IndexMut for GrowableAllocRingBuffer { + fn index_mut(&mut self, index: isize) -> &mut Self::Output { + self.get_mut(index).expect("index out of bounds") + } +} + +impl FromIterator for GrowableAllocRingBuffer { + fn from_iter>(iter: I) -> Self { + Self(VecDeque::from_iter(iter)) + } +} diff --git a/src/with_const_generics.rs b/src/with_const_generics.rs index 388a93f..6d33138 100644 --- a/src/with_const_generics.rs +++ b/src/with_const_generics.rs @@ -1,6 +1,6 @@ use crate::ringbuffer_trait::RingBufferIntoIterator; use crate::with_alloc::alloc_ringbuffer::RingbufferSize; -use crate::{RingBuffer, RingBufferExt, RingBufferRead, RingBufferWrite}; +use crate::RingBuffer; use core::iter::FromIterator; use core::mem; use core::mem::MaybeUninit; @@ -14,7 +14,7 @@ use core::ops::{Index, IndexMut}; /// /// # Example /// ``` -/// use ringbuffer::{ConstGenericRingBuffer, RingBuffer, RingBufferExt, RingBufferWrite}; +/// use ringbuffer::{ConstGenericRingBuffer, RingBuffer}; /// /// let mut buffer = ConstGenericRingBuffer::<_, 2>::new(); /// @@ -223,23 +223,6 @@ impl IntoIterator for ConstGenericRingBuffer { } } -impl RingBufferRead for ConstGenericRingBuffer { - fn dequeue(&mut self) -> Option { - if self.is_empty() { - None - } else { - let index = crate::mask_modulo(CAP, self.readptr); - let res = mem::replace(&mut self.buf[index], MaybeUninit::uninit()); - self.readptr += 1; - - // Safety: the fact that we got this maybeuninit from the buffer (with mask) means that - // it's initialized. If it wasn't the is_empty call would have caught it. Values - // are always initialized when inserted so this is safe. - unsafe { Some(res.assume_init()) } - } - } -} - impl Extend for ConstGenericRingBuffer { fn extend>(&mut self, iter: A) { let iter = iter.into_iter(); @@ -250,7 +233,14 @@ impl Extend for ConstGenericRingBuffer { } } -impl RingBufferWrite for ConstGenericRingBuffer { +unsafe impl RingBuffer for ConstGenericRingBuffer { + #[inline] + unsafe fn ptr_capacity(_: *const Self) -> usize { + CAP + } + + impl_ringbuffer!(readptr, writeptr); + #[inline] fn push(&mut self, value: T) { if self.is_full() { @@ -271,9 +261,22 @@ impl RingBufferWrite for ConstGenericRingBuffer self.buf[index] = MaybeUninit::new(value); self.writeptr += 1; } -} -unsafe impl RingBufferExt for ConstGenericRingBuffer { + fn dequeue(&mut self) -> Option { + if self.is_empty() { + None + } else { + let index = crate::mask_modulo(CAP, self.readptr); + let res = mem::replace(&mut self.buf[index], MaybeUninit::uninit()); + self.readptr += 1; + + // Safety: the fact that we got this maybeuninit from the buffer (with mask) means that + // it's initialized. If it wasn't the is_empty call would have caught it. Values + // are always initialized when inserted so this is safe. + unsafe { Some(res.assume_init()) } + } + } + impl_ringbuffer_ext!( get_unchecked, get_unchecked_mut, @@ -291,16 +294,6 @@ unsafe impl RingBufferExt for ConstGenericRingBuffer RingBuffer for ConstGenericRingBuffer { - #[inline] - #[cfg(not(tarpaulin_include))] - unsafe fn ptr_capacity(_: *const Self) -> usize { - CAP - } - - impl_ringbuffer!(readptr, writeptr); -} - impl Default for ConstGenericRingBuffer { /// Creates a buffer with a capacity specified through the Cap type parameter. /// # Panics diff --git a/tests/compiletests.rs b/tests/compiletests.rs index 8c3a2a2..f48163e 100644 --- a/tests/compiletests.rs +++ b/tests/compiletests.rs @@ -18,7 +18,6 @@ fn run_mode(mode: &'static str) { #[test] #[cfg_attr(miri, ignore)] -#[cfg(not(tarpaulin))] fn compile_test() { run_mode("compile-fail"); } diff --git a/tests/conversions.rs b/tests/conversions.rs index 8140f40..5816a5e 100644 --- a/tests/conversions.rs +++ b/tests/conversions.rs @@ -3,8 +3,8 @@ extern crate alloc; use alloc::collections::{LinkedList, VecDeque}; use alloc::string::ToString; use core::ops::Deref; +use ringbuffer::RingBuffer; use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer}; -use ringbuffer::{RingBufferExt, RingBufferWrite}; use std::vec; macro_rules! convert_test {