use super::{
observer::{DelegateObserver, Observer},
utils::modulus,
};
use crate::utils::{move_uninit_slice, slice_as_uninit_mut, slice_assume_init_mut, slice_assume_init_ref};
use core::{iter::Chain, mem::MaybeUninit, ptr, slice};
#[cfg(feature = "std")]
use std::io::{self, Write};
pub trait Consumer: Observer {
unsafe fn set_read_index(&self, value: usize);
unsafe fn advance_read_index(&self, count: usize) {
self.set_read_index((self.read_index() + count) % modulus(self));
}
fn occupied_slices(&self) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
unsafe { self.unsafe_slices(self.read_index(), self.write_index()) }
}
unsafe fn occupied_slices_mut(&mut self) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
self.unsafe_slices_mut(self.read_index(), self.write_index())
}
#[inline]
fn as_slices(&self) -> (&[Self::Item], &[Self::Item]) {
unsafe {
let (left, right) = self.occupied_slices();
(slice_assume_init_ref(left), slice_assume_init_ref(right))
}
}
#[inline]
fn as_mut_slices(&mut self) -> (&mut [Self::Item], &mut [Self::Item]) {
unsafe {
let (left, right) = self.occupied_slices_mut();
(slice_assume_init_mut(left), slice_assume_init_mut(right))
}
}
#[inline]
fn first(&self) -> Option<&Self::Item> {
self.as_slices().0.first()
}
#[inline]
fn first_mut(&mut self) -> Option<&mut Self::Item> {
self.as_mut_slices().0.first_mut()
}
fn last(&self) -> Option<&Self::Item> {
let (first, second) = self.as_slices();
if second.is_empty() {
first.last()
} else {
second.last()
}
}
fn last_mut(&mut self) -> Option<&mut Self::Item> {
let (first, second) = self.as_mut_slices();
if second.is_empty() {
first.last_mut()
} else {
second.last_mut()
}
}
fn try_pop(&mut self) -> Option<Self::Item> {
if !self.is_empty() {
let elem = unsafe { self.occupied_slices().0.get_unchecked(0).assume_init_read() };
unsafe { self.advance_read_index(1) };
Some(elem)
} else {
None
}
}
fn pop_slice_uninit(&mut self, elems: &mut [MaybeUninit<Self::Item>]) -> usize {
let (left, right) = self.occupied_slices();
let count = if elems.len() < left.len() {
move_uninit_slice(elems, unsafe { left.get_unchecked(..elems.len()) });
elems.len()
} else {
let (left_elems, elems) = elems.split_at_mut(left.len());
move_uninit_slice(left_elems, left);
left.len()
+ if elems.len() < right.len() {
move_uninit_slice(elems, unsafe { right.get_unchecked(..elems.len()) });
elems.len()
} else {
move_uninit_slice(unsafe { elems.get_unchecked_mut(..right.len()) }, right);
right.len()
}
};
unsafe { self.advance_read_index(count) };
count
}
fn pop_slice(&mut self, elems: &mut [Self::Item]) -> usize
where
Self::Item: Copy,
{
self.pop_slice_uninit(unsafe { slice_as_uninit_mut(elems) })
}
fn pop_iter(&mut self) -> PopIter<Self> {
PopIter::new(self)
}
fn iter(&self) -> Iter<'_, Self> {
let (left, right) = self.as_slices();
left.iter().chain(right.iter())
}
fn iter_mut(&mut self) -> IterMut<'_, Self> {
let (left, right) = self.as_mut_slices();
left.iter_mut().chain(right.iter_mut())
}
fn skip(&mut self, count: usize) -> usize {
unsafe {
let (left, right) = self.occupied_slices_mut();
for elem in left.iter_mut().chain(right.iter_mut()).take(count) {
ptr::drop_in_place(elem.as_mut_ptr());
}
let actual_count = usize::min(count, left.len() + right.len());
self.advance_read_index(actual_count);
actual_count
}
}
fn clear(&mut self) -> usize {
unsafe {
let (left, right) = self.occupied_slices_mut();
for elem in left.iter_mut().chain(right.iter_mut()) {
ptr::drop_in_place(elem.as_mut_ptr());
}
let count = left.len() + right.len();
self.advance_read_index(count);
count
}
}
#[cfg(feature = "std")]
fn write_into<S: Write>(&mut self, writer: &mut S, count: Option<usize>) -> Option<io::Result<usize>>
where
Self: Consumer<Item = u8>,
{
let (left, _) = self.occupied_slices();
let count = usize::min(count.unwrap_or(left.len()), left.len());
if count == 0 {
return None;
}
let left_init = unsafe { slice_assume_init_ref(&left[..count]) };
let write_count = match writer.write(left_init) {
Ok(n) => n,
Err(e) => return Some(Err(e)),
};
assert!(write_count <= count);
unsafe { self.advance_read_index(write_count) };
Some(Ok(write_count))
}
}
pub struct IntoIter<C: Consumer + ?Sized> {
inner: C,
}
impl<C: Consumer> IntoIter<C> {
pub fn new(inner: C) -> Self {
Self { inner }
}
pub fn into_inner(self) -> C {
self.inner
}
}
impl<C: Consumer> Iterator for IntoIter<C> {
type Item = C::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.try_pop()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.inner.occupied_len(), None)
}
}
pub struct PopIter<'a, C: Consumer + ?Sized> {
inner: &'a C,
iter: Chain<slice::Iter<'a, MaybeUninit<C::Item>>, slice::Iter<'a, MaybeUninit<C::Item>>>,
count: usize,
len: usize,
}
impl<'a, C: Consumer + ?Sized> Drop for PopIter<'a, C> {
fn drop(&mut self) {
self.commit();
}
}
impl<'a, C: Consumer + ?Sized> PopIter<'a, C> {
pub fn new(inner: &'a mut C) -> Self {
let (len, iter) = {
let (left, right) = inner.occupied_slices();
(left.len() + right.len(), left.iter().chain(right))
};
Self {
inner,
iter,
count: 0,
len,
}
}
pub fn commit(&mut self) {
unsafe { self.inner.advance_read_index(self.count) };
self.count = 0;
}
}
impl<'a, C: Consumer> Iterator for PopIter<'a, C> {
type Item = C::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|item| {
self.count += 1;
unsafe { item.assume_init_read() }
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remain = self.len - self.count;
(remain, Some(remain))
}
}
impl<'a, C: Consumer> ExactSizeIterator for PopIter<'a, C> {}
#[allow(type_alias_bounds)]
pub type Iter<'a, C: Consumer> = Chain<slice::Iter<'a, C::Item>, slice::Iter<'a, C::Item>>;
#[allow(type_alias_bounds)]
pub type IterMut<'a, C: Consumer> = Chain<slice::IterMut<'a, C::Item>, slice::IterMut<'a, C::Item>>;
pub trait DelegateConsumer: DelegateObserver
where
Self::Base: Consumer,
{
}
impl<D: DelegateConsumer> Consumer for D
where
D::Base: Consumer,
{
#[inline]
unsafe fn set_read_index(&self, value: usize) {
self.base().set_read_index(value)
}
#[inline]
unsafe fn advance_read_index(&self, count: usize) {
self.base().advance_read_index(count)
}
#[inline]
fn occupied_slices(&self) -> (&[core::mem::MaybeUninit<Self::Item>], &[core::mem::MaybeUninit<Self::Item>]) {
self.base().occupied_slices()
}
#[inline]
unsafe fn occupied_slices_mut(&mut self) -> (&mut [core::mem::MaybeUninit<Self::Item>], &mut [core::mem::MaybeUninit<Self::Item>]) {
self.base_mut().occupied_slices_mut()
}
#[inline]
fn as_slices(&self) -> (&[Self::Item], &[Self::Item]) {
self.base().as_slices()
}
#[inline]
fn as_mut_slices(&mut self) -> (&mut [Self::Item], &mut [Self::Item]) {
self.base_mut().as_mut_slices()
}
#[inline]
fn try_pop(&mut self) -> Option<Self::Item> {
self.base_mut().try_pop()
}
#[inline]
fn pop_slice(&mut self, elems: &mut [Self::Item]) -> usize
where
Self::Item: Copy,
{
self.base_mut().pop_slice(elems)
}
#[inline]
fn iter(&self) -> Iter<'_, Self> {
self.base().iter()
}
#[inline]
fn iter_mut(&mut self) -> IterMut<'_, Self> {
self.base_mut().iter_mut()
}
#[inline]
fn skip(&mut self, count: usize) -> usize {
self.base_mut().skip(count)
}
#[inline]
fn clear(&mut self) -> usize {
self.base_mut().clear()
}
}
macro_rules! impl_consumer_traits {
($type:ident $(< $( $param:tt $( : $first_bound:tt $(+ $next_bound:tt )* )? ),+ >)?) => {
impl $(< $( $param $( : $first_bound $(+ $next_bound )* )? ),+ >)? core::iter::IntoIterator for $type $(< $( $param ),+ >)? where Self: Sized {
type Item = <Self as $crate::traits::Observer>::Item;
type IntoIter = $crate::traits::consumer::IntoIter<Self>;
fn into_iter(self) -> Self::IntoIter {
$crate::traits::consumer::IntoIter::new(self)
}
}
#[cfg(feature = "std")]
impl $(< $( $param $( : $first_bound $(+ $next_bound )* )? ),+ >)? std::io::Read for $type $(< $( $param ),+ >)?
where
Self: $crate::traits::Consumer<Item = u8>,
{
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let n = self.pop_slice(buf);
if n == 0 {
Err(std::io::ErrorKind::WouldBlock.into())
} else {
Ok(n)
}
}
}
};
}
pub(crate) use impl_consumer_traits;