diff --git a/src/traits/consumer.rs b/src/traits/consumer.rs index a809789..a62bc46 100644 --- a/src/traits/consumer.rs +++ b/src/traits/consumer.rs @@ -1,6 +1,6 @@ use super::{observer::Observer, utils::modulus}; use crate::utils::{slice_assume_init_mut, slice_assume_init_ref, write_uninit_slice}; -use core::{iter::Chain, mem::MaybeUninit, ptr, slice}; +use core::{iter::Chain, marker::PhantomData, mem::MaybeUninit, ptr, slice}; #[cfg(feature = "std")] use std::io::{self, Write}; @@ -106,12 +106,11 @@ pub trait Consumer: Observer { count } - fn into_iter(self) -> IntoIter { - IntoIter::new(self) - } - /// Returns an iterator that removes items one by one from the ring buffer. - fn pop_iter(&mut self) -> PopIter<'_, Self> { + fn pop_iter(&mut self) -> PopIter<&mut Self, Self> + where + Self: AsMut + AsRef, + { PopIter::new(self) } @@ -214,74 +213,34 @@ pub trait Consumer: Observer { } } -pub struct IntoIter(C); -impl IntoIter { - pub fn new(inner: C) -> Self { - Self(inner) - } - pub fn into_inner(self) -> C { - self.0 - } -} -impl Iterator for IntoIter { - type Item = C::Item; - - #[inline] - fn next(&mut self) -> Option { - self.0.try_pop() - } - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.0.occupied_len(), None) - } -} - /// 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, +pub struct PopIter + AsRef, C: Consumer> { + inner: U, + _ghost: PhantomData, } -impl<'a, C: Consumer> PopIter<'a, C> { - pub fn new(target: &'a mut C) -> Self { - let slices = target.occupied_slices(); + +impl + AsRef, C: Consumer> PopIter { + pub fn new(inner: U) -> Self { Self { - len: slices.0.len() + slices.1.len(), - slices, - target, + inner, + _ghost: PhantomData, } } + pub fn into_inner(self) -> U { + self.inner + } } -impl<'a, C: Consumer> Iterator for PopIter<'a, C> { + +impl + AsRef, C: Consumer> Iterator for PopIter { 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) - } - } + self.inner.as_mut().try_pop() } #[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()) }; + (self.inner.as_ref().occupied_len(), None) } } diff --git a/src/wrap/caching.rs b/src/wrap/caching.rs index 870433f..0ca4ab5 100644 --- a/src/wrap/caching.rs +++ b/src/wrap/caching.rs @@ -1,5 +1,6 @@ use super::{direct::Obs, frozen::Frozen}; use crate::{ + consumer::PopIter, rb::traits::{RbRef, ToRbRef}, traits::{Consumer, Observer, Producer}, }; @@ -43,6 +44,17 @@ impl ToRbRef for Caching { } } +impl AsRef for Caching { + fn as_ref(&self) -> &Self { + self + } +} +impl AsMut for Caching { + fn as_mut(&mut self) -> &mut Self { + self + } +} + impl Observer for Caching { type Item = ::Item; @@ -130,6 +142,14 @@ where } } +impl IntoIterator for CachingCons { + type Item = ::Item; + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + PopIter::new(self) + } +} + #[cfg(feature = "std")] impl io::Read for CachingCons where diff --git a/src/wrap/direct.rs b/src/wrap/direct.rs index fbaf035..6593229 100644 --- a/src/wrap/direct.rs +++ b/src/wrap/direct.rs @@ -1,5 +1,6 @@ use super::frozen::Frozen; use crate::{ + consumer::PopIter, rb::traits::{RbRef, ToRbRef}, traits::{consumer::Consumer, producer::Producer, Observer}, }; @@ -51,6 +52,17 @@ impl ToRbRef for Direct { } } +impl AsRef for Direct { + fn as_ref(&self) -> &Self { + self + } +} +impl AsMut for Direct { + fn as_mut(&mut self) -> &mut Self { + self + } +} + impl Observer for Direct { type Item = ::Item; @@ -107,6 +119,14 @@ where } } +impl IntoIterator for Cons { + type Item = ::Item; + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + PopIter::new(self) + } +} + #[cfg(feature = "std")] impl io::Read for Cons where diff --git a/src/wrap/frozen.rs b/src/wrap/frozen.rs index 2c29069..cfe4ac6 100644 --- a/src/wrap/frozen.rs +++ b/src/wrap/frozen.rs @@ -1,5 +1,6 @@ use super::direct::Obs; use crate::{ + consumer::PopIter, rb::traits::{RbRef, ToRbRef}, traits::{Consumer, Observer, Producer}, }; @@ -63,6 +64,17 @@ impl ToRbRef for Frozen { } } +impl AsRef for Frozen { + fn as_ref(&self) -> &Self { + self + } +} +impl AsMut for Frozen { + fn as_mut(&mut self) -> &mut Self { + self + } +} + impl Frozen { /// Commit changes to the ring buffer. pub fn commit(&self) { @@ -169,6 +181,14 @@ where } } +impl IntoIterator for FrozenCons { + type Item = ::Item; + type IntoIter = PopIter; + fn into_iter(self) -> Self::IntoIter { + PopIter::new(self) + } +} + #[cfg(feature = "std")] impl io::Read for FrozenCons where