#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![warn(missing_docs)]
#![doc(test(attr(deny(warnings))))]
extern crate alloc;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt::Debug;
use core::hash::Hash;
use core::marker::PhantomData;
use core::ops::{Bound, Deref, DerefMut, RangeBounds};
use core::ptr;
use core::{cmp, mem};
#[cfg(feature = "std")]
use std::io::{Read, Write};
use buffer::Buffer;
use iter::RawValIter;
mod buffer;
mod iter;
#[cfg(test)]
mod drop_tracker;
pub struct LinearDeque<T> {
buf: Buffer<T>,
len: usize,
off: usize,
}
unsafe impl<T: Send> Send for LinearDeque<T> {}
unsafe impl<T: Sync> Sync for LinearDeque<T> {}
impl<T> LinearDeque<T> {
fn ptr(&self) -> *mut T {
self.buf.ptr.as_ptr()
}
fn cap(&self) -> usize {
self.buf.cap
}
#[must_use]
pub fn new() -> Self {
Self::with_reserved_space(0, 0)
}
#[must_use]
pub fn with_reserved_space(front: usize, back: usize) -> Self {
let mut buf = Buffer::new();
let cap = front + back;
if cap > 0 && !is_zst::<T>() {
buf.realloc(cap);
}
LinearDeque {
buf,
len: 0,
off: front,
}
}
#[must_use]
pub fn front(&self) -> Option<&T> {
self.first()
}
pub fn front_mut(&mut self) -> Option<&mut T> {
self.first_mut()
}
#[must_use]
pub fn back(&self) -> Option<&T> {
self.last()
}
pub fn back_mut(&mut self) -> Option<&mut T> {
self.last_mut()
}
pub fn push_front(&mut self, elem: T) {
if !is_zst::<T>() {
self.ensure_reserved_front_space(1);
unsafe {
self.off -= 1;
ptr::write(self.ptr().add(self.off), elem);
}
}
self.len += 1;
}
pub fn push_back(&mut self, elem: T) {
self.ensure_reserved_back_space(1);
unsafe {
ptr::write(self.ptr().add(self.off + self.len), elem);
}
self.len += 1;
}
pub fn pop_front(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
self.off += 1;
unsafe { Some(ptr::read(self.ptr().add(self.off - 1))) }
}
}
pub fn pop_back(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
unsafe { Some(ptr::read(self.ptr().add(self.off + self.len))) }
}
}
pub fn insert(&mut self, index: usize, elem: T) {
assert!(index <= self.len, "index out of bounds");
if !is_zst::<T>() {
if 2 * index < self.len {
unsafe {
let pending_copy = self.prepare_reserved_front_space(1);
let (mut front_copy, back_copy) = pending_copy.split(index);
front_copy.dst -= 1;
back_copy.perform(self.ptr());
front_copy.perform(self.ptr());
self.off -= 1;
ptr::write(self.ptr().add(self.off + index), elem);
}
} else {
unsafe {
let pending_copy = self.prepare_reserved_back_space(1);
let (front_copy, mut back_copy) = pending_copy.split(index);
back_copy.dst += 1;
front_copy.perform(self.ptr());
back_copy.perform(self.ptr());
ptr::write(self.ptr().add(self.off + index), elem);
}
}
}
self.len += 1;
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index < self.len {
unsafe {
let start = self.ptr().add(self.off);
let result = ptr::read(start.add(index));
if index < self.len / 2 {
ptr::copy(start, start.add(1), index);
self.off += 1;
} else {
ptr::copy(start.add(index + 1), start.add(index), self.len - index - 1);
}
self.len -= 1;
Some(result)
}
} else {
None
}
}
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
{
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(start) => start.checked_add(1).expect("invalid start index"),
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(end) => end.checked_add(1).expect("invalid end index"),
Bound::Excluded(&end) => end,
Bound::Unbounded => self.len,
};
assert!(!(start > end || end > self.len), "invalid range");
let iter = unsafe { RawValIter::new(&self[start..end]) };
let front_len = start;
let back_len = self.len - end;
let count = end - start;
let pending_copy = if front_len < back_len {
let prev_off = self.off;
self.off += count;
PendingCopy {
src: prev_off,
dst: prev_off + count,
count: front_len,
}
} else {
PendingCopy {
src: self.off + end,
dst: self.off + start,
count: back_len,
}
};
self.len -= count;
Drain {
iter,
pending_copy,
ptr: self.ptr(),
vec: PhantomData,
}
}
pub fn extend_at_front(&mut self, iter: impl IntoIterator<Item = T>) {
let iter = iter.into_iter();
let (lower, upper) = iter.size_hint();
let count = upper.unwrap_or(lower);
if count < usize::MAX {
self.ensure_reserved_front_space(count);
}
for elem in iter {
self.push_front(elem);
}
}
pub fn extend_at_back(&mut self, iter: impl IntoIterator<Item = T>) {
let iter = iter.into_iter();
let (lower, upper) = iter.size_hint();
let count = upper.unwrap_or(lower);
if count < usize::MAX {
self.ensure_reserved_back_space(count);
}
for elem in iter {
self.push_back(elem);
}
}
pub fn resize_at_front_with(&mut self, new_len: usize, mut f: impl FnMut() -> T) {
match new_len.cmp(&self.len) {
Ordering::Less => self.truncate_at_front(new_len),
Ordering::Equal => (),
Ordering::Greater => {
let count = new_len - self.len;
self.set_reserved_space(SetReservedSpace::GrowTo(count), SetReservedSpace::Keep);
self.extend_at_front(core::iter::from_fn(|| Some(f())).take(count));
}
}
}
pub fn resize_at_back_with(&mut self, new_len: usize, mut f: impl FnMut() -> T) {
match new_len.cmp(&self.len) {
Ordering::Less => self.truncate_at_back(new_len),
Ordering::Equal => (),
Ordering::Greater => {
let count = new_len - self.len;
self.set_reserved_space(SetReservedSpace::Keep, SetReservedSpace::GrowTo(count));
self.extend_at_back(core::iter::from_fn(|| Some(f())).take(count));
}
}
}
#[inline]
pub fn resize_with(&mut self, new_len: usize, f: impl FnMut() -> T) {
self.resize_at_back_with(new_len, f);
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.retain_mut(|x| f(x));
}
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
unsafe {
let mut dropped_index_option = None;
let base = self.ptr().add(self.off);
for i in 0..self.len {
let p = base.add(i);
if f(&mut *p) {
if let Some(dropped_index) = dropped_index_option {
ptr::copy_nonoverlapping(p, base.add(dropped_index), 1);
dropped_index_option = Some(dropped_index + 1);
}
} else {
p.drop_in_place();
if dropped_index_option.is_none() {
dropped_index_option = Some(i);
}
}
}
if let Some(dropped_index) = dropped_index_option {
self.len = dropped_index;
}
}
}
pub fn truncate_at_front(&mut self, len: usize) {
if len < self.len {
unsafe {
let count = self.len() - len;
let front = self.get_unchecked_mut(..count);
ptr::drop_in_place(front);
self.off += count;
self.len = len;
}
}
}
pub fn truncate_at_back(&mut self, len: usize) {
if len < self.len {
unsafe {
let back = self.get_unchecked_mut(len..);
ptr::drop_in_place(back);
self.len = len;
}
}
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.truncate_at_back(len);
}
pub fn clear(&mut self) {
self.truncate_at_back(0);
self.off = self.cap() / 2;
}
pub fn set_reserved_space(&mut self, front: SetReservedSpace, back: SetReservedSpace) {
fn new_space(current: usize, set: SetReservedSpace) -> usize {
match set {
SetReservedSpace::Keep => current,
SetReservedSpace::ShrinkTo(new) => current.min(new),
SetReservedSpace::GrowTo(new) => current.max(new),
SetReservedSpace::Exact(new) => new,
}
}
if is_zst::<T>() {
return;
}
let front_space = self.reserved_front_space();
let back_space = self.reserved_back_space();
let cap = self.cap();
let new_front_space = new_space(front_space, front);
let new_back_space = new_space(back_space, back);
let new_cap = new_front_space + self.len + new_back_space;
if new_cap > cap {
self.buf.realloc(new_cap);
}
if new_front_space != front_space {
unsafe {
ptr::copy(
self.ptr().add(front_space),
self.ptr().add(new_front_space),
self.len,
);
}
self.off = new_front_space;
}
if new_cap < cap {
self.buf.realloc(new_cap);
}
}
fn ensure_reserved_front_space(&mut self, count: usize) {
unsafe {
let pending_copy = self.prepare_reserved_front_space(count);
pending_copy.perform(self.ptr());
}
}
unsafe fn prepare_reserved_front_space(&mut self, count: usize) -> PendingCopy {
let mut pending_copy = PendingCopy {
src: self.off,
dst: self.off,
count: self.len,
};
if self.reserved_front_space() >= count {
} else {
let total_reserved_space = self.cap() - self.len;
self.off = if total_reserved_space >= count {
usize::midpoint(total_reserved_space, count)
} else {
let growth = cmp::max(1, self.len);
let new_cap = if count > total_reserved_space + growth {
self.len + count
} else {
self.cap() + growth
};
self.buf.realloc(new_cap);
new_cap - self.len
};
pending_copy.dst = self.off;
}
debug_assert!(self.reserved_front_space() >= count);
pending_copy
}
fn ensure_reserved_back_space(&mut self, count: usize) {
unsafe {
let pending_copy = self.prepare_reserved_back_space(count);
pending_copy.perform(self.ptr());
}
}
unsafe fn prepare_reserved_back_space(&mut self, count: usize) -> PendingCopy {
let mut pending_copy = PendingCopy {
src: self.off,
dst: self.off,
count: self.len,
};
if self.reserved_back_space() >= count {
} else {
let total_reserved_space = self.cap() - self.len;
self.off = if total_reserved_space >= count {
(total_reserved_space - count) / 2
} else {
let growth = cmp::max(1, self.len);
let new_cap = if count > total_reserved_space + growth {
self.len + count
} else {
self.cap() + growth
};
self.buf.realloc(new_cap);
0
};
pending_copy.dst = self.off;
}
debug_assert!(self.reserved_back_space() >= count);
pending_copy
}
#[must_use]
pub fn reserved_front_space(&self) -> usize {
if is_zst::<T>() { usize::MAX } else { self.off }
}
#[must_use]
pub fn reserved_back_space(&self) -> usize {
if is_zst::<T>() {
usize::MAX
} else {
self.cap() - self.len - self.off
}
}
}
impl<T: Clone> LinearDeque<T> {
pub fn resize_at_front(&mut self, new_len: usize, value: T) {
self.resize_at_front_with(new_len, || value.clone());
}
pub fn resize_at_back(&mut self, new_len: usize, value: T) {
self.resize_at_back_with(new_len, || value.clone());
}
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
self.resize_at_back(new_len, value);
}
}
impl<T> Default for LinearDeque<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Drop for LinearDeque<T> {
fn drop(&mut self) {
while self.pop_back().is_some() {}
}
}
impl<T> Deref for LinearDeque<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
unsafe { core::slice::from_raw_parts(self.ptr().add(self.off), self.len) }
}
}
impl<T> DerefMut for LinearDeque<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { core::slice::from_raw_parts_mut(self.ptr().add(self.off), self.len) }
}
}
impl<T> Extend<T> for LinearDeque<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.extend_at_back(iter);
}
}
impl<'a, T> Extend<&'a T> for LinearDeque<T>
where
T: 'a + Copy,
{
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.extend(iter.into_iter().copied());
}
}
impl<T> IntoIterator for LinearDeque<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
unsafe {
let iter = RawValIter::new(&self);
let buf = ptr::read(&raw const self.buf);
mem::forget(self);
IntoIter { iter, _buf: buf }
}
}
}
macro_rules! impl_partial_eq {
([$($n:tt)*] $rhs:ty) => {
impl<T, U, $($n)*> PartialEq<$rhs> for LinearDeque<T>
where
T: PartialEq<U>,
{
fn eq(&self, other: & $rhs) -> bool {
self.deref() == other.deref()
}
}
};
}
impl_partial_eq!([const N: usize] [U; N]);
impl_partial_eq!([const N: usize] &[U; N]);
impl_partial_eq!([const N: usize] &mut [U; N]);
impl_partial_eq!([] & [U]);
impl_partial_eq!([] &mut [U]);
impl_partial_eq!([] Vec<U>);
impl_partial_eq!([] LinearDeque<U>);
impl<T: Eq> Eq for LinearDeque<T> {}
impl<T: PartialOrd> PartialOrd for LinearDeque<T> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T: Ord> Ord for LinearDeque<T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.iter().cmp(other.iter())
}
}
impl<T: Hash> Hash for LinearDeque<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state);
}
}
impl<T, const N: usize> From<[T; N]> for LinearDeque<T> {
fn from(value: [T; N]) -> Self {
Self::from_iter(value)
}
}
impl<T> From<Vec<T>> for LinearDeque<T> {
fn from(value: Vec<T>) -> Self {
Self::from_iter(value)
}
}
impl<T> FromIterator<T> for LinearDeque<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower, upper) = iter.size_hint();
let size = upper.unwrap_or(lower);
let mut deque = Self::with_reserved_space(0, size);
for elem in iter {
deque.push_back(elem);
}
deque
}
}
#[cfg(feature = "std")]
impl Read for LinearDeque<u8> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let result = (&*self as &[u8]).read(buf);
if let Ok(ref count) = result {
self.truncate_at_front(self.len - count);
}
result
}
}
#[cfg(feature = "std")]
impl Write for LinearDeque<u8> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.extend(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<T: Clone> Clone for LinearDeque<T> {
fn clone(&self) -> Self {
let mut clone = Self::with_reserved_space(0, self.len);
for elem in self.iter() {
clone.push_back(elem.clone());
}
clone
}
}
impl<T: Debug> Debug for LinearDeque<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LinearDeque")
.field("values", &&**self)
.field(
"reserved_spaces",
&(self.reserved_front_space(), self.reserved_back_space()),
)
.finish()
}
}
#[derive(Clone, Copy, Debug)]
#[must_use]
struct PendingCopy {
src: usize,
dst: usize,
count: usize,
}
impl PendingCopy {
unsafe fn perform<T>(self, ptr: *mut T) {
unsafe {
if self.count > 0 && self.src != self.dst {
ptr::copy(ptr.add(self.src), ptr.add(self.dst), self.count);
}
}
}
fn split(self, index: usize) -> (PendingCopy, PendingCopy) {
let low = PendingCopy {
count: index,
..self
};
let high = PendingCopy {
src: self.src + index,
dst: self.dst + index,
count: self.count - index,
};
(low, high)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum SetReservedSpace {
Keep,
ShrinkTo(usize),
GrowTo(usize),
Exact(usize),
}
pub struct IntoIter<T> {
_buf: Buffer<T>,
iter: RawValIter<T>,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
for _ in &mut *self {}
}
}
pub struct Drain<'a, T: 'a> {
vec: PhantomData<&'a mut LinearDeque<T>>,
iter: RawValIter<T>,
pending_copy: PendingCopy,
ptr: *mut T,
}
impl<T> Iterator for Drain<'_, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> Drop for Drain<'_, T> {
fn drop(&mut self) {
for _ in &mut *self {}
unsafe {
self.pending_copy.perform(self.ptr);
}
}
}
fn is_zst<T>() -> bool {
mem::size_of::<T>() == 0
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use core::hash::{Hash as _, Hasher};
use core::{mem, ptr};
use std::collections::hash_map::DefaultHasher;
use std::io::{Read as _, Write as _};
use crate::drop_tracker::DropTracker;
use crate::{LinearDeque, SetReservedSpace};
macro_rules! assert_deque {
($deque:ident, $expected_reserved_front_space:expr, $expected_elems:expr, $expected_reserved_back_space:expr $(,)?) => {{
let expected_reserved_front_space = $expected_reserved_front_space;
let expected_elems: Vec<_> = $expected_elems.into_iter().collect();
let expected_reserved_back_space = $expected_reserved_back_space;
let expected_len = expected_elems.len();
let expected_capacity =
expected_reserved_front_space + expected_len + expected_reserved_back_space;
let expected_off = expected_reserved_front_space;
assert_eq!($deque.cap(), expected_capacity, "cap");
assert_eq!($deque.len, expected_len, "len");
assert_eq!($deque.off, expected_off, "off");
for (i, expected_elem) in expected_elems.into_iter().enumerate() {
let elem = unsafe { ptr::read($deque.ptr().add($deque.off + i)) };
assert_eq!(elem, expected_elem, "index {i}");
}
assert_eq!(
$deque.reserved_front_space(),
expected_reserved_front_space,
"front space"
);
assert_eq!(
$deque.reserved_back_space(),
expected_reserved_back_space,
"back_space"
);
}};
}
fn prepare_deque<T: Clone + Eq + Debug>(
reserved_front_space: usize,
elems: impl IntoIterator<Item = T>,
reserved_back_space: usize,
) -> LinearDeque<T> {
let elems: Vec<_> = elems.into_iter().collect();
let capacity = reserved_front_space + elems.len() + reserved_back_space;
let mut deque: LinearDeque<T> = LinearDeque::new();
if capacity != 0 {
deque.buf.realloc(capacity);
deque.len = elems.len();
deque.off = reserved_front_space;
for (i, elem) in elems.iter().enumerate() {
unsafe {
ptr::write(deque.ptr().add(deque.off + i), elem.clone());
}
}
}
assert_deque!(deque, reserved_front_space, elems, reserved_back_space);
deque
}
macro_rules! assert_zst_deque {
($deque:ident, $expected_len:expr) => {{
fn assert_zst_deque<T>(_: &LinearDeque<T>) {
assert_eq!(mem::size_of::<T>(), 0);
}
assert_zst_deque(&$deque);
}
assert_eq!($deque.cap(), usize::MAX);
assert_eq!($deque.len, $expected_len);};
}
fn prepare_zst_deque<T>(len: usize) -> LinearDeque<T> {
assert_eq!(mem::size_of::<T>(), 0);
let mut deque = LinearDeque::new();
deque.len = len;
deque
}
#[test]
fn new_zst() {
let deque: LinearDeque<()> = LinearDeque::new();
assert_zst_deque!(deque, 0);
}
#[test]
fn with_reserved_space() {
let deque: LinearDeque<char> = LinearDeque::with_reserved_space(3, 4);
assert_deque!(deque, 3, [], 4);
}
#[test]
fn with_reserved_space_zst() {
let deque: LinearDeque<()> = LinearDeque::with_reserved_space(3, 4);
assert_zst_deque!(deque, 0);
}
#[test]
fn front_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(0);
assert_eq!(deque.front(), None);
let deque: LinearDeque<()> = prepare_zst_deque(2);
assert_eq!(deque.front(), Some(&()));
}
#[test]
fn back_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(0);
assert_eq!(deque.back(), None);
let deque: LinearDeque<()> = prepare_zst_deque(2);
assert_eq!(deque.back(), Some(&()));
}
#[test]
fn push_front() {
let mut deque: LinearDeque<char> = prepare_deque(2, [], 1);
deque.push_front('A');
assert_deque!(deque, 1, ['A'], 1);
deque.push_front('B');
assert_deque!(deque, 0, ['B', 'A'], 1);
deque.push_front('C');
assert_deque!(deque, 0, ['C', 'B', 'A'], 0);
deque.push_front('D');
assert_deque!(deque, 2, ['D', 'C', 'B', 'A'], 0);
deque.push_front('E');
assert_deque!(deque, 1, ['E', 'D', 'C', 'B', 'A'], 0);
}
#[test]
fn push_front_zst() {
let mut deque = prepare_zst_deque(0);
deque.push_front(());
deque.push_front(());
assert_zst_deque!(deque, 2);
}
#[test]
fn push_back() {
let mut deque: LinearDeque<char> = prepare_deque(1, [], 2);
deque.push_back('A');
assert_deque!(deque, 1, ['A'], 1);
deque.push_back('B');
assert_deque!(deque, 1, ['A', 'B'], 0);
deque.push_back('C');
assert_deque!(deque, 0, ['A', 'B', 'C'], 0);
deque.push_back('D');
assert_deque!(deque, 0, ['A', 'B', 'C', 'D'], 2);
deque.push_back('E');
assert_deque!(deque, 0, ['A', 'B', 'C', 'D', 'E'], 1);
}
#[test]
fn push_back_zst() {
let mut deque = prepare_zst_deque(0);
deque.push_back(());
deque.push_back(());
assert_zst_deque!(deque, 2);
}
#[test]
fn pop_front() {
let mut deque = prepare_deque(1, ['B', 'A'], 2);
let popped = deque.pop_front();
assert_eq!(popped, Some('B'));
assert_deque!(deque, 2, ['A'], 2);
let popped = deque.pop_front();
assert_eq!(popped, Some('A'));
assert_deque!(deque, 3, [], 2);
let popped = deque.pop_front();
assert_eq!(popped, None);
assert_deque!(deque, 3, [], 2);
}
#[test]
fn pop_front_zst() {
let mut deque = prepare_zst_deque(2);
let popped = deque.pop_front();
assert_eq!(popped, Some(()));
assert_zst_deque!(deque, 1);
let popped = deque.pop_front();
assert_eq!(popped, Some(()));
assert_zst_deque!(deque, 0);
let popped = deque.pop_front();
assert_eq!(popped, None);
assert_zst_deque!(deque, 0);
}
#[test]
fn pop_back() {
let mut deque = prepare_deque(2, ['A', 'B'], 1);
let popped = deque.pop_back();
assert_eq!(popped, Some('B'));
assert_deque!(deque, 2, ['A'], 2);
let popped = deque.pop_back();
assert_eq!(popped, Some('A'));
assert_deque!(deque, 2, [], 3);
let popped = deque.pop_back();
assert_eq!(popped, None);
assert_deque!(deque, 2, [], 3);
}
#[test]
fn pop_back_zst() {
let mut deque = prepare_zst_deque(2);
let popped = deque.pop_back();
assert_eq!(popped, Some(()));
assert_zst_deque!(deque, 1);
let popped = deque.pop_back();
assert_eq!(popped, Some(()));
assert_zst_deque!(deque, 0);
let popped = deque.pop_back();
assert_eq!(popped, None);
assert_zst_deque!(deque, 0);
}
#[test]
fn insert_near_front() {
let mut deque = prepare_deque(1, ['A', 'B', 'C'], 1);
deque.insert(1, 'x');
assert_deque!(deque, 0, ['A', 'x', 'B', 'C'], 1);
deque.insert(1, 'y');
assert_deque!(deque, 0, ['A', 'y', 'x', 'B', 'C'], 0);
deque.insert(1, 'z');
assert_deque!(deque, 4, ['A', 'z', 'y', 'x', 'B', 'C'], 0);
}
#[test]
fn insert_near_back() {
let mut deque = prepare_deque(1, ['A', 'B', 'C'], 1);
deque.insert(2, 'x');
assert_deque!(deque, 1, ['A', 'B', 'x', 'C'], 0);
deque.insert(3, 'y');
assert_deque!(deque, 0, ['A', 'B', 'x', 'y', 'C'], 0);
deque.insert(4, 'z');
assert_deque!(deque, 0, ['A', 'B', 'x', 'y', 'z', 'C'], 4);
}
#[test]
fn insert_zst() {
let mut deque = LinearDeque::new();
deque.insert(0, ());
deque.insert(0, ());
deque.insert(2, ());
deque.insert(2, ());
assert_zst_deque!(deque, 4);
}
#[test]
fn remove_near_front() {
let mut deque = prepare_deque(0, ['A', 'B', 'C', 'D'], 0);
let removed = deque.remove(1);
assert_eq!(removed, Some('B'));
assert_deque!(deque, 1, ['A', 'C', 'D'], 0);
}
#[test]
fn remove_near_back() {
let mut deque = prepare_deque(0, ['A', 'B', 'C', 'D'], 0);
let removed = deque.remove(2);
assert_eq!(removed, Some('C'));
assert_deque!(deque, 0, ['A', 'B', 'D'], 1);
}
#[test]
fn remove_zst() {
let mut deque = prepare_zst_deque(3);
let removed = deque.remove(1);
assert_eq!(removed, Some(()));
assert_zst_deque!(deque, 2);
let removed = deque.remove(1);
assert_eq!(removed, Some(()));
assert_zst_deque!(deque, 1);
let removed = deque.remove(0);
assert_eq!(removed, Some(()));
assert_zst_deque!(deque, 0);
let removed = deque.remove(0);
assert_eq!(removed, None);
assert_zst_deque!(deque, 0);
}
#[test]
fn drain_all() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(..);
assert_eq!(drained.collect::<Vec<_>>(), Vec::from_iter('A'..='H'));
assert_eq!(deque.cap(), 12);
assert!(deque.reserved_front_space() >= 2);
assert!(deque.reserved_back_space() >= 2);
assert!(deque.is_empty());
}
#[test]
fn drain_start() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(..3);
assert_eq!(drained.collect::<Vec<_>>(), Vec::from_iter('A'..='C'));
assert_deque!(deque, 5, 'D'..='H', 2);
}
#[test]
fn drain_end() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(5..);
assert_eq!(drained.collect::<Vec<_>>(), Vec::from_iter('F'..='H'));
assert_deque!(deque, 2, 'A'..='E', 5);
}
#[test]
fn drain_near_start() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(1..5);
assert_eq!(drained.collect::<Vec<_>>(), Vec::from_iter('B'..='E'));
assert_deque!(deque, 6, ['A', 'F', 'G', 'H'], 2);
}
#[test]
fn drain_near_end() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(3..7);
assert_eq!(drained.collect::<Vec<_>>(), Vec::from_iter('D'..='G'));
assert_deque!(deque, 2, ['A', 'B', 'C', 'H'], 6);
}
#[test]
fn drain_nothing() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let drained = deque.drain(3..3);
assert_eq!(drained.count(), 0);
assert_deque!(deque, 2, 'A'..='H', 2);
}
#[test]
fn drain_not_fully_consumed() {
let mut deque = prepare_deque(2, 'A'..='H', 2);
let mut drained = deque.drain(3..7);
assert_eq!(drained.next(), Some('D'));
drop(drained);
assert_deque!(deque, 2, ['A', 'B', 'C', 'H'], 6);
}
#[test]
fn drain_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(8);
let iter = deque.drain(3..5);
assert_eq!(iter.count(), 2);
assert_zst_deque!(deque, 6);
let iter = deque.drain(4..);
assert_eq!(iter.count(), 2);
assert_zst_deque!(deque, 4);
let iter = deque.drain(..2);
assert_eq!(iter.count(), 2);
assert_zst_deque!(deque, 2);
let iter = deque.drain(..);
assert_eq!(iter.count(), 2);
assert_zst_deque!(deque, 0);
}
#[test]
fn extend_at_front() {
let mut deque = prepare_deque(1, ['C', 'D'], 1);
deque.extend_at_front(['B', 'A']);
assert_deque!(deque, 0, 'A'..='D', 0);
}
#[test]
fn extend_at_front_zst() {
let mut deque = prepare_zst_deque(2);
deque.extend_at_front(std::iter::repeat(()).take(4));
assert_zst_deque!(deque, 6);
}
#[test]
fn extend_at_back() {
let mut deque = prepare_deque(1, ['A', 'B'], 1);
deque.extend_at_back(['C', 'D']);
assert_deque!(deque, 0, 'A'..='D', 0);
}
#[test]
fn extend_at_back_zst() {
let mut deque = prepare_zst_deque(2);
deque.extend_at_back(std::iter::repeat(()).take(4));
assert_zst_deque!(deque, 6);
}
#[test]
fn reserved_front_space() {
let deque = prepare_deque(3, 'A'..='D', 4);
assert_eq!(deque.reserved_front_space(), 3);
}
#[test]
fn reserved_front_space_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(5);
assert_eq!(deque.reserved_front_space(), usize::MAX);
}
#[test]
fn reserved_back_space() {
let deque = prepare_deque(3, 'A'..='D', 4);
assert_eq!(deque.reserved_back_space(), 4);
}
#[test]
fn reserved_back_space_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(5);
assert_eq!(deque.reserved_back_space(), usize::MAX);
}
#[test]
fn deref_empty() {
let deque: LinearDeque<char> = prepare_deque(6, [], 4);
assert!(deque.is_empty());
assert_eq!(deque.len(), 0);
}
#[test]
fn deref_non_empty() {
let deque = prepare_deque(2, ['A', 'B', 'C'], 4);
assert!(!deque.is_empty());
assert_eq!(deque.len(), 3);
assert_eq!(deque[0], 'A');
assert_eq!(deque[1], 'B');
assert_eq!(deque[2], 'C');
}
#[test]
fn deref_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(4);
assert!(!deque.is_empty());
assert_eq!(deque.len(), 4);
assert_eq!(deque[0], ());
assert_zst_deque!(deque, 4);
}
#[test]
fn into_iter() {
let deque = prepare_deque(2, ['A', 'B', 'C'], 4);
let mut iter = deque.into_iter();
assert_eq!(iter.next(), Some('A'));
assert_eq!(iter.next(), Some('B'));
assert_eq!(iter.next(), Some('C'));
assert_eq!(iter.next(), None);
}
#[test]
fn into_iter_double_ended() {
let deque = prepare_deque(2, ['A', 'B', 'C'], 4);
let mut iter = deque.into_iter();
assert_eq!(iter.next_back(), Some('C'));
assert_eq!(iter.next_back(), Some('B'));
assert_eq!(iter.next_back(), Some('A'));
assert_eq!(iter.next_back(), None);
}
#[test]
fn into_iter_mixed() {
let deque = prepare_deque(2, ['A', 'B', 'C'], 4);
let mut iter = deque.into_iter();
assert_eq!(iter.next_back(), Some('C'));
assert_eq!(iter.next(), Some('A'));
assert_eq!(iter.next_back(), Some('B'));
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
}
#[test]
fn into_iter_zst() {
let deque: LinearDeque<()> = prepare_zst_deque(4);
let iter = deque.into_iter();
assert_eq!(iter.count(), 4);
}
#[test]
fn resize_at_front_larger() {
let mut deque = prepare_deque(2, ['A', 'B', 'C', 'D'], 3);
deque.resize_at_front(10, 'x');
assert_deque!(
deque,
0,
['x', 'x', 'x', 'x', 'x', 'x', 'A', 'B', 'C', 'D'],
3
);
}
#[test]
fn resize_at_front_smaller() {
let mut deque = prepare_deque(2, ['A', 'B', 'C', 'D'], 3);
deque.resize_at_front(3, 'x');
assert_deque!(deque, 3, ['B', 'C', 'D'], 3);
}
#[test]
fn resize_at_front_zst() {
let mut deque = prepare_zst_deque(5);
deque.resize_at_front(2, ());
assert_zst_deque!(deque, 2);
deque.resize_at_front(4, ());
assert_zst_deque!(deque, 4);
}
#[test]
fn resize_at_back_larger() {
let mut deque = prepare_deque(3, ['A', 'B', 'C', 'D'], 2);
deque.resize_at_back(10, 'x');
assert_deque!(
deque,
3,
['A', 'B', 'C', 'D', 'x', 'x', 'x', 'x', 'x', 'x'],
0
);
}
#[test]
fn resize_at_back_smaller() {
let mut deque = prepare_deque(3, ['A', 'B', 'C', 'D'], 2);
deque.resize_at_back(3, 'x');
assert_deque!(deque, 3, ['A', 'B', 'C'], 3);
}
#[test]
fn resize_at_back_zst() {
let mut deque = prepare_zst_deque(5);
deque.resize_at_back(2, ());
assert_zst_deque!(deque, 2);
deque.resize_at_back(4, ());
assert_zst_deque!(deque, 4);
}
#[test]
fn resize_at_front_with_larger() {
let mut deque = prepare_deque(2, 'A'..='D', 3);
let mut chars = 'a'..;
deque.resize_at_front_with(7, || chars.next().unwrap());
assert_deque!(deque, 0, ['c', 'b', 'a', 'A', 'B', 'C', 'D'], 3);
}
#[test]
fn resize_at_front_with_smaller() {
let mut deque = prepare_deque(2, 'A'..='D', 3);
let mut chars = 'a'..;
deque.resize_at_front_with(3, || chars.next().unwrap());
assert_deque!(deque, 3, ['B', 'C', 'D'], 3);
}
#[test]
fn resize_at_front_with_zst() {
let mut deque = prepare_zst_deque(5);
deque.resize_at_front_with(2, || ());
assert_zst_deque!(deque, 2);
deque.resize_at_front_with(4, || ());
assert_zst_deque!(deque, 4);
}
#[test]
fn resize_at_back_with_larger() {
let mut deque = prepare_deque(3, 'A'..='D', 2);
let mut chars = 'a'..;
deque.resize_at_back_with(7, || chars.next().unwrap());
assert_deque!(deque, 3, ['A', 'B', 'C', 'D', 'a', 'b', 'c'], 0);
}
#[test]
fn resize_at_back_with_smaller() {
let mut deque = prepare_deque(2, 'A'..='D', 3);
let mut chars = 'a'..;
deque.resize_at_back_with(3, || chars.next().unwrap());
assert_deque!(deque, 2, ['A', 'B', 'C'], 4);
}
#[test]
fn resize_at_back_with_zst() {
let mut deque = prepare_zst_deque(5);
deque.resize_at_back_with(2, || ());
assert_zst_deque!(deque, 2);
deque.resize_at_back_with(4, || ());
assert_zst_deque!(deque, 4);
}
#[test]
fn retain() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(2, drop_tracker.wrap_iter(['A', 'b', 'c', 'D', 'e']), 1);
let (dropped, _) = drop_tracker.track(|| {
deque.retain(|c| c.value.is_lowercase());
});
assert_deque!(deque, 2, drop_tracker.wrap_iter(['b', 'c', 'e']), 3);
assert_eq!(dropped, ['A', 'D']);
}
#[test]
fn retain_mut() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(2, drop_tracker.wrap_iter(['A', 'b', 'c', 'D', 'e']), 1);
let (dropped, _) = drop_tracker.track(|| {
deque.retain_mut(|c| {
if c.value.is_lowercase() {
c.value = c.value.to_uppercase().next().unwrap();
true
} else {
false
}
});
});
assert_deque!(deque, 2, drop_tracker.wrap_iter(['B', 'C', 'E']), 3);
assert_eq!(dropped, ['A', 'D']);
}
#[test]
fn retain_mut_drop_none() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(2, drop_tracker.wrap_iter('A'..='E'), 1);
let (dropped, _) = drop_tracker.track(|| {
deque.retain_mut(|_| true);
});
assert_deque!(deque, 2, drop_tracker.wrap_iter('A'..='E'), 1);
assert!(dropped.is_empty());
}
#[test]
fn retain_mut_drop_all() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(2, drop_tracker.wrap_iter('A'..='E'), 1);
let (dropped, _) = drop_tracker.track(|| {
deque.retain_mut(|_| false);
});
assert_deque!(deque, 2, [], 6);
assert_eq!(dropped, Vec::from_iter('A'..='E'));
}
#[test]
fn retain_mut_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(4);
let mut p = false;
deque.retain(|_| {
p = !p;
p
});
assert_zst_deque!(deque, 2);
}
#[test]
fn truncate_at_front() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(5, drop_tracker.wrap_iter('A'..='F'), 1);
let (dropped, _) = drop_tracker.track(|| {
deque.truncate_at_front(2);
});
assert_deque!(deque, 9, drop_tracker.wrap_iter('E'..='F'), 1);
assert_eq!(dropped, Vec::from_iter('A'..='D'));
}
#[test]
fn truncate_at_front_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(4);
deque.truncate_at_front(3);
assert_zst_deque!(deque, 3);
}
#[test]
fn truncate_at_back() {
let mut drop_tracker = DropTracker::new();
let mut deque = prepare_deque(1, drop_tracker.wrap_iter('A'..='F'), 5);
let (dropped, _) = drop_tracker.track(|| {
deque.truncate_at_back(2);
});
assert_deque!(deque, 1, drop_tracker.wrap_iter('A'..='B'), 9);
assert_eq!(dropped, Vec::from_iter('C'..='F'));
}
#[test]
fn truncate_at_back_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(4);
deque.truncate_at_back(3);
assert_zst_deque!(deque, 3);
}
#[test]
fn clear() {
let mut deque = prepare_deque(2, 'A'..='D', 4);
deque.clear();
assert_deque!(deque, 5, [], 5);
}
#[test]
fn clear_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(4);
deque.clear();
assert_zst_deque!(deque, 0);
}
#[test]
fn set_reserved_space_keeping() {
let mut deque = prepare_deque(2, 'A'..='D', 5);
deque.set_reserved_space(SetReservedSpace::Keep, SetReservedSpace::Keep);
assert_deque!(deque, 2, 'A'..='D', 5);
}
#[test]
fn set_reserved_space_growing() {
let mut deque = prepare_deque(3, 'A'..='D', 1);
deque.set_reserved_space(SetReservedSpace::GrowTo(6), SetReservedSpace::GrowTo(2));
assert_deque!(deque, 6, 'A'..='D', 2);
}
#[test]
fn set_reserved_space_not_growing() {
let mut deque = prepare_deque(3, 'A'..='D', 1);
deque.set_reserved_space(SetReservedSpace::GrowTo(2), SetReservedSpace::GrowTo(1));
assert_deque!(deque, 3, 'A'..='D', 1);
}
#[test]
fn set_reserved_space_shrinking() {
let mut deque = prepare_deque(5, 'A'..='D', 2);
deque.set_reserved_space(SetReservedSpace::ShrinkTo(2), SetReservedSpace::ShrinkTo(1));
assert_deque!(deque, 2, 'A'..='D', 1);
}
#[test]
fn set_reserved_space_not_shrinking() {
let mut deque = prepare_deque(5, 'A'..='D', 2);
deque.set_reserved_space(SetReservedSpace::ShrinkTo(6), SetReservedSpace::ShrinkTo(3));
assert_deque!(deque, 5, 'A'..='D', 2);
}
#[test]
fn set_reserved_space_exactly_growing() {
let mut deque = prepare_deque(2, 'A'..='D', 1);
deque.set_reserved_space(SetReservedSpace::Exact(5), SetReservedSpace::Exact(2));
assert_deque!(deque, 5, 'A'..='D', 2);
}
#[test]
fn set_reserved_space_exactly_shrinking() {
let mut deque = prepare_deque(5, 'A'..='D', 2);
deque.set_reserved_space(SetReservedSpace::Exact(2), SetReservedSpace::Exact(1));
assert_deque!(deque, 2, 'A'..='D', 1);
}
#[test]
fn ensure_reserved_front_space_doing_nothing_1() {
let mut deque = prepare_deque(3, 'A'..='C', 1);
deque.ensure_reserved_front_space(1);
assert_deque!(deque, 3, 'A'..='C', 1);
}
#[test]
fn ensure_reserved_front_space_doing_nothing_2() {
let mut deque = prepare_deque(3, 'A'..='C', 1);
deque.ensure_reserved_front_space(3);
assert_deque!(deque, 3, 'A'..='C', 1);
}
#[test]
fn ensure_reserved_front_space_moving_1() {
let mut deque = prepare_deque(1, 'A'..='C', 3);
deque.ensure_reserved_front_space(2);
assert_deque!(deque, 3, 'A'..='C', 1);
}
#[test]
fn ensure_reserved_front_space_moving_2() {
let mut deque = prepare_deque(1, 'A'..='C', 3);
deque.ensure_reserved_front_space(4);
assert_deque!(deque, 4, 'A'..='C', 0);
}
#[test]
fn ensure_reserved_front_space_reallocating_1() {
let mut deque = prepare_deque(2, 'A'..='C', 2);
deque.ensure_reserved_front_space(5);
assert_deque!(deque, 7, 'A'..='C', 0);
}
#[test]
fn ensure_reserved_front_space_reallocating_2() {
let mut deque = prepare_deque(2, 'A'..='C', 2);
deque.ensure_reserved_front_space(8);
assert_deque!(deque, 8, 'A'..='C', 0);
}
#[test]
fn ensure_reserved_back_space_doing_nothing_1() {
let mut deque = prepare_deque(1, 'A'..='C', 3);
deque.ensure_reserved_back_space(1);
assert_deque!(deque, 1, 'A'..='C', 3);
}
#[test]
fn ensure_reserved_back_space_doing_nothing_2() {
let mut deque = prepare_deque(1, 'A'..='C', 3);
deque.ensure_reserved_back_space(3);
assert_deque!(deque, 1, 'A'..='C', 3);
}
#[test]
fn ensure_reserved_back_space_moving_1() {
let mut deque = prepare_deque(3, 'A'..='C', 1);
deque.ensure_reserved_back_space(2);
assert_deque!(deque, 1, 'A'..='C', 3);
}
#[test]
fn ensure_reserved_back_space_moving_2() {
let mut deque = prepare_deque(3, 'A'..='C', 1);
deque.ensure_reserved_back_space(4);
assert_deque!(deque, 0, 'A'..='C', 4);
}
#[test]
fn ensure_reserved_back_space_reallocating_1() {
let mut deque = prepare_deque(2, 'A'..='C', 2);
deque.ensure_reserved_back_space(5);
assert_deque!(deque, 0, 'A'..='C', 7);
}
#[test]
fn ensure_reserved_back_space_reallocating_2() {
let mut deque = prepare_deque(2, 'A'..='C', 2);
deque.ensure_reserved_back_space(8);
assert_deque!(deque, 0, 'A'..='C', 8);
}
#[test]
fn set_reserved_space_zst() {
let mut deque: LinearDeque<()> = prepare_zst_deque(5);
deque.set_reserved_space(SetReservedSpace::Exact(3), SetReservedSpace::Exact(4));
assert_zst_deque!(deque, 5);
}
#[test]
fn eq() {
let mut array = ['A', 'B'];
let mut array_x = ['B', 'A'];
let deque = prepare_deque(1, array, 5);
{
let slice: &[_] = &array;
let slice_x: &[_] = &array_x;
assert!(deque == slice);
assert!(deque != slice_x);
}
assert!(deque == &array);
assert!(deque != &array_x);
{
let slice_mut: &mut [_] = &mut array;
let slice_mut_x: &mut [_] = &mut array_x;
assert!(deque == slice_mut);
assert!(deque != slice_mut_x);
}
assert!(deque == &mut array);
assert!(deque != &mut array_x);
assert!(deque == array);
assert!(deque != array_x);
assert!(deque == Vec::from(array));
assert!(deque != Vec::from(array_x));
assert!(deque == prepare_deque(5, array, 0));
assert!(deque != prepare_deque(1, array_x, 5));
}
#[test]
fn hash() {
let deque1 = prepare_deque(3, ['A', 'B', 'C'], 5);
let deque2 = {
let mut d = LinearDeque::new();
d.push_back('B');
d.push_front('A');
d.push_back('C');
d
};
let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();
deque1.hash(&mut hasher1);
deque2.hash(&mut hasher2);
assert_eq!(hasher1.finish(), hasher2.finish());
}
#[test]
fn from_iter() {
let deque = LinearDeque::from_iter('A'..='D');
assert_deque!(deque, 0, ['A', 'B', 'C', 'D'], 0);
}
#[test]
fn from_iter_zst() {
let deque = LinearDeque::from_iter(std::iter::repeat(()).take(4));
assert_zst_deque!(deque, 4);
}
#[test]
fn read() {
let mut deque = prepare_deque(1, b'A'..=b'E', 2);
let mut buf = [b'0'; 3];
let result = deque.read(&mut buf);
assert_eq!(result.unwrap(), 3);
assert_eq!(buf, [b'A', b'B', b'C']);
assert_deque!(deque, 4, [b'D', b'E'], 2);
}
#[test]
fn write() {
let mut deque = prepare_deque(2, b'A'..=b'C', 1);
let buf: Vec<_> = (b'D'..=b'H').collect();
let result = deque.write(&buf);
assert_eq!(result.unwrap(), 5);
assert_deque!(deque, 0, b'A'..=b'H', 1);
}
#[test]
fn clone() {
let mut deque = prepare_deque(2, 'A'..='C', 1);
let mut clone = deque.clone();
deque[1] = 'x';
clone[1] = 'y';
assert_deque!(deque, 2, ['A', 'x', 'C'], 1);
assert_deque!(clone, 0, ['A', 'y', 'C'], 0);
}
}