//! A circular buffer with fixed capacity. //! Requires Rust 1.59+ //! //! It can be stored directly on the stack if needed. //! //! This queue has `O(1)` amortized inserts and removals from both ends of the //! container. It also has `O(1)` indexing like a vector. The contained elements //! are not required to be copyable //! //! This crate is inspired by [**bluss/arrayvec**](https://github.com/bluss/arrayvec) //! //! # Feature Flags //! The **arraydeque** crate has the following cargo feature flags: //! //! - `std` //! - Optional, enabled by default //! - Conversions between `ArrayDeque` and `Vec` //! - Use libstd //! //! # Usage //! //! First, add the following to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! arraydeque = "0.5" //! ``` //! //! Next, add this to your crate root: //! //! ``` //! extern crate arraydeque; //! ``` //! //! Currently arraydeque by default links to the standard library, but if you would //! instead like to use arraydeque in a `#![no_std]` situation or crate you can //! request this via: //! //! ```toml //! [dependencies] //! arraydeque = { version = "0.4", default-features = false } //! ``` //! //! # Behaviors //! //! `ArrayDeque` provides two different behaviors, `Saturating` and `Wrapping`, //! determining whether to remove existing element automatically when pushing //! to a full deque. //! //! See the [behavior module documentation](behavior/index.html) for more.
#[cfg(not(any(feature = "std", test)))] externcrate core as std;
use std::cmp; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; use std::marker; use std::mem::MaybeUninit; use std::ops::Index; use std::ops::IndexMut; use std::ptr;
/// A fixed capacity ring buffer. /// /// It can be stored directly on the stack if needed. /// /// The "default" usage of this type as a queue is to use `push_back` to add to /// the queue, and `pop_front` to remove from the queue. Iterating over `ArrayDeque` goes front /// to back. pubstruct ArrayDeque<T, const CAP: usize, B: Behavior = Saturating> {
xs: MaybeUninit<[T; CAP]>,
tail: usize,
len: usize,
marker: marker::PhantomData<B>,
}
impl<T, const CAP: usize> ArrayDeque<T, CAP, Saturating> { /// Add an element to the front of the deque. /// /// Return `Ok(())` if the push succeeds, or return `Err(CapacityError { *element* })` /// if the vector is full. /// /// # Examples /// /// ``` /// // 1 -(+)-> [_, _, _] => [1, _, _] -> Ok(()) /// // 2 -(+)-> [1, _, _] => [2, 1, _] -> Ok(()) /// // 3 -(+)-> [2, 1, _] => [3, 2, 1] -> Ok(()) /// // 4 -(+)-> [3, 2, 1] => [3, 2, 1] -> Err(CapacityError { element: 4 }) /// /// use arraydeque::{ArrayDeque, CapacityError}; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_front(1); /// buf.push_front(2); /// buf.push_front(3); /// /// let overflow = buf.push_front(4); /// /// assert_eq!(overflow, Err(CapacityError { element: 4 })); /// assert_eq!(buf.back(), Some(&1)); /// ``` pubfn push_front(&mutself, element: T) -> Result<(), CapacityError<T>> { if !self.is_full() { unsafe { self.push_front_unchecked(element);
}
Ok(())
} else {
Err(CapacityError { element })
}
}
/// Add an element to the back of the deque. /// /// Return `Ok(())` if the push succeeds, or return `Err(CapacityError { *element* })` /// if the vector is full. /// /// # Examples /// /// ``` /// // [_, _, _] <-(+)- 1 => [_, _, 1] -> Ok(()) /// // [_, _, 1] <-(+)- 2 => [_, 1, 2] -> Ok(()) /// // [_, 1, 2] <-(+)- 3 => [1, 2, 3] -> Ok(()) /// // [1, 2, 3] <-(+)- 4 => [1, 2, 3] -> Err(CapacityError { element: 4 }) /// /// use arraydeque::{ArrayDeque, CapacityError}; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// /// let overflow = buf.push_back(4); /// /// assert_eq!(overflow, Err(CapacityError { element: 4 })); /// assert_eq!(buf.back(), Some(&3)); /// ``` pubfn push_back(&mutself, element: T) -> Result<(), CapacityError<T>> { if !self.is_full() { unsafe { self.push_back_unchecked(element);
}
Ok(())
} else {
Err(CapacityError { element })
}
}
/// Inserts an element at `index` within the `ArrayDeque`. Whichever /// end is closer to the insertion point will be moved to make room, /// and all the affected elements will be moved to new positions. /// /// Return `Ok(())` if the push succeeds, or return `Err(CapacityError { *element* })` /// if the vector is full. /// /// Element at index 0 is the front of the queue. /// /// # Panics /// /// Panics if `index` is greater than `ArrayDeque`'s length /// /// # Examples /// /// ``` /// // [_, _, _] <-(#0)- 3 => [3, _, _] -> Ok(()) /// // [3, _, _] <-(#0)- 1 => [1, 3, _] -> Ok(()) /// // [1, 3, _] <-(#1)- 2 => [1, 2, 3] -> Ok(()) /// // [1, 2, 3] <-(#1)- 4 => [1, 2, 3] -> Err(CapacityError { element: 4 }) /// /// use arraydeque::{ArrayDeque, CapacityError}; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.insert(0, 3); /// buf.insert(0, 1); /// buf.insert(1, 2); /// /// let overflow = buf.insert(1, 4); /// /// assert_eq!(overflow, Err(CapacityError { element: 4 })); /// assert_eq!(buf.back(), Some(&3)); /// ``` #[track_caller] #[inline] pubfn insert(&mutself, index: usize, element: T) -> Result<(), CapacityError<T>> {
assert!(index <= self.len(), "index out of bounds");
ifself.is_full() { return Err(CapacityError { element });
}
unsafe { self.insert_unchecked(index, element);
}
Ok(())
}
/// Extend deque from front with the contents of an iterator. /// /// Does not extract more items than there is space for. /// No error occurs if there are more iterator elements. /// /// # Examples /// /// ``` /// // [9, 8, 7] -(+)-> [_, _, _, _, _, _, _] => [7, 8, 9, _, _, _, _] /// // [6, 5, 4] -(+)-> [7, 8, 9, _, _, _, _] => [4, 5, 6, 7, 8, 9, _] /// // [3, 2, 1] -(+)-> [4, 5, 6, 7, 8, 9, _] => [3, 4, 5, 6, 7, 8, 9] /// /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 7> = ArrayDeque::new(); /// /// buf.extend_front([9, 8, 7].into_iter()); /// buf.extend_front([6, 5, 4].into_iter()); /// /// assert_eq!(buf.len(), 6); /// /// // max capacity reached /// buf.extend_front([3, 2, 1].into_iter()); /// /// assert_eq!(buf.len(), 7); /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9].into()); /// ``` #[allow(unused_must_use)] pubfn extend_front<I>(&mutself, iter: I) where
I: IntoIterator<Item = T>,
{ let take = self.capacity() - self.len(); for element in iter.into_iter().take(take) { self.push_front(element);
}
}
/// Extend deque from back with the contents of an iterator. /// /// Does not extract more items than there is space for. /// No error occurs if there are more iterator elements. /// /// # Examples /// /// ``` /// // [_, _, _, _, _, _, _] <-(+)- [1, 2, 3] => [_, _, _, _, 1, 2, 3] /// // [_, _, _, _, 1, 2, 3] <-(+)- [4, 5, 6] => [_, 1, 2, 3, 4, 5, 6] /// // [_, 1, 2, 3, 4, 5, 6] <-(+)- [7, 8, 9] => [1, 2, 3, 4, 5, 6, 7] /// /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 7> = ArrayDeque::new(); /// /// buf.extend_back([1, 2, 3].into_iter()); /// buf.extend_back([4, 5, 6].into_iter()); /// /// assert_eq!(buf.len(), 6); /// /// // max capacity reached /// buf.extend_back([7, 8, 9].into_iter()); /// /// assert_eq!(buf.len(), 7); /// assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7].into()); /// ``` #[allow(unused_must_use)] pubfn extend_back<I>(&mutself, iter: I) where
I: IntoIterator<Item = T>,
{ let take = self.capacity() - self.len(); for element in iter.into_iter().take(take) { self.push_back(element);
}
}
}
// Move the least number of elements in the ring buffer and insert // the given object // // At most len/2 - 1 elements will be moved. O(min(n, n-i)) // // There are three main cases: // Elements are contiguous // - special case when tail is 0 // Elements are discontiguous and the insert is in the tail section // Elements are discontiguous and the insert is in the head section // // For each of those there are two more cases: // Insert is closer to tail // Insert is closer to head // // Key: H - self.head // T - self.tail // o - Valid element // I - Insertion element // A - The element that should be after the insertion point // M - Indicates element was moved
let idx = Self::wrap_add(self.tail(), index);
let distance_to_tail = index; let distance_to_head = self.len() - index;
let contiguous = self.is_contiguous();
match (
contiguous,
distance_to_tail <= distance_to_head,
idx >= self.tail(),
) {
(true, true, _) if index == 0 => { // push_front // // T // I H // [A o o o o o o . . . . . . . . .] // // H T // [A o o o o o o o . . . . . I] //
self.set_tail_backward();
}
(true, true, _) => { unsafe { // contiguous, insert closer to tail: // // T I H // [. . . o o A o o o o . . . . . .] // // T H // [. . o o I A o o o o . . . . . .] // M M // // contiguous, insert closer to tail and tail is 0: // // // T I H // [o o A o o o o . . . . . . . . .] // // H T // [o I A o o o o o . . . . . . . o] // M M
let tail = self.tail(); let new_tail = Self::wrap_sub(self.tail(), 1);
self.copy(new_tail, tail, 1); // Already moved the tail, so we only copy `index - 1` elements. self.copy(tail, tail + 1, index - 1);
self.set_tail_backward();
}
}
(true, false, _) => { unsafe { // contiguous, insert closer to head: // // T I H // [. . . o o o o A o o . . . . . .] // // T H // [. . . o o o o I A o o . . . . .] // M M M
let head = self.head(); self.copy(idx + 1, idx, head - idx);
self.set_head_forward();
}
}
(false, true, true) => { unsafe { // discontiguous, insert closer to tail, tail section: // // H T I // [o o o o o o . . . . . o o A o o] // // H T // [o o o o o o . . . . o o I A o o] // M M
let tail = self.tail(); self.copy(tail - 1, tail, index);
self.set_tail_backward();
}
}
(false, false, true) => { unsafe { // discontiguous, insert closer to head, tail section: // // H T I // [o o . . . . . . . o o o o o A o] // // H T // [o o o . . . . . . o o o o o I A] // M M M M
// copy elements up to new head let head = self.head(); self.copy(1, 0, head);
// copy last element into empty spot at bottom of buffer self.copy(0, CAP - 1, 1);
// move elements from idx to end forward not including ^ element self.copy(idx + 1, idx, CAP - 1 - idx);
self.set_head_forward();
}
}
(false, true, false) if idx == 0 => { unsafe { // discontiguous, insert is closer to tail, head section, // and is at index zero in the internal buffer: // // I H T // [A o o o o o o o o o . . . o o o] // // H T // [A o o o o o o o o o . . o o o I] // M M M
// copy elements up to new tail let tail = self.tail(); self.copy(tail - 1, tail, CAP - tail);
// copy last element into empty spot at bottom of buffer self.copy(CAP - 1, 0, 1);
self.set_tail_backward();
}
}
(false, true, false) => { unsafe { // discontiguous, insert closer to tail, head section: // // I H T // [o o o A o o o o o o . . . o o o] // // H T // [o o I A o o o o o o . . o o o o] // M M M M M M
let tail = self.tail(); // copy elements up to new tail self.copy(tail - 1, tail, CAP - tail);
// copy last element into empty spot at bottom of buffer self.copy(CAP - 1, 0, 1);
// move elements from idx-1 to end forward not including ^ element self.copy(0, 1, idx - 1);
self.set_tail_backward();
}
}
(false, false, false) => { unsafe { // discontiguous, insert closer to head, head section: // // I H T // [o o o o A o o . . . . . . o o o] // // H T // [o o o o I A o o . . . . . o o o] // M M M
let head = self.head(); self.copy(idx + 1, idx, head - idx);
self.set_head_forward();
}
}
}
// tail might've been changed so we need to recalculate let new_idx = Self::wrap_add(self.tail(), index); unsafe { self.buffer_write(new_idx, element);
}
}
/// Copies a contiguous block of memory len long from src to dst #[inline] unsafefn copy(&mutself, dst: usize, src: usize, len: 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
); let xs = self.ptr_mut();
ptr::copy(xs.add(src), xs.add(dst), len);
}
/// Copies a potentially wrapping block of memory len long from src to dest. /// (abs(dst - src) + len) must be no larger than cap() (There must be at /// most one continuous overlapping region between src and dest). unsafefn wrap_copy(&mutself, dst: usize, src: usize, len: usize) { #[allow(dead_code)] fn diff(a: usize, b: usize) -> usize { if a <= b {
b - a
} else {
a - b
}
}
debug_assert!(
cmp::min(diff(dst, src), CAP - diff(dst, src)) + len <= CAP, "wrc dst={} src={} len={} cap={}",
dst,
src,
len,
CAP
);
if src == dst || len == 0 { return;
}
let dst_after_src = Self::wrap_sub(dst, src) < len;
let src_pre_wrap_len = CAP - src; let dst_pre_wrap_len = CAP - 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) => { // src doesn't wrap, dst doesn't wrap // // S . . . // 1 [_ _ A A B B C C _] // 2 [_ _ A A A A B B _] // D . . . // self.copy(dst, src, len);
}
(false, false, true) => { // dst before src, src doesn't wrap, dst wraps // // S . . . // 1 [A A B B _ _ _ C C] // 2 [A A B B _ _ _ A A] // 3 [B B B B _ _ _ A A] // . . D . // self.copy(dst, src, dst_pre_wrap_len); self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
}
(true, false, true) => { // src before dst, src doesn't wrap, dst wraps // // S . . . // 1 [C C _ _ _ A A B B] // 2 [B B _ _ _ A A B B] // 3 [B B _ _ _ A A A A] // . . D . // self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); self.copy(dst, src, dst_pre_wrap_len);
}
(false, true, false) => { // dst before src, src wraps, dst doesn't wrap // // . . S . // 1 [C C _ _ _ A A B B] // 2 [C C _ _ _ B B B B] // 3 [C C _ _ _ B B C C] // D . . . // self.copy(dst, src, src_pre_wrap_len); self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
}
(true, true, false) => { // src before dst, src wraps, dst doesn't wrap // // . . S . // 1 [A A B B _ _ _ C C] // 2 [A A A A _ _ _ C C] // 3 [C C A A _ _ _ C C] // D . . . // self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); self.copy(dst, src, src_pre_wrap_len);
}
(false, true, true) => { // dst before src, src wraps, dst wraps // // . . . S . // 1 [A B C D _ E F G H] // 2 [A B C D _ E G H H] // 3 [A B C D _ E G H A] // 4 [B C C D _ E G H A] // . . D . . //
debug_assert!(dst_pre_wrap_len > src_pre_wrap_len); let delta = dst_pre_wrap_len - src_pre_wrap_len; self.copy(dst, src, src_pre_wrap_len); self.copy(dst + src_pre_wrap_len, 0, delta); self.copy(0, delta, len - dst_pre_wrap_len);
}
(true, true, true) => { // src before dst, src wraps, dst wraps // // . . S . . // 1 [A B C D _ E F G H] // 2 [A A B D _ E F G H] // 3 [H A B D _ E F G H] // 4 [H A B D _ E F F G] // . . . D . //
debug_assert!(src_pre_wrap_len > dst_pre_wrap_len); let delta = src_pre_wrap_len - dst_pre_wrap_len; self.copy(delta, 0, len - src_pre_wrap_len); self.copy(0, CAP - delta, delta); self.copy(dst, src, dst_pre_wrap_len);
}
}
}
#[inline] unsafefn buffer_read(&mutself, offset: usize) -> T {
ptr::read(self.ptr().add(offset))
}
/// Return the capacity of the `ArrayDeque`. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let buf: ArrayDeque<usize, 2> = ArrayDeque::new(); /// /// assert_eq!(buf.capacity(), 2); /// ``` #[inline] pubconstfn capacity(&self) -> usize {
CAP
}
/// Returns the number of elements in the `ArrayDeque`. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 1> = ArrayDeque::new(); /// /// assert_eq!(buf.len(), 0); /// /// buf.push_back(1); /// /// assert_eq!(buf.len(), 1); /// ``` #[inline] pubfn len(&self) -> usize { self.len
}
/// Returns true if the buffer contains no elements /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 1> = ArrayDeque::new(); /// /// assert!(buf.is_empty()); /// /// buf.push_back(1); /// /// assert!(!buf.is_empty()); /// ``` #[inline] pubfn is_empty(&self) -> bool { self.len() == 0
}
/// Entire capacity of the underlying storage pubfn as_uninit_slice(&self) -> &[MaybeUninit<T>] { unsafe { std::slice::from_raw_parts(self.xs.as_ptr().cast(), CAP) }
}
/// Entire capacity of the underlying storage pubfn as_uninit_slice_mut(&mutself) -> &mut [MaybeUninit<T>] { unsafe { std::slice::from_raw_parts_mut(self.xs.as_mut_ptr().cast(), CAP) }
}
/// Returns true if the buffer is full. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 1> = ArrayDeque::new(); /// /// assert!(!buf.is_full()); /// /// buf.push_back(1); /// /// assert!(buf.is_full()); /// ``` #[inline] pubfn is_full(&self) -> bool { self.len() == self.capacity()
}
/// Returns `true` if the `ArrayDeque` contains an element equal to the /// given value. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.contains(&1), true); /// assert_eq!(buf.contains(&3), false); /// ``` pubfn contains(&self, x: &T) -> bool where
T: PartialEq<T>,
{ let (a, b) = self.as_slices();
a.contains(x) || b.contains(x)
}
/// Provides a reference to the front element, or `None` if the sequence is /// empty. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// assert_eq!(buf.front(), None); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.front(), Some(&1)); /// ``` pubfn front(&self) -> Option<&T> { if !self.is_empty() {
Some(&self[0])
} else {
None
}
}
/// Provides a mutable reference to the front element, or `None` if the /// sequence is empty. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// assert_eq!(buf.front_mut(), None); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.front_mut(), Some(&mut 1)); /// ``` pubfn front_mut(&mutself) -> Option<&mut T> { if !self.is_empty() {
Some(&mutself[0])
} else {
None
}
}
/// Provides a reference to the back element, or `None` if the sequence is /// empty. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.back(), Some(&2)); /// ``` pubfn back(&self) -> Option<&T> { if !self.is_empty() {
Some(&self[self.len() - 1])
} else {
None
}
}
/// Provides a mutable reference to the back element, or `None` if the /// sequence is empty. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.back_mut(), Some(&mut 2)); /// ``` pubfn back_mut(&mutself) -> Option<&mut T> { let len = self.len(); if !self.is_empty() {
Some(&mutself[len - 1])
} else {
None
}
}
/// Retrieves an element in the `ArrayDeque` by index. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.get(1), Some(&1)); /// ``` #[inline] pubfn get(&self, index: usize) -> Option<&T> { if index < self.len() { let idx = Self::wrap_add(self.tail(), index); unsafe { Some(&*self.ptr().add(idx)) }
} else {
None
}
}
/// Retrieves an element in the `ArrayDeque` mutably by index. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.get_mut(1), Some(&mut 1)); /// ``` #[inline] pubfn get_mut(&mutself, index: usize) -> Option<&mut T> { if index < self.len() { let idx = Self::wrap_add(self.tail(), index); unsafe { Some(&mut *self.ptr_mut().add(idx)) }
} else {
None
}
}
/// Create a draining iterator that removes the specified range in the /// `ArrayDeque` and yields the removed items. /// /// Note 1: The element range is removed even if the iterator is not /// consumed until the end. /// /// Note 2: It is unspecified how many elements are removed from the deque, /// if the `Drain` value is not dropped, but the borrow it holds expires /// (eg. due to mem::forget). /// /// # Panics /// /// Panics if the starting point is greater than the end point or if /// the end point is greater than the length of the deque. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// { /// let drain = buf.drain(2..); /// assert!([2].into_iter().eq(drain)); /// } /// /// { /// let iter = buf.iter(); /// assert!([0, 1].iter().eq(iter)); /// } /// /// // A full range clears all contents /// buf.drain(..); /// assert!(buf.is_empty()); /// ``` #[track_caller] #[inline] pubfn drain<R>(&mutself, range: R) -> Drain<T, CAP, B> where
R: RangeArgument<usize>,
{ let len = self.len(); let start = range.start().unwrap_or(0); let end = range.end().unwrap_or(len);
assert!(start <= end, "drain lower bound was too large");
assert!(end <= len, "drain upper bound was too large");
let drain_tail = Self::wrap_add(self.tail(), start); let drain_head = Self::wrap_add(self.tail(), end); let drain_len = end - start;
/// Swaps elements at indices `i` and `j`. /// /// `i` and `j` may be equal. /// /// Fails if there is no element with either index. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// buf.swap(0, 2); /// /// assert_eq!(buf, [2, 1, 0].into()); /// ``` #[track_caller] #[inline] pubfn swap(&mutself, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len()); let ri = Self::wrap_add(self.tail(), i); let rj = Self::wrap_add(self.tail(), j); let xs = self.ptr_mut(); unsafe { ptr::swap(xs.add(ri), xs.add(rj)) }
}
/// Removes an element from anywhere in the `ArrayDeque` and returns it, replacing it with the /// last element. /// /// This does not preserve ordering, but is O(1). /// /// Returns `None` if `index` is out of bounds. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// assert_eq!(buf.swap_remove_back(0), None); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.swap_remove_back(0), Some(0)); /// assert_eq!(buf, [2, 1].into()); /// ``` pubfn swap_remove_back(&mutself, index: usize) -> Option<T> { let length = self.len(); if length > 0 && index < length - 1 { self.swap(index, length - 1);
} elseif index >= length { return None;
} self.pop_back()
}
/// Removes an element from anywhere in the `ArrayDeque` and returns it, /// replacing it with the first element. /// /// This does not preserve ordering, but is O(1). /// /// Returns `None` if `index` is out of bounds. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// assert_eq!(buf.swap_remove_back(0), None); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.swap_remove_front(2), Some(2)); /// assert_eq!(buf, [1, 0].into()); /// ``` pubfn swap_remove_front(&mutself, index: usize) -> Option<T> { let length = self.len(); if length > 0 && index < length && index != 0 { self.swap(index, 0);
} elseif index >= length { return None;
} self.pop_front()
}
/// Removes and returns the element at `index` from the `ArrayDeque`. /// Whichever end is closer to the removal point will be moved to make /// room, and all the affected elements will be moved to new positions. /// Returns `None` if `index` is out of bounds. /// /// Element at index 0 is the front of the queue. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.remove(1), Some(1)); /// assert_eq!(buf, [0, 2].into()); /// ``` pubfn remove(&mutself, index: usize) -> Option<T> { ifself.is_empty() || self.len() <= index { return None;
}
// There are three main cases: // Elements are contiguous // Elements are discontiguous and the removal is in the tail section // Elements are discontiguous and the removal is in the head section // - special case when elements are technically contiguous, // but self.head = 0 // // For each of those there are two more cases: // Insert is closer to tail // Insert is closer to head // // Key: H - self.head // T - self.tail // o - Valid element // x - Element marked for removal // R - Indicates element that is being removed // M - Indicates element was moved
let idx = Self::wrap_add(self.tail(), index);
let elem = unsafe { Some(self.buffer_read(idx)) };
let distance_to_tail = index; let distance_to_head = self.len() - index;
let contiguous = self.is_contiguous();
match (
contiguous,
distance_to_tail <= distance_to_head,
idx >= self.tail(),
) {
(true, true, _) => { unsafe { // contiguous, remove closer to tail: // // T R H // [. . . o o x o o o o . . . . . .] // // T H // [. . . . o o o o o o . . . . . .] // M M
let tail = self.tail(); self.copy(tail + 1, tail, index); self.set_tail_forward();
}
}
(true, false, _) => { unsafe { // contiguous, remove closer to head: // // T R H // [. . . o o o o x o o . . . . . .] // // T H // [. . . o o o o o o . . . . . . .] // M M
let head = self.head(); self.copy(idx, idx + 1, head - idx - 1); self.set_head_backward();
}
}
(false, true, true) => { unsafe { // discontiguous, remove closer to tail, tail section: // // H T R // [o o o o o o . . . . . o o x o o] // // H T // [o o o o o o . . . . . . o o o o] // M M
let tail = self.tail(); self.copy(tail + 1, tail, index); self.set_tail_forward();
}
}
(false, false, false) => { unsafe { // discontiguous, remove closer to head, head section: // // R H T // [o o o o x o o . . . . . . o o o] // // H T // [o o o o o o . . . . . . . o o o] // M M
let head = self.head(); self.copy(idx, idx + 1, head - idx - 1); self.set_head_backward();
}
}
(false, false, true) => { unsafe { // discontiguous, remove closer to head, tail section: // // H T R // [o o o . . . . . . o o o o o x o] // // H T // [o o . . . . . . . o o o o o o o] // M M M M // // or quasi-discontiguous, remove next to head, tail section: // // H T R // [. . . . . . . . . o o o o o x o] // // T H // [. . . . . . . . . o o o o o o .] // M
// draw in elements in the tail section self.copy(idx, idx + 1, CAP - idx - 1);
// Prevents underflow. ifself.head() != 0 { // copy first element into empty spot self.copy(CAP - 1, 0, 1);
// move elements in the head section backwards let head = self.head(); self.copy(0, 1, head - 1);
}
self.set_head_backward();
}
}
(false, true, false) => { unsafe { // discontiguous, remove closer to tail, head section: // // R H T // [o o x o o o o o o o . . . o o o] // // H T // [o o o o o o o o o o . . . . o o] // M M M M M
let tail = self.tail(); // draw in elements up to idx self.copy(1, 0, idx);
// copy last element into empty spot self.copy(0, CAP - 1, 1);
// move elements from tail to end forward, excluding the last one self.copy(tail + 1, tail, CAP - tail - 1);
self.set_tail_forward();
}
}
}
elem
}
/// Splits the collection into two at the given index. /// /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`, /// and the returned `Self` contains elements `[at, len)`. /// /// Element at index 0 is the front of the queue. /// /// # Panics /// /// Panics if `at > len` /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// // buf = [0], buf2 = [1, 2] /// let buf2 = buf.split_off(1); /// /// assert_eq!(buf.len(), 1); /// assert_eq!(buf2.len(), 2); /// ``` #[track_caller] #[inline] pubfn split_off(&mutself, at: usize) -> Self { let len = self.len();
assert!(at <= len, "`at` out of bounds");
let other_len = len - at; letmut 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 { // `at` lies in the first half. let amount_in_first = first_len - at;
// just take all of the second half.
ptr::copy_nonoverlapping(
second_half.as_ptr(),
other.ptr_mut().add(amount_in_first),
second_len,
);
} else { // `at` lies in the second half, need to factor in the elements we skipped // in the first half. let offset = at - first_len; let amount_in_second = second_len - offset;
ptr::copy_nonoverlapping(
second_half.as_ptr().add(offset),
other.ptr_mut(),
amount_in_second,
);
}
}
// Cleanup where the ends of the buffers are unsafe { self.set_len(at);
other.set_len(other_len);
}
other
}
/// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns false. /// This method operates in place and preserves the order of the retained /// elements. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 4> = ArrayDeque::new(); /// /// buf.extend_back(0..4); /// buf.retain(|&x| x % 2 == 0); /// /// assert_eq!(buf, [0, 2].into()); /// ``` pubfn retain<F>(&mutself, mut f: F) where
F: FnMut(&T) -> bool,
{ let len = self.len(); letmut del = 0; for i in0..len { if !f(&self[i]) {
del += 1;
} elseif del > 0 { self.swap(i - del, i);
}
} if del > 0 { for _ in (len - del)..self.len() { self.pop_back();
}
}
}
/// Returns a pair of slices which contain, in order, the contents of the /// `ArrayDeque`. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 7> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// /// assert_eq!(buf.as_slices(), (&[0, 1][..], &[][..])); /// /// buf.push_front(2); /// /// assert_eq!(buf.as_slices(), (&[2][..], &[0, 1][..])); /// ``` #[inline] pubfn as_slices(&self) -> (&[T], &[T]) { let contiguous = self.is_contiguous(); let head = self.head(); let tail = self.tail(); let buf = self.as_uninit_slice();
if contiguous { let (empty, buf) = buf.split_at(0); unsafe {
(
slice_assume_init_ref(&buf[tail..head]),
slice_assume_init_ref(empty),
)
}
} else { let (mid, right) = buf.split_at(tail); let (left, _) = mid.split_at(head);
/// Copy of currently-unstable `MaybeUninit::slice_assume_init_ref`. unsafefn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] { // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. // The pointer obtained is valid since it refers to memory owned by `slice` which is a // reference and thus guaranteed to be valid for reads.
&*(slice as *const [MaybeUninit<T>] as *const [T])
}
/// Copy of currently-unstable `MaybeUninit::slice_assume_init_mut`. unsafefn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &pan style='color:red'>mut [T] { // SAFETY: similar to safety notes for `slice_assume_init_ref`, but we have a // mutable reference which is also guaranteed to be valid for writes.
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
}
impl<T, const CAP: usize, B: Behavior> Ord for ArrayDeque<T, CAP, B> where
T: Ord,
{ #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other.iter())
}
}
impl<T, const CAP: usize, B: Behavior> Hash for ArrayDeque<T, CAP, B> where
T: Hash,
{ fn hash<H: Hasher>(&self, state: &mut H) { self.len().hash(state); let (a, b) = self.as_slices();
Hash::hash_slice(a, state);
Hash::hash_slice(b, state);
}
}
impl<T, const CAP: usize, B: Behavior> Index<usize> for ArrayDeque<T, CAP, B> { type Output = T;
#[inline] fn index(&self, index: usize) -> &T { let len = self.len(); self.get(index)
.or_else(|| {
panic!( "index out of bounds: the len is {} but the index is {}",
len, index
)
})
.unwrap()
}
}
impl<T, const CAP: usize, B: Behavior> IndexMut<usize> for ArrayDeque<T, CAP, B> { #[inline] fn index_mut(&mutself, index: usize) -> &mut T { let len = self.len(); self.get_mut(index)
.or_else(|| {
panic!( "index out of bounds: the len is {} but the index is {}",
len, index
)
})
.unwrap()
}
}
impl<T, const CAP: usize, B: Behavior> IntoIterator for ArrayDeque<T, CAP, B> { type Item = T; type IntoIter = IntoIter<T, CAP, B>;
for padding in0..CAP { for drain_start in0..CAP { for drain_end in drain_start..CAP { // deque starts from different tail position unsafe {
tester.set_len(0);
tester.set_tail(padding);
}
for len in0..CAP + 1 { for padding in0..CAP { // deque starts from different tail position unsafe {
tester.set_len(0);
tester.set_tail(padding);
}
letmut expected = ArrayDeque::<f64, CAP>::new(); for x in0..len {
tester.push_back(x as f64);
expected.push_back(x as f64);
}
assert_eq!(tester, expected);
// test negative if len > 2 {
tester.pop_front();
expected.pop_back();
assert!(tester != expected);
}
}
}
}
// len is the length *after* removal for len in0..CAP { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect(); for padding in0..CAP { for to_remove in0..len + 1 { unsafe {
tester.set_tail(padding);
tester.set_len(0);
} for i in0..len { if i == to_remove {
tester.push_back(1234);
}
tester.push_back(i);
} if to_remove == len {
tester.push_back(1234);
}
tester.remove(to_remove);
assert!(tester.tail() < CAP);
assert!(tester.head() < CAP);
assert_eq!(tester, expected);
}
}
}
}
#[test] fn test_clone() { let tester: ArrayDeque<_, 16> = (0..16).into_iter().collect(); let cloned = tester.clone();
assert_eq!(tester, cloned)
}
// len is the length *after* insertion for len in1..CAP { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect(); for padding in0..CAP { for to_insert in0..len { unsafe {
tester.set_tail(padding);
tester.set_len(0);
} for i in0..len { if i != to_insert {
tester.push_back(i);
}
} unsafe { tester.insert_unchecked(to_insert, to_insert) };
assert!(tester.tail() < CAP);
assert!(tester.head() < CAP);
assert_eq!(tester, expected);
}
}
}
}