use core::fmt::{self, Debug, Display};
use core::num::Wrapping;
use crate::{storage::Slot, RingBuffer, Storage};
pub mod prop;
mod tests;
pub struct MaskingBuffer<S: Storage + ?Sized> {
cur: Wrapping<usize>,
len: usize,
data: S,
}
impl<S: Storage> MaskingBuffer<S> {
pub fn new(storage: S) -> Result<Self, Error> {
if storage.cap().is_power_of_two() {
Ok(unsafe { Self::new_unchecked(storage) })
} else {
Err(Error::NotPowerOfTwo)
}
}
pub unsafe fn new_unchecked(storage: S) -> Self {
Self { cur: Wrapping(0), len: 0, data: storage }
}
}
impl<S: Storage + ?Sized> MaskingBuffer<S> {
fn mask(&self, off: Wrapping<usize>) -> usize {
off.0 & (self.cap() - 1)
}
}
impl<S: Storage + ?Sized> RingBuffer for MaskingBuffer<S> {
type Item = S::Item;
fn cap(&self) -> usize {
self.data.cap()
}
fn len(&self) -> usize {
self.len
}
fn get(&self, off: usize) -> Option<&Self::Item> {
if off >= self.len { return None; }
let off = self.mask(self.cur + Wrapping(off));
Some(unsafe { self.data.get().get_unchecked(off).get_ref() })
}
fn get_mut(&mut self, off: usize) -> Option<&mut Self::Item> {
if off >= self.len { return None; }
let off = self.mask(self.cur + Wrapping(off));
Some(unsafe { self.data.get_mut().get_unchecked_mut(off).get_mut() })
}
unsafe fn get_disjoint_mut(&self, off: usize) -> &mut Self::Item {
let off = self.mask(self.cur + Wrapping(off));
unsafe { self.data.get().get_unchecked(off).get_int_mut() }
}
fn enqueue(&mut self, item: Self::Item) -> Option<Self::Item> {
let is_full = self.is_full();
let off = self.mask(self.cur + Wrapping(self.len));
let ptr = unsafe { self.data.get_mut().get_unchecked_mut(off) };
let res = is_full.then(|| {
self.len -= 1;
self.cur += 1;
unsafe { ptr.take() }
});
*ptr = Slot::new(item);
self.len += 1;
res
}
fn dequeue(&mut self) -> Option<Self::Item> {
if self.is_empty() { return None; }
let off = self.mask(self.cur);
let item = unsafe { self.data.get_mut().get_unchecked_mut(off).take() };
self.cur += 1;
self.len -= 1;
Some(item)
}
fn skip_one(&mut self) {
if self.is_empty() { return; }
let off = self.mask(self.cur + Wrapping(self.len));
unsafe { self.data.get_mut().get_unchecked_mut(off).drop_in_place(); }
self.cur += 1;
self.len -= 1;
}
}
impl<T: Clone, S: Storage<Item = T> + Clone> Clone for MaskingBuffer<S> {
fn clone(&self) -> Self {
let mut res = unsafe { Self::new_unchecked(self.data.clone()) };
for item in self.iter() {
res.enqueue(item.clone());
}
res
}
}
impl<S: Storage> Debug for MaskingBuffer<S>
where S: Debug, S::Item: Debug {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct Items<'a, S: Storage>(&'a MaskingBuffer<S>);
impl<'a, S: Storage> Debug for Items<'a, S>
where S::Item: Debug {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.iter()).finish()
}
}
f.debug_struct("MaskingBuffer")
.field("cur", &self.cur)
.field("len", &self.len)
.field("data", &self.data)
.field("items", &Items(self))
.finish()
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Error {
NotPowerOfTwo,
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotPowerOfTwo => write!(f,
"An attempt was made to create a `MaskingBuffer` with a \
capacity that is not a power of two"),
}
}
}