use super::{
Based,
utils::{add_mod, modulus, sub_mod},
};
use core::{mem::MaybeUninit, num::NonZeroUsize};
pub trait Observer {
type Item: Sized;
fn capacity(&self) -> NonZeroUsize;
fn read_index(&self) -> usize;
fn write_index(&self) -> usize;
unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]);
#[allow(clippy::mut_from_ref)]
unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]);
fn read_is_held(&self) -> bool;
fn write_is_held(&self) -> bool;
fn occupied_len(&self) -> usize {
let modulus = modulus(self);
sub_mod(self.write_index(), self.read_index(), modulus)
}
fn vacant_len(&self) -> usize {
let modulus = modulus(self);
sub_mod(
add_mod(self.read_index(), self.capacity().get(), modulus),
self.write_index(),
modulus,
)
}
#[inline]
fn is_empty(&self) -> bool {
self.read_index() == self.write_index()
}
#[inline]
fn is_full(&self) -> bool {
self.vacant_len() == 0
}
}
pub trait DelegateObserver: Based
where
Self::Base: Observer,
{
}
impl<D: DelegateObserver> Observer for D
where
D::Base: Observer,
{
type Item = <D::Base as Observer>::Item;
#[inline]
fn capacity(&self) -> NonZeroUsize {
self.base().capacity()
}
#[inline]
fn read_index(&self) -> usize {
self.base().read_index()
}
#[inline]
fn write_index(&self) -> usize {
self.base().write_index()
}
#[inline]
unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
unsafe { self.base().unsafe_slices(start, end) }
}
#[inline]
unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
unsafe { self.base().unsafe_slices_mut(start, end) }
}
#[inline]
fn read_is_held(&self) -> bool {
self.base().read_is_held()
}
#[inline]
fn write_is_held(&self) -> bool {
self.base().write_is_held()
}
#[inline]
fn occupied_len(&self) -> usize {
self.base().occupied_len()
}
#[inline]
fn vacant_len(&self) -> usize {
self.base().vacant_len()
}
#[inline]
fn is_empty(&self) -> bool {
self.base().is_empty()
}
#[inline]
fn is_full(&self) -> bool {
self.base().is_full()
}
}