#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
#![deny(missing_docs)]
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc as std;
#[cfg(feature = "std")]
extern crate std;
use core::{
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
iter::{once, repeat_with, Chain, Once},
mem::{self, ManuallyDrop, MaybeUninit},
ops::{self, Index, IndexMut, Range, RangeBounds},
ptr, slice,
};
use generic_array::GenericArray;
use macros::*;
pub use generic_array::{typenum, ArrayLength, ConstArrayLength, IntoArrayLength};
pub use into_iter::IntoIter;
pub use iter::Iter;
pub use iter_mut::IterMut;
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub use unstable::ExtractIf;
mod drain;
mod into_iter;
#[cfg(feature = "std")]
mod io;
mod iter;
mod iter_mut;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
mod serde;
#[cfg(all(test, any(feature = "std", feature = "alloc")))]
mod heap_tests;
#[cfg(test)]
mod tests;
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
mod unstable;
mod macros;
pub use generic_array as array;
pub type ConstGenericArrayDeque<T, const N: usize> = GenericArrayDeque<T, ConstArrayLength<N>>;
pub struct GenericArrayDeque<T, N>
where
N: ArrayLength,
{
array: GenericArray<MaybeUninit<T>, N>,
head: usize,
len: usize,
}
impl<T, N> Clone for GenericArrayDeque<T, N>
where
T: Clone,
N: ArrayLength,
{
fn clone(&self) -> Self {
let mut deq = Self::new();
for item in self.iter() {
let cloned = item.clone();
unsafe {
deq.ptr_mut().add(deq.len).write(MaybeUninit::new(cloned));
}
deq.len += 1;
}
deq
}
fn clone_from(&mut self, source: &Self) {
self.clear();
for item in source.iter() {
let cloned = item.clone();
unsafe {
self.ptr_mut().add(self.len).write(MaybeUninit::new(cloned));
}
self.len += 1;
}
}
}
impl<T, N> Default for GenericArrayDeque<T, N>
where
N: ArrayLength,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn default() -> Self {
Self::new()
}
}
impl<T: fmt::Debug, N: ArrayLength> fmt::Debug for GenericArrayDeque<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T: PartialEq, N1: ArrayLength, N2: ArrayLength> PartialEq<GenericArrayDeque<T, N2>>
for GenericArrayDeque<T, N1>
{
fn eq(&self, other: &GenericArrayDeque<T, N2>) -> bool {
if self.len != other.len() {
return false;
}
let (sa, sb) = self.as_slices();
let (oa, ob) = other.as_slices();
if sa.len() == oa.len() {
sa == oa && sb == ob
} else if sa.len() < oa.len() {
let front = sa.len();
let mid = oa.len() - front;
let (oa_front, oa_mid) = oa.split_at(front);
let (sb_mid, sb_back) = sb.split_at(mid);
debug_assert_eq!(sa.len(), oa_front.len());
debug_assert_eq!(sb_mid.len(), oa_mid.len());
debug_assert_eq!(sb_back.len(), ob.len());
sa == oa_front && sb_mid == oa_mid && sb_back == ob
} else {
let front = oa.len();
let mid = sa.len() - front;
let (sa_front, sa_mid) = sa.split_at(front);
let (ob_mid, ob_back) = ob.split_at(mid);
debug_assert_eq!(sa_front.len(), oa.len());
debug_assert_eq!(sa_mid.len(), ob_mid.len());
debug_assert_eq!(sb.len(), ob_back.len());
sa_front == oa && sa_mid == ob_mid && sb == ob_back
}
}
}
impl<T: Eq, N: ArrayLength> Eq for GenericArrayDeque<T, N> {}
macro_rules! __impl_slice_eq1 {
([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => {
impl<T, U, L: ArrayLength, $($vars)*> PartialEq<$rhs> for $lhs
where
T: PartialEq<U>,
$($constraints)*
{
fn eq(&self, other: &$rhs) -> bool {
if self.len() != other.len() {
return false;
}
let (sa, sb) = self.as_slices();
let (oa, ob) = other[..].split_at(sa.len());
sa == oa && sb == ob
}
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
__impl_slice_eq1! { [] GenericArrayDeque<T, L>, std::vec::Vec<U>, }
__impl_slice_eq1! { [] GenericArrayDeque<T, L>, &[U], }
__impl_slice_eq1! { [] GenericArrayDeque<T, L>, &mut [U], }
__impl_slice_eq1! { [const N: usize] GenericArrayDeque<T, L>, [U; N], }
__impl_slice_eq1! { [const N: usize] GenericArrayDeque<T, L>, &[U; N], }
__impl_slice_eq1! { [const N: usize] GenericArrayDeque<T, L>, &mut [U; N], }
impl<T: PartialOrd, N: ArrayLength> PartialOrd for GenericArrayDeque<T, N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T: Ord, N: ArrayLength> Ord for GenericArrayDeque<T, N> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
impl<T: Hash, N: ArrayLength> Hash for GenericArrayDeque<T, N> {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(self.len);
self.iter().for_each(|elem| elem.hash(state));
}
}
impl<T, N: ArrayLength> Index<usize> for GenericArrayDeque<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &T {
self.get(index).expect("Out of bounds access")
}
}
impl<T, N: ArrayLength> IndexMut<usize> for GenericArrayDeque<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
self.get_mut(index).expect("Out of bounds access")
}
}
impl<T, N: ArrayLength> IntoIterator for GenericArrayDeque<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> IntoIter<T, N> {
IntoIter::new(self)
}
}
impl<'a, T, N: ArrayLength> IntoIterator for &'a GenericArrayDeque<T, N> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
impl<'a, T, N: ArrayLength> IntoIterator for &'a mut GenericArrayDeque<T, N> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
impl<T, N: ArrayLength, const SIZE: usize> TryFrom<[T; SIZE]> for GenericArrayDeque<T, N> {
type Error = [T; SIZE];
#[cfg_attr(not(tarpaulin), inline(always))]
fn try_from(arr: [T; SIZE]) -> Result<Self, Self::Error> {
Self::try_from_array(arr)
}
}
impl<T, N: ArrayLength> From<GenericArray<T, N>> for GenericArrayDeque<T, N> {
fn from(arr: GenericArray<T, N>) -> Self {
let mut deq = Self::new();
let arr = ManuallyDrop::new(arr);
if mem::size_of::<T>() != 0 {
unsafe {
ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr_mut() as _, N::USIZE);
}
}
deq.head = 0;
deq.len = N::USIZE;
deq
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
const _: () = {
#[allow(unused_imports)]
use std::{collections::VecDeque, vec::Vec};
impl<T, N: ArrayLength> GenericArrayDeque<T, N> {
pub fn try_from_vec(vec: Vec<T>) -> Result<Self, Vec<T>> {
if vec.len() > N::USIZE {
return Err(vec);
}
let mut vec = ManuallyDrop::new(vec);
let ptr = vec.as_mut_ptr();
let len = vec.len();
let cap = vec.capacity();
let mut deq = GenericArray::uninit();
unsafe {
ptr::copy_nonoverlapping(ptr, deq.as_mut_slice().as_mut_ptr() as *mut T, len);
drop(Vec::from_raw_parts(ptr, 0, cap));
}
Ok(Self {
array: deq,
head: 0,
len,
})
}
}
impl<T, N: ArrayLength> TryFrom<Vec<T>> for GenericArrayDeque<T, N> {
type Error = Vec<T>;
#[cfg_attr(not(tarpaulin), inline(always))]
fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
Self::try_from_vec(vec)
}
}
impl<T, N: ArrayLength> TryFrom<VecDeque<T>> for GenericArrayDeque<T, N> {
type Error = VecDeque<T>;
#[cfg_attr(not(tarpaulin), inline(always))]
fn try_from(vec_deq: VecDeque<T>) -> Result<Self, Self::Error> {
if vec_deq.len() > N::USIZE {
return Err(vec_deq);
}
let mut deq = GenericArray::uninit();
let len = vec_deq.len();
for (i, item) in vec_deq.into_iter().enumerate() {
deq[i].write(item);
}
Ok(Self {
array: deq,
head: 0,
len,
})
}
}
impl<T, N: ArrayLength> From<GenericArrayDeque<T, N>> for Vec<T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(deq: GenericArrayDeque<T, N>) -> Self {
let mut vec = Vec::with_capacity(deq.len());
for item in deq.into_iter() {
vec.push(item);
}
vec
}
}
impl<T, N: ArrayLength> From<GenericArrayDeque<T, N>> for VecDeque<T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(deq: GenericArrayDeque<T, N>) -> Self {
let mut vec = VecDeque::with_capacity(deq.len());
for item in deq.into_iter() {
vec.push_back(item);
}
vec
}
}
};
impl<T, N> GenericArrayDeque<T, N>
where
N: ArrayLength,
{
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new() -> Self {
Self {
array: GenericArray::uninit(),
head: 0,
len: 0,
}
}
#[inline(always)]
#[rustversion::attr(since(1.81), const)]
pub fn from_array<const U: usize>(array: [T; U]) -> Self
where
typenum::Const<U>: IntoArrayLength<ArrayLength = N>,
{
let ptr = array.as_slice().as_ptr();
mem::forget(array);
Self {
array: GenericArray::from_array(unsafe { ptr.cast::<[MaybeUninit<T>; U]>().read() }),
head: 0,
len: U,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn try_from_array<const SIZE: usize>(arr: [T; SIZE]) -> Result<Self, [T; SIZE]> {
if SIZE > N::USIZE {
return Err(arr);
}
let ptr = arr.as_ptr();
mem::forget(arr);
unsafe {
let mut array = GenericArray::uninit();
ptr::copy_nonoverlapping(ptr, array.as_mut_slice().as_mut_ptr() as _, SIZE);
Ok(Self {
array,
head: 0,
len: SIZE,
})
}
}
#[allow(clippy::type_complexity)]
pub fn try_from_iter<I: IntoIterator<Item = T>>(
iter: I,
) -> Result<Self, (Self, Chain<Once<T>, I::IntoIter>)> {
let mut deq = Self::new();
let mut iterator = iter.into_iter();
for idx in 0..N::USIZE {
match iterator.next() {
Some(value) => {
deq.array[idx].write(value);
deq.len += 1;
}
None => return Ok(deq),
}
}
match iterator.next() {
None => Ok(deq),
Some(value) => Err((deq, once(value).chain(iterator))),
}
}
pub fn try_extend_from_iter<I: IntoIterator<Item = T>>(
&mut self,
iter: I,
) -> Option<Chain<Once<T>, I::IntoIter>> {
let mut iterator = iter.into_iter();
for idx in self.len..N::USIZE {
let value = iterator.next()?;
let idx = self.to_physical_idx(idx);
self.array[idx].write(value);
self.len += 1;
}
iterator.next().map(|value| once(value).chain(iterator))
}
pub fn try_from_exact_iter<I>(iter: I) -> Result<Self, I::IntoIter>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
let iter = iter.into_iter();
if iter.len() > N::USIZE {
return Err(iter);
}
let mut deq = Self::new();
for value in iter {
if deq.len == N::USIZE {
break;
}
deq.array[deq.len].write(value);
deq.len += 1;
}
Ok(deq)
}
pub fn try_extend_from_exact_iter<I>(&mut self, iter: I) -> Option<I::IntoIter>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
let iter = iter.into_iter();
if iter.len() > self.remaining_capacity() {
return Some(iter);
}
for value in iter {
if self.len == N::USIZE {
break;
}
let idx = self.to_physical_idx(self.len);
self.array[idx].write(value);
self.len += 1;
}
None
}
pub unsafe fn from_iter_unchecked<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut deq = Self::new();
let mut iterator = iter.into_iter();
for idx in 0..N::USIZE {
match iterator.next() {
Some(value) => {
deq.array[idx].write(value);
deq.len += 1;
}
None => break,
}
}
deq
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn capacity(&self) -> usize {
N::USIZE
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn len(&self) -> usize {
self.len
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn remaining_capacity(&self) -> usize {
debug_assert!(self.len <= self.capacity());
self.capacity() - self.len
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_full(&self) -> bool {
self.len == self.capacity()
}
#[inline]
pub fn range<R>(&self, range: R) -> Iter<'_, T>
where
R: RangeBounds<usize>,
{
let (a_range, b_range) = self.slice_ranges(range, self.len);
let a = unsafe { &*self.buffer_range(a_range) };
let b = unsafe { &*self.buffer_range(b_range) };
Iter::new(a.iter(), b.iter())
}
#[inline]
pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
where
R: RangeBounds<usize>,
{
let (a_range, b_range) = self.slice_ranges(range, self.len);
let base = self.ptr_mut();
let (a, b) = unsafe {
let a_ptr = ptr::slice_from_raw_parts_mut(
base.add(a_range.start) as *mut T,
a_range.end - a_range.start,
);
let b_ptr = ptr::slice_from_raw_parts_mut(
base.add(b_range.start) as *mut T,
b_range.end - b_range.start,
);
(&mut *a_ptr, &mut *b_ptr)
};
IterMut::new(a.iter_mut(), b.iter_mut())
}
pub fn iter(&self) -> Iter<'_, T> {
let (a, b) = self.as_slices();
Iter::new(a.iter(), b.iter())
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
let (a, b) = self.as_mut_slices();
IterMut::new(a.iter_mut(), b.iter_mut())
}
#[inline]
#[must_use = "use `.truncate()` if you don't need the other half"]
#[rustversion::attr(since(1.83), const)]
pub fn split_off(&mut self, at: usize) -> Self {
let len = self.len;
assert!(at <= len, "`at` out of bounds");
let other_len = len - at;
let mut other = Self::new();
unsafe {
let (first_half, second_half) = self.as_slices();
let first_len = first_half.len();
let second_len = second_half.len();
if at < first_len {
let amount_in_first = first_len - at;
ptr::copy_nonoverlapping(
first_half.as_ptr().add(at),
other.ptr_mut() as _,
amount_in_first,
);
ptr::copy_nonoverlapping(
second_half.as_ptr(),
other.ptr_mut().add(amount_in_first) as _,
second_len,
);
} else {
let offset = at - first_len;
let amount_in_second = second_len - offset;
ptr::copy_nonoverlapping(
second_half.as_ptr().add(offset),
other.ptr_mut() as _,
amount_in_second,
);
}
}
self.len = at;
other.len = other_len;
other
}
#[inline]
#[rustversion::attr(since(1.83), const)]
pub fn append(&mut self, other: &mut Self) -> bool {
if self.len + other.len > self.capacity() {
return false;
}
if mem::size_of::<T>() == 0 {
match self.len.checked_add(other.len) {
Some(new_len) => self.len = new_len,
None => panic!("capacity overflow"),
}
other.len = 0;
other.head = 0;
return true;
}
unsafe {
let (left, right) = other.as_slices();
self.copy_slice(self.to_physical_idx(self.len), left);
self.copy_slice(self.to_physical_idx(self.len + left.len()), right);
}
self.len += other.len;
other.len = 0;
other.head = 0;
true
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn as_slices(&self) -> (&[T], &[T]) {
let (a_range, b_range) = self.slice_full_ranges();
unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) }
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
let (a_range, b_range) = self.slice_full_ranges();
let base = self.ptr_mut();
unsafe {
let a_ptr = ptr::slice_from_raw_parts_mut(
base.add(a_range.start) as *mut T,
a_range.end - a_range.start,
);
let b_ptr = ptr::slice_from_raw_parts_mut(
base.add(b_range.start) as *mut T,
b_range.end - b_range.start,
);
(&mut *a_ptr, &mut *b_ptr)
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn front(&self) -> Option<&T> {
self.get(0)
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.84), const)]
pub fn front_mut(&mut self) -> Option<&mut T> {
self.get_mut(0)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn back(&self) -> Option<&T> {
self.get(self.len.wrapping_sub(1))
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.84), const)]
pub fn back_mut(&mut self) -> Option<&mut T> {
self.get_mut(self.len.wrapping_sub(1))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
let idx = self.to_physical_idx(index);
unsafe { Some((&*self.ptr().add(idx)).assume_init_ref()) }
} else {
None
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.84), const)]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
let idx = self.to_physical_idx(index);
unsafe { Some((&mut *self.ptr_mut().add(idx)).assume_init_mut()) }
} else {
None
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn push_back(&mut self, value: T) -> Option<T> {
if self.is_full() {
Some(value)
} else {
let _ = unsafe { push_back_unchecked!(self(value)) };
None
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn pop_front(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
let old_head = self.head;
self.head = self.to_physical_idx(1);
self.len -= 1;
unsafe {
assert_unchecked(self.len < self.capacity());
Some(self.buffer_read(old_head))
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn pop_back(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
self.len -= 1;
unsafe {
assert_unchecked(self.len < self.capacity());
Some(self.buffer_read(self.to_physical_idx(self.len)))
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn push_front(&mut self, value: T) -> Option<T> {
if self.is_full() {
Some(value)
} else {
let _ = unsafe { push_front_unchecked!(self(value)) };
None
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn rotate_left(&mut self, n: usize) {
assert!(n <= self.len());
let k = self.len - n;
if n <= k {
unsafe { self.rotate_left_inner(n) }
} else {
unsafe { self.rotate_right_inner(k) }
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn rotate_right(&mut self, n: usize) {
assert!(n <= self.len());
let k = self.len - n;
if n <= k {
unsafe { self.rotate_right_inner(n) }
} else {
unsafe { self.rotate_left_inner(k) }
}
}
#[rustversion::attr(since(1.92), const)]
pub fn make_contiguous(&mut self) -> &mut [T] {
if mem::size_of::<T>() == 0 {
self.head = 0;
}
if self.is_contiguous() {
let base = self.ptr_mut();
unsafe { return slice::from_raw_parts_mut(base.add(self.head) as *mut T, self.len) }
}
let &mut Self { head, len, .. } = self;
let cap = self.capacity();
let free = cap - len;
let head_len = cap - head;
let tail = len - head_len;
let tail_len = tail;
if free >= head_len {
unsafe {
self.copy(0, head_len, tail_len);
self.copy_nonoverlapping(head, 0, head_len);
}
self.head = 0;
} else if free >= tail_len {
unsafe {
self.copy(head, tail, head_len);
self.copy_nonoverlapping(0, tail + head_len, tail_len);
}
self.head = tail;
} else {
if head_len > tail_len {
unsafe {
if free != 0 {
self.copy(0, free, tail_len);
}
let slice = &mut *self.buffer_range_mut(free..self.capacity());
slice.rotate_left(tail_len);
self.head = free;
}
} else {
unsafe {
if free != 0 {
self.copy(self.head, tail_len, head_len);
}
let slice = &mut *self.buffer_range_mut(0..self.len);
slice.rotate_right(head_len);
self.head = 0;
}
}
}
let base = self.ptr_mut();
unsafe { slice::from_raw_parts_mut(base.add(self.head) as *mut T, self.len) }
}
pub fn truncate(&mut self, len: usize) {
struct Dropper<'a, T>(&'a mut [T]);
impl<T> Drop for Dropper<'_, T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.0);
}
}
}
unsafe {
if len >= self.len {
return;
}
let (front, back) = self.as_mut_slices();
if len > front.len() {
let begin = len - front.len();
let drop_back = back.get_unchecked_mut(begin..) as *mut _;
self.len = len;
ptr::drop_in_place(drop_back);
} else {
let drop_back = back as *mut _;
let drop_front = front.get_unchecked_mut(len..) as *mut _;
self.len = len;
let _back_dropper = Dropper(&mut *drop_back);
ptr::drop_in_place(drop_front);
}
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn clear(&mut self) {
self.truncate(0);
self.head = 0;
}
#[inline]
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq<T>,
{
let (a, b) = self.as_slices();
a.contains(x) || b.contains(x)
}
#[inline]
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where
T: Ord,
{
self.binary_search_by(|e| e.cmp(x))
}
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> Ordering,
{
let (front, back) = self.as_slices();
let cmp_back = back.first().map(&mut f);
if let Some(Ordering::Equal) = cmp_back {
Ok(front.len())
} else if let Some(Ordering::Less) = cmp_back {
back
.binary_search_by(f)
.map(|idx| idx + front.len())
.map_err(|idx| idx + front.len())
} else {
front.binary_search_by(f)
}
}
#[inline]
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> B,
B: Ord,
{
self.binary_search_by(|k| f(k).cmp(b))
}
pub fn partition_point<P>(&self, mut pred: P) -> usize
where
P: FnMut(&T) -> bool,
{
let (front, back) = self.as_slices();
if let Some(true) = back.first().map(&mut pred) {
back.partition_point(pred) + front.len()
} else {
front.partition_point(pred)
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len());
let ri = self.to_physical_idx(i);
let rj = self.to_physical_idx(j);
let base = self.ptr_mut();
unsafe {
ptr::swap(base.add(ri), base.add(rj));
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
let length = self.len;
if index < length && index != 0 {
self.swap(index, 0);
} else if index >= length {
return None;
}
self.pop_front()
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
let length = self.len;
if length > 0 && index < length - 1 {
self.swap(index, length - 1);
} else if index >= length {
return None;
}
self.pop_back()
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.85), const)]
pub fn insert(&mut self, index: usize, value: T) -> Option<T> {
if index > self.len() || self.is_full() {
return Some(value);
}
let _ = insert!(self(index, value));
None
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[rustversion::attr(since(1.83), const)]
pub fn remove(&mut self, index: usize) -> Option<T> {
if self.len <= index {
return None;
}
let wrapped_idx = self.to_physical_idx(index);
let elem = unsafe { Some(self.buffer_read(wrapped_idx)) };
let k = self.len - index - 1;
if k < index {
unsafe { self.wrap_copy(self.wrap_add(wrapped_idx, 1), wrapped_idx, k) };
self.len -= 1;
} else {
let old_head = self.head;
self.head = self.to_physical_idx(1);
unsafe { self.wrap_copy(old_head, self.head, index) };
self.len -= 1;
}
elem
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.retain_mut(|elem| f(elem));
}
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let len = self.len;
let mut idx = 0;
let mut cur = 0;
while cur < len {
if !f(&mut self[cur]) {
cur += 1;
break;
}
cur += 1;
idx += 1;
}
while cur < len {
if !f(&mut self[cur]) {
cur += 1;
continue;
}
self.swap(idx, cur);
cur += 1;
idx += 1;
}
if cur != idx {
self.truncate(idx);
}
}
}
impl<T, N> GenericArrayDeque<T, N>
where
N: ArrayLength,
T: Clone,
{
pub fn resize(&mut self, new_len: usize, value: T) -> Option<T> {
if new_len > self.capacity() {
return Some(value);
}
if new_len > self.len() {
let extra = new_len - self.len();
for v in repeat_n(value, extra) {
self.push_back(v);
}
} else {
self.truncate(new_len);
}
None
}
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) -> bool {
let len = self.len;
if new_len > self.capacity() {
return false;
}
if new_len > len {
for val in repeat_with(generator).take(new_len - len) {
self.push_back(val);
}
} else {
self.truncate(new_len);
}
true
}
}
impl<T, N> Drop for GenericArrayDeque<T, N>
where
N: ArrayLength,
{
fn drop(&mut self) {
self.clear();
}
}
impl<T, N> GenericArrayDeque<T, N>
where
N: ArrayLength,
{
#[inline]
const fn ptr(&self) -> *const MaybeUninit<T> {
self.array.as_slice().as_ptr()
}
#[inline]
#[rustversion::attr(since(1.83), const)]
fn ptr_mut(&mut self) -> *mut MaybeUninit<T> {
self.array.as_mut_slice().as_mut_ptr()
}
fn slice_ranges<R>(&self, r: R, len: usize) -> (Range<usize>, Range<usize>)
where
R: RangeBounds<usize>,
{
let Range { start, end } = range::<R>(r, ..len);
let len = end - start;
if len == 0 {
(0..0, 0..0)
} else {
let wrapped_start = self.to_physical_idx(start);
let head_len = self.capacity() - wrapped_start;
if head_len >= len {
(wrapped_start..wrapped_start + len, 0..0)
} else {
let tail_len = len - head_len;
(wrapped_start..self.capacity(), 0..tail_len)
}
}
}
const fn slice_full_ranges(&self) -> (Range<usize>, Range<usize>) {
let start = 0;
let end = self.len;
let len = end - start;
if len == 0 {
(0..0, 0..0)
} else {
let wrapped_start = self.to_physical_idx(start);
let head_len = self.capacity() - wrapped_start;
if head_len >= len {
(wrapped_start..wrapped_start + len, 0..0)
} else {
let tail_len = len - head_len;
(wrapped_start..self.capacity(), 0..tail_len)
}
}
}
#[inline]
const fn wrap_add(&self, idx: usize, addend: usize) -> usize {
wrap_index(idx.wrapping_add(addend), self.capacity())
}
#[inline]
const fn to_physical_idx(&self, idx: usize) -> usize {
self.wrap_add(self.head, idx)
}
#[inline]
const fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize {
wrap_index(
idx.wrapping_sub(subtrahend).wrapping_add(self.capacity()),
self.capacity(),
)
}
#[inline]
#[rustversion::attr(since(1.75), const)]
unsafe fn buffer_read(&self, off: usize) -> T {
unsafe { (&*self.ptr().add(off)).assume_init_read() }
}
#[inline]
const unsafe fn buffer_range(&self, range: Range<usize>) -> *const [T] {
unsafe { ptr::slice_from_raw_parts(self.ptr().add(range.start) as _, range.end - range.start) }
}
#[inline]
#[rustversion::attr(since(1.83), const)]
unsafe fn buffer_range_mut(&mut self, range: Range<usize>) -> *mut [T] {
unsafe {
ptr::slice_from_raw_parts_mut(
self.ptr_mut().add(range.start) as _,
range.end - range.start,
)
}
}
#[inline]
#[rustversion::attr(since(1.85), const)]
unsafe fn buffer_write(&mut self, off: usize, value: T) -> &mut T {
unsafe {
let ptr = &mut *self.ptr_mut().add(off);
ptr.write(value);
ptr.assume_init_mut()
}
}
#[rustversion::attr(since(1.83), const)]
unsafe fn rotate_left_inner(&mut self, mid: usize) {
debug_assert!(mid * 2 <= self.len());
unsafe {
self.wrap_copy(self.head, self.to_physical_idx(self.len), mid);
}
self.head = self.to_physical_idx(mid);
}
#[rustversion::attr(since(1.83), const)]
unsafe fn rotate_right_inner(&mut self, k: usize) {
debug_assert!(k * 2 <= self.len());
self.head = self.wrap_sub(self.head, k);
unsafe {
self.wrap_copy(self.to_physical_idx(self.len), self.head, k);
}
}
#[inline]
#[rustversion::attr(since(1.83), const)]
unsafe fn copy(&mut self, src: usize, dst: usize, len: usize) {
check_copy_bounds(dst, src, len, self.capacity());
unsafe {
let base_ptr = self.ptr_mut();
let src_ptr = base_ptr.add(src) as *const MaybeUninit<T>;
let dst_ptr = base_ptr.add(dst);
ptr::copy(src_ptr, dst_ptr, len);
}
}
#[inline]
#[rustversion::attr(since(1.83), const)]
unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) {
debug_assert!(src.len() <= self.capacity());
let head_room = self.capacity() - dst;
if src.len() <= head_room {
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.ptr_mut().add(dst) as _, src.len());
}
} else {
let (left, right) = src.split_at(head_room);
unsafe {
ptr::copy_nonoverlapping(left.as_ptr(), self.ptr_mut().add(dst) as _, left.len());
ptr::copy_nonoverlapping(right.as_ptr(), self.ptr_mut() as _, right.len());
}
}
}
#[inline]
#[rustversion::attr(since(1.83), const)]
unsafe fn copy_nonoverlapping(&mut self, src: usize, dst: usize, len: usize) {
check_copy_bounds(dst, src, len, self.capacity());
unsafe {
let base_ptr = self.ptr_mut();
let src_ptr = base_ptr.add(src) as *const MaybeUninit<T>;
let dst_ptr = base_ptr.add(dst);
ptr::copy_nonoverlapping(src_ptr, dst_ptr, len);
}
}
#[rustversion::attr(since(1.83), const)]
unsafe fn wrap_copy(&mut self, src: usize, dst: usize, len: usize) {
if mem::size_of::<T>() == 0 || src == dst || len == 0 {
return;
}
let dst_after_src = self.wrap_sub(dst, src) < len;
let src_pre_wrap_len = self.capacity() - src;
let dst_pre_wrap_len = self.capacity() - dst;
let src_wraps = src_pre_wrap_len < len;
let dst_wraps = dst_pre_wrap_len < len;
match (dst_after_src, src_wraps, dst_wraps) {
(_, false, false) => {
unsafe {
self.copy(src, dst, len);
}
}
(false, false, true) => {
unsafe {
self.copy(src, dst, dst_pre_wrap_len);
self.copy(src + dst_pre_wrap_len, 0, len - dst_pre_wrap_len);
}
}
(true, false, true) => {
unsafe {
self.copy(src + dst_pre_wrap_len, 0, len - dst_pre_wrap_len);
self.copy(src, dst, dst_pre_wrap_len);
}
}
(false, true, false) => {
unsafe {
self.copy(src, dst, src_pre_wrap_len);
self.copy(0, dst + src_pre_wrap_len, len - src_pre_wrap_len);
}
}
(true, true, false) => {
unsafe {
self.copy(0, dst + src_pre_wrap_len, len - src_pre_wrap_len);
self.copy(src, dst, src_pre_wrap_len);
}
}
(false, true, true) => {
debug_assert!(dst_pre_wrap_len > src_pre_wrap_len);
let delta = dst_pre_wrap_len - src_pre_wrap_len;
unsafe {
self.copy(src, dst, src_pre_wrap_len);
self.copy(0, dst + src_pre_wrap_len, delta);
self.copy(delta, 0, len - dst_pre_wrap_len);
}
}
(true, true, true) => {
debug_assert!(src_pre_wrap_len > dst_pre_wrap_len);
let delta = src_pre_wrap_len - dst_pre_wrap_len;
unsafe {
self.copy(0, delta, len - src_pre_wrap_len);
self.copy(self.capacity() - delta, 0, delta);
self.copy(src, dst, dst_pre_wrap_len);
}
}
}
}
#[inline]
#[cfg(feature = "std")]
unsafe fn write_iter(&mut self, dst: usize, iter: impl Iterator<Item = T>, written: &mut usize) {
iter.enumerate().for_each(|(i, element)| unsafe {
self.buffer_write(dst + i, element);
*written += 1;
});
}
#[cfg(feature = "std")]
unsafe fn write_iter_wrapping(
&mut self,
dst: usize,
mut iter: impl Iterator<Item = T>,
len: usize,
) -> usize {
struct Guard<'a, T, N: ArrayLength> {
deque: &'a mut GenericArrayDeque<T, N>,
written: usize,
}
impl<T, N: ArrayLength> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
self.deque.len += self.written;
}
}
let head_room = self.capacity() - dst;
let mut guard = Guard {
deque: self,
written: 0,
};
if head_room >= len {
unsafe { guard.deque.write_iter(dst, iter, &mut guard.written) };
} else {
unsafe {
guard
.deque
.write_iter(dst, iter.by_ref().take(head_room), &mut guard.written);
guard.deque.write_iter(0, iter, &mut guard.written)
};
}
guard.written
}
#[inline]
const fn is_contiguous(&self) -> bool {
self.head <= self.capacity() - self.len
}
}
#[inline]
const fn wrap_index(logical_index: usize, capacity: usize) -> usize {
debug_assert!(
(logical_index == 0 && capacity == 0)
|| logical_index < capacity
|| (logical_index - capacity) < capacity
);
if logical_index >= capacity {
logical_index - capacity
} else {
logical_index
}
}
fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
where
R: ops::RangeBounds<usize>,
{
let len = bounds.end;
let end = match range.end_bound() {
ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),
ops::Bound::Included(&end) => end + 1,
ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len),
ops::Bound::Excluded(&end) => end,
ops::Bound::Unbounded => len,
};
let start = match range.start_bound() {
ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len),
ops::Bound::Excluded(&start) => start + 1,
ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len),
ops::Bound::Included(&start) => start,
ops::Bound::Unbounded => 0,
};
ops::Range { start, end }
}
#[cfg(feature = "unstable")]
fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
where
R: ops::RangeBounds<usize>,
{
let len = bounds.end;
let end = match range.end_bound() {
ops::Bound::Included(&end) if end >= len => return None,
ops::Bound::Included(&end) => end + 1,
ops::Bound::Excluded(&end) if end > len => return None,
ops::Bound::Excluded(&end) => end,
ops::Bound::Unbounded => len,
};
let start = match range.start_bound() {
ops::Bound::Excluded(&start) if start >= end => return None,
ops::Bound::Excluded(&start) => start + 1,
ops::Bound::Included(&start) if start > end => return None,
ops::Bound::Included(&start) => start,
ops::Bound::Unbounded => 0,
};
Some(ops::Range { start, end })
}
#[track_caller]
fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
if start > len {
panic!(
"range start index {start} out of range for slice of length {len}",
)
}
if end > len {
panic!(
"range end index {end} out of range for slice of length {len}",
)
}
if start > end {
panic!(
"slice index starts at {start} but ends at {end}",
)
}
panic!(
"range end index {end} out of range for slice of length {len}",
)
}
#[rustversion::since(1.83)]
const fn check_copy_bounds(dst: usize, src: usize, len: usize, cap: usize) {
debug_assert!(dst + len <= cap,);
debug_assert!(src + len <= cap,);
}
#[rustversion::before(1.83)]
fn check_copy_bounds(dst: usize, src: usize, len: usize, cap: usize) {
debug_assert!(
dst + len <= cap,
"cpy dst={} src={} len={} cap={}",
dst,
src,
len,
cap
);
debug_assert!(
src + len <= cap,
"cpy dst={} src={} len={} cap={}",
dst,
src,
len,
cap
);
}
#[rustversion::since(1.82)]
#[inline]
fn repeat_n<T: Clone>(element: T, count: usize) -> impl Iterator<Item = T> {
core::iter::repeat_n(element, count)
}
#[rustversion::before(1.82)]
#[inline]
fn repeat_n<T: Clone>(element: T, mut count: usize) -> impl Iterator<Item = T> {
core::iter::from_fn(move || {
if count == 0 {
None
} else {
count -= 1;
Some(element.clone())
}
})
}
#[rustversion::before(1.85)]
#[cfg_attr(not(tarpaulin), inline(always))]
const unsafe fn assert_unchecked(_: bool) {}
#[rustversion::since(1.85)]
#[cfg_attr(not(tarpaulin), inline(always))]
const unsafe fn assert_unchecked(cond: bool) {
core::hint::assert_unchecked(cond);
}