use crate::CircularBuffer;
use crate::Inner;
use crate::Iter;
use crate::IterMut;
use core::borrow::Borrow;
use core::borrow::BorrowMut;
use core::mem;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::ops::DerefMut;
use core::ops::Index;
use core::ops::IndexMut;
use core::ptr;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::boxed::Box;
pub use crate::iter::fixed::IntoIter;
#[repr(transparent)]
pub struct FixedCircularBuffer<T, const N: usize> {
inner: Inner<[MaybeUninit<T>; N]>,
}
impl<T, const N: usize> FixedCircularBuffer<T, N> {
#[inline]
#[must_use]
pub const fn new() -> Self {
Self {
inner: Inner {
size: 0,
start: 0,
items: [const { MaybeUninit::uninit() }; N],
},
}
}
#[must_use]
#[cfg(feature = "alloc")]
pub fn boxed() -> Box<Self> {
let mut uninit: Box<MaybeUninit<Self>> = Box::new_uninit();
let ptr = uninit.as_mut_ptr();
unsafe {
core::ptr::addr_of_mut!((*ptr).inner.size).write(0);
core::ptr::addr_of_mut!((*ptr).inner.start).write(0);
}
unsafe { uninit.assume_init() }
}
#[inline]
#[must_use]
pub const fn as_circular_buffer(&self) -> &CircularBuffer<T> {
let inner_unsized: &Inner<[MaybeUninit<T>]> = &self.inner;
unsafe { mem::transmute(inner_unsized) }
}
#[inline]
#[must_use]
pub const fn as_mut_circular_buffer(&mut self) -> &mut CircularBuffer<T> {
let inner_unsized: &mut Inner<[MaybeUninit<T>]> = &mut self.inner;
unsafe { mem::transmute(inner_unsized) }
}
}
impl<T, const N: usize> Default for FixedCircularBuffer<T, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<const N: usize, const M: usize, T> From<[T; M]> for FixedCircularBuffer<T, N> {
fn from(mut arr: [T; M]) -> Self {
let size = if N >= M { M } else { N };
let mut elems = [const { MaybeUninit::uninit() }; N];
let (discard, copy) = arr.split_at_mut(M - size);
debug_assert_eq!(copy.len(), size);
let elems_ptr = elems.as_mut_ptr();
let discard_ptr = discard as *mut [T];
let copy_ptr = copy.as_ptr() as *const MaybeUninit<T>;
unsafe {
copy_ptr.copy_to_nonoverlapping(elems_ptr, size);
}
mem::forget(arr);
unsafe {
ptr::drop_in_place(discard_ptr);
}
Self {
inner: Inner {
size,
start: 0,
items: elems,
},
}
}
}
impl<T, const N: usize> FromIterator<T> for FixedCircularBuffer<T, N> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
let mut buf = Self::new();
iter.into_iter().for_each(|item| {
buf.push_back(item);
});
buf
}
}
impl<T, const N: usize> Deref for FixedCircularBuffer<T, N> {
type Target = CircularBuffer<T>;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_circular_buffer()
}
}
impl<T, const N: usize> DerefMut for FixedCircularBuffer<T, N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_circular_buffer()
}
}
impl<T, const N: usize> Borrow<CircularBuffer<T>> for FixedCircularBuffer<T, N> {
#[inline]
fn borrow(&self) -> &CircularBuffer<T> {
self.as_circular_buffer()
}
}
impl<T, const N: usize> BorrowMut<CircularBuffer<T>> for FixedCircularBuffer<T, N> {
#[inline]
fn borrow_mut(&mut self) -> &mut CircularBuffer<T> {
self.as_mut_circular_buffer()
}
}
impl<T, const N: usize> AsRef<CircularBuffer<T>> for FixedCircularBuffer<T, N> {
#[inline]
fn as_ref(&self) -> &CircularBuffer<T> {
self.as_circular_buffer()
}
}
impl<T, const N: usize> AsMut<CircularBuffer<T>> for FixedCircularBuffer<T, N> {
#[inline]
fn as_mut(&mut self) -> &mut CircularBuffer<T> {
self.as_mut_circular_buffer()
}
}
impl<T, const N: usize> Extend<T> for FixedCircularBuffer<T, N> {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
self.deref_mut().extend(iter);
}
}
impl<'a, T, const N: usize> Extend<&'a T> for FixedCircularBuffer<T, N>
where
T: Copy,
{
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = &'a T>,
{
self.deref_mut().extend(iter);
}
}
impl<T, const N: usize> Index<usize> for FixedCircularBuffer<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.deref().index(index)
}
}
impl<T, const N: usize> IndexMut<usize> for FixedCircularBuffer<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.deref_mut().index_mut(index)
}
}
impl<T, const N: usize> IntoIterator for FixedCircularBuffer<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self)
}
}
impl<'a, T, const N: usize> IntoIterator for &'a FixedCircularBuffer<T, N> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Iter::new(self)
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut FixedCircularBuffer<T, N> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IterMut::new(self)
}
}
impl<T, const N: usize> Clone for FixedCircularBuffer<T, N>
where
T: Clone,
{
fn clone(&self) -> Self {
let (front, back) = self.as_slices();
let mut buf = Self::new();
buf.extend_from_slice(front);
buf.extend_from_slice(back);
buf
}
fn clone_from(&mut self, other: &Self) {
let (front, back) = other.as_slices();
self.clear();
self.extend_from_slice(front);
self.extend_from_slice(back);
}
}
impl<T, const N: usize> Drop for FixedCircularBuffer<T, N> {
#[inline]
fn drop(&mut self) {
self.clear();
}
}