From 2df5e2cb1e226c8d73606fed1667e0d94abe4df7 Mon Sep 17 00:00:00 2001 From: Alexey Gerasev Date: Tue, 1 Aug 2023 09:46:09 +0700 Subject: [PATCH] IntoIter and PopIter now associated types --- src/halves/cached.rs | 15 +++++++++- src/halves/direct.rs | 17 +++++++++-- src/halves/frozen.rs | 15 +++++++++- src/rb/local.rs | 12 +++++++- src/rb/shared.rs | 12 +++++++- src/rb/traits.rs | 5 +--- src/traits/consumer.rs | 63 +++++---------------------------------- src/traits/ring_buffer.rs | 2 +- 8 files changed, 75 insertions(+), 66 deletions(-) diff --git a/src/halves/cached.rs b/src/halves/cached.rs index db6dc51..5d617fc 100644 --- a/src/halves/cached.rs +++ b/src/halves/cached.rs @@ -4,7 +4,10 @@ use super::{ }; use crate::{ impl_consumer_traits, impl_producer_traits, - rb::traits::{RbRef, ToRbRef}, + rb::{ + iter::PopIter, + traits::{RbRef, ToRbRef}, + }, traits::{Consumer, Observe, Observer, Producer}, }; use core::{mem::MaybeUninit, num::NonZeroUsize}; @@ -142,6 +145,16 @@ impl Consumer for CachingCons { } r } + + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + unsafe { PopIter::new(self.frozen.into_rb_ref()) } + } + + type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a; + fn pop_iter(&mut self) -> Self::PopIter<'_> { + unsafe { PopIter::new(self.frozen.rb_ref().deref()) } + } } impl_producer_traits!(CachingProd); diff --git a/src/halves/direct.rs b/src/halves/direct.rs index d7a32b3..5a4d43a 100644 --- a/src/halves/direct.rs +++ b/src/halves/direct.rs @@ -1,7 +1,10 @@ use crate::{ delegate_observer, impl_consumer_traits, impl_producer_traits, - rb::traits::{RbRef, ToRbRef}, - traits::{Consumer, Observe, Observer, Producer}, + rb::{ + iter::PopIter, + traits::{RbRef, ToRbRef}, + }, + traits::{Consumer, Observe, Observer, Producer, RingBuffer}, }; /// Observer of ring buffer. @@ -91,6 +94,16 @@ impl Consumer for Cons { unsafe fn set_read_index(&self, value: usize) { self.rb().set_read_index(value) } + + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + unsafe { PopIter::new(self.rb) } + } + + type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a; + fn pop_iter(&mut self) -> Self::PopIter<'_> { + unsafe { PopIter::new(&self.rb.deref()) } + } } impl_producer_traits!(Prod); diff --git a/src/halves/frozen.rs b/src/halves/frozen.rs index 46d2948..399e396 100644 --- a/src/halves/frozen.rs +++ b/src/halves/frozen.rs @@ -2,7 +2,10 @@ use super::direct::{Cons, Obs, Prod}; use crate::{ - rb::traits::{RbRef, ToRbRef}, + rb::{ + iter::PopIter, + traits::{RbRef, ToRbRef}, + }, traits::{Consumer, Observe, Observer, Producer}, }; use core::{ @@ -81,6 +84,16 @@ impl Consumer for FrozenCons { unsafe fn set_read_index(&self, value: usize) { self.read.set(value); } + + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + unsafe { PopIter::new(self.into_rb_ref()) } + } + + type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a; + fn pop_iter(&mut self) -> Self::PopIter<'_> { + unsafe { PopIter::new(&self.rb.deref()) } + } } impl Producer for FrozenProd { diff --git a/src/rb/local.rs b/src/rb/local.rs index 07b27ac..e3c6336 100644 --- a/src/rb/local.rs +++ b/src/rb/local.rs @@ -1,4 +1,4 @@ -use super::{macros::rb_impl_init, traits::RbRef, utils::ranges}; +use super::{iter::PopIter, macros::rb_impl_init, traits::RbRef, utils::ranges}; #[cfg(feature = "alloc")] use crate::traits::Split; use crate::{ @@ -83,6 +83,16 @@ impl Consumer for LocalRb { unsafe fn set_read_index(&self, value: usize) { self.read.set(value); } + + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + unsafe { PopIter::new(self) } + } + + type PopIter<'a> = PopIter<&'a Self> where S: 'a; + fn pop_iter(&mut self) -> Self::PopIter<'_> { + unsafe { PopIter::new(self) } + } } impl RingBuffer for LocalRb {} diff --git a/src/rb/shared.rs b/src/rb/shared.rs index a6e16f6..264ada9 100644 --- a/src/rb/shared.rs +++ b/src/rb/shared.rs @@ -1,4 +1,4 @@ -use super::{macros::rb_impl_init, traits::RbRef, utils::ranges}; +use super::{iter::PopIter, macros::rb_impl_init, traits::RbRef, utils::ranges}; #[cfg(feature = "alloc")] use crate::traits::Split; use crate::{ @@ -111,6 +111,16 @@ impl Consumer for SharedRb { unsafe fn set_read_index(&self, value: usize) { self.read.store(value, Ordering::Release); } + + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + unsafe { PopIter::new(self) } + } + + type PopIter<'a> = PopIter<&'a Self> where S: 'a; + fn pop_iter(&mut self) -> Self::PopIter<'_> { + unsafe { PopIter::new(self) } + } } impl RingBuffer for SharedRb {} diff --git a/src/rb/traits.rs b/src/rb/traits.rs index 50618c3..2cadb01 100644 --- a/src/rb/traits.rs +++ b/src/rb/traits.rs @@ -9,10 +9,7 @@ pub unsafe trait RbRef: AsRef { } } -unsafe impl<'a, B: RingBuffer> RbRef for &'a B -where - B: RbRef, -{ +unsafe impl<'a, B: RingBuffer> RbRef for &'a B { type Target = B; fn deref(&self) -> &Self::Target { self diff --git a/src/traits/consumer.rs b/src/traits/consumer.rs index d26b7f8..edfe52e 100644 --- a/src/traits/consumer.rs +++ b/src/traits/consumer.rs @@ -115,14 +115,16 @@ pub trait Consumer: Observer { count } - fn into_iter(self) -> IntoIter { - IntoIter::new(self) - } + type IntoIter: Iterator::Item>; + + fn into_iter(self) -> Self::IntoIter; + + type PopIter<'a>: Iterator::Item> + 'a + where + Self: 'a; /// Returns an iterator that removes items one by one from the ring buffer. - fn pop_iter(&mut self) -> PopIter<'_, Self> { - PopIter::new(self) - } + fn pop_iter(&mut self) -> Self::PopIter<'_>; /// Returns a front-to-back iterator containing references to items in the ring buffer. /// @@ -232,55 +234,6 @@ impl Iterator for IntoIter { } } -/// An iterator that removes items from the ring buffer. -pub struct PopIter<'a, C: Consumer> { - target: &'a C, - slices: (&'a [MaybeUninit], &'a [MaybeUninit]), - len: usize, -} -impl<'a, C: Consumer> PopIter<'a, C> { - pub fn new(target: &'a mut C) -> Self { - let slices = target.occupied_slices(); - Self { - len: slices.0.len() + slices.1.len(), - slices, - target, - } - } -} -impl<'a, C: Consumer> Iterator for PopIter<'a, C> { - type Item = C::Item; - #[inline] - fn next(&mut self) -> Option { - match self.slices.0.len() { - 0 => None, - n => { - let item = unsafe { self.slices.0.get_unchecked(0).assume_init_read() }; - if n == 1 { - (self.slices.0, self.slices.1) = (self.slices.1, &[]); - } else { - self.slices.0 = unsafe { self.slices.0.get_unchecked(1..n) }; - } - Some(item) - } - } - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.len(), Some(self.len())) - } -} -impl<'a, C: Consumer> ExactSizeIterator for PopIter<'a, C> { - fn len(&self) -> usize { - self.slices.0.len() + self.slices.1.len() - } -} -impl<'a, C: Consumer> Drop for PopIter<'a, C> { - fn drop(&mut self) { - unsafe { self.target.advance_read_index(self.len - self.len()) }; - } -} - /// Iterator over ring buffer contents. /// /// *Please do not rely on actual type, it may change in future.* diff --git a/src/traits/ring_buffer.rs b/src/traits/ring_buffer.rs index dd72bc8..7308b1b 100644 --- a/src/traits/ring_buffer.rs +++ b/src/traits/ring_buffer.rs @@ -12,7 +12,7 @@ use super::{Consumer, Observer, Producer}; /// It allows us to distinguish situations when the buffer is empty (`read == write`) and when the buffer is full (`write - read` modulo `2 * capacity` equals to `capacity`) /// without using the space for an extra element in container. /// And obviously we cannot store more than `capacity` items in the buffer, so `write - read` modulo `2 * capacity` is not allowed to be greater than `capacity`. -pub trait RingBuffer: Observer + Consumer + Producer { +pub trait RingBuffer: Observer + Consumer + Producer + AsRef { /// Pushes an item to the ring buffer overwriting the latest item if the buffer is full. /// /// Returns overwritten item if overwriting took place.