From f64f30bb24e80c545de51dace3d2bc602d7441b5 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 12 May 2024 22:11:30 +0200 Subject: [PATCH] ringbuffer_trait: add extend_from_slice This adds an extend_from_slice function to the RingBuffer trait. The default implementation calls push() for each element. However, by creating specialized implementations for the various buffers, one can do various performance optimizations in a follow-up. --- src/ringbuffer_trait.rs | 10 +++++++++- src/with_alloc/alloc_ringbuffer.rs | 8 ++++++++ src/with_alloc/vecdeque.rs | 13 +++++++++++++ src/with_const_generics.rs | 8 ++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/ringbuffer_trait.rs b/src/ringbuffer_trait.rs index 9f869c4..e295193 100644 --- a/src/ringbuffer_trait.rs +++ b/src/ringbuffer_trait.rs @@ -86,7 +86,6 @@ pub unsafe trait RingBuffer: /// /// Cycles around if capacity is reached. /// Forms a more natural counterpart to [`dequeue`](RingBuffer::dequeue). - /// An alias is provided with [`push`](RingBuffer::push). fn enqueue(&mut self, value: T) -> Option; /// dequeues the top item off the ringbuffer, and moves this item out. @@ -237,6 +236,15 @@ pub unsafe trait RingBuffer: RingBufferIterator::new(self) } + /// Extends the ringbuffer with elements from a slice. + fn extend_from_slice(&mut self, elements: &[T]) where T: Clone { + // Default implementation. + // For performance reasons, specific RingBuffers should use an optimized implementation. + for element in elements { + let _ = self.enqueue(element.clone()); + } + } + /// Converts the buffer to a vector. This Copies all elements in the ringbuffer. #[cfg(feature = "alloc")] fn to_vec(&self) -> Vec diff --git a/src/with_alloc/alloc_ringbuffer.rs b/src/with_alloc/alloc_ringbuffer.rs index f21769e..3af05f3 100644 --- a/src/with_alloc/alloc_ringbuffer.rs +++ b/src/with_alloc/alloc_ringbuffer.rs @@ -474,4 +474,12 @@ mod tests { assert_eq!(buf.capacity, 4); assert_eq!(buf.to_vec(), alloc::vec![1, 2, 3, 4]); } + + #[test] + fn test_extend_from_slice() { + let mut buf = AllocRingBuffer::new(3); + let elems = [1, 2, 3]; + buf.extend_from_slice(&elems); + assert_eq!(buf.to_vec().as_slice(), elems) + } } diff --git a/src/with_alloc/vecdeque.rs b/src/with_alloc/vecdeque.rs index 978bbe5..8bc57af 100644 --- a/src/with_alloc/vecdeque.rs +++ b/src/with_alloc/vecdeque.rs @@ -282,3 +282,16 @@ impl FromIterator for GrowableAllocRingBuffer { Self(VecDeque::from_iter(iter)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extend_from_slice() { + let mut buf = GrowableAllocRingBuffer::new(); + let elems = [1, 2, 3]; + buf.extend_from_slice(&elems); + assert_eq!(buf.to_vec().as_slice(), elems) + } +} diff --git a/src/with_const_generics.rs b/src/with_const_generics.rs index 4f76e23..c198b24 100644 --- a/src/with_const_generics.rs +++ b/src/with_const_generics.rs @@ -502,5 +502,13 @@ mod tests { vec![1, 2, 3] ); } + + #[test] + fn test_extend_from_slice() { + let mut buf = ConstGenericRingBuffer::::new(); + let elems = [1, 2, 3]; + buf.extend_from_slice(&elems); + assert_eq!(buf.to_vec().as_slice(), elems) + } } }