mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-27 04:20:24 +00:00
commit
8d76c2d755
@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [v0.7.3] - 2021-07-01
|
||||
|
||||
### Added
|
||||
|
||||
- Added `Deque`.
|
||||
|
||||
### Changed
|
||||
|
||||
- `Box::freeze` is deprecated due to possibility of undefined behavior.
|
||||
|
846
src/deque.rs
Normal file
846
src/deque.rs
Normal file
@ -0,0 +1,846 @@
|
||||
use core::iter::FusedIterator;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::{ptr, slice};
|
||||
|
||||
/// A fixed capacity double-ended queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use heapless::Deque;
|
||||
///
|
||||
/// // A deque with a fixed capacity of 8 elements allocated on the stack
|
||||
/// let mut deque = Deque::<_, 8>::new();
|
||||
///
|
||||
/// // You can use it as a good old FIFO queue.
|
||||
/// deque.push_back(1);
|
||||
/// deque.push_back(2);
|
||||
/// assert_eq!(deque.len(), 2);
|
||||
///
|
||||
/// assert_eq!(deque.pop_front(), Some(1));
|
||||
/// assert_eq!(deque.pop_front(), Some(2));
|
||||
/// assert_eq!(deque.len(), 0);
|
||||
///
|
||||
/// // Deque is double-ended, you can push and pop from the front and back.
|
||||
/// deque.push_back(1);
|
||||
/// deque.push_front(2);
|
||||
/// deque.push_back(3);
|
||||
/// deque.push_front(4);
|
||||
/// assert_eq!(deque.pop_front(), Some(4));
|
||||
/// assert_eq!(deque.pop_front(), Some(2));
|
||||
/// assert_eq!(deque.pop_front(), Some(1));
|
||||
/// assert_eq!(deque.pop_front(), Some(3));
|
||||
///
|
||||
/// // You can iterate it, yielding all the elements front-to-back.
|
||||
/// for x in &deque {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Deque<T, const N: usize> {
|
||||
buffer: [MaybeUninit<T>; N],
|
||||
|
||||
/// Front index. Always 0..=(N-1)
|
||||
front: usize,
|
||||
/// Back index. Always 0..=(N-1).
|
||||
back: usize,
|
||||
|
||||
/// Used to distinguish "empty" and "full" cases when `front == back`.
|
||||
/// May only be `true` if `front == back`, always `false` otherwise.
|
||||
full: bool,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Deque<T, N> {
|
||||
const INIT: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
|
||||
/// Constructs a new, empty deque with a fixed capacity of `N`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use heapless::Deque;
|
||||
///
|
||||
/// // allocate the deque on the stack
|
||||
/// let mut x: Deque<u8, 16> = Deque::new();
|
||||
///
|
||||
/// // allocate the deque in a static variable
|
||||
/// static mut X: Deque<u8, 16> = Deque::new();
|
||||
/// ```
|
||||
pub const fn new() -> Self {
|
||||
// Const assert N > 0
|
||||
crate::sealed::greater_than_0::<N>();
|
||||
|
||||
Self {
|
||||
buffer: [Self::INIT; N],
|
||||
front: 0,
|
||||
back: 0,
|
||||
full: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(i: usize) -> usize {
|
||||
if i + 1 == N {
|
||||
0
|
||||
} else {
|
||||
i + 1
|
||||
}
|
||||
}
|
||||
|
||||
fn decrement(i: usize) -> usize {
|
||||
if i == 0 {
|
||||
N - 1
|
||||
} else {
|
||||
i - 1
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the maximum number of elements the deque can hold.
|
||||
pub const fn capacity(&self) -> usize {
|
||||
N
|
||||
}
|
||||
|
||||
/// Returns the number of elements currently in the deque.
|
||||
pub const fn len(&self) -> usize {
|
||||
if self.full {
|
||||
N
|
||||
} else if self.back < self.front {
|
||||
self.back + N - self.front
|
||||
} else {
|
||||
self.back - self.front
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the deque, removing all values.
|
||||
pub fn clear(&mut self) {
|
||||
// safety: we're immediately setting a consistent empty state.
|
||||
unsafe { self.drop_contents() }
|
||||
self.front = 0;
|
||||
self.back = 0;
|
||||
self.full = false;
|
||||
}
|
||||
|
||||
/// Drop all items in the `Deque`, leaving the state `back/front/full` unmodified.
|
||||
///
|
||||
/// safety: leaves the `Deque` in an inconsistent state, so can cause duplicate drops.
|
||||
unsafe fn drop_contents(&mut self) {
|
||||
// We drop each element used in the deque by turning into a &mut[T]
|
||||
let (a, b) = self.as_mut_slices();
|
||||
ptr::drop_in_place(a);
|
||||
ptr::drop_in_place(b);
|
||||
}
|
||||
|
||||
/// Returns whether the deque is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.front == self.back && !self.full
|
||||
}
|
||||
|
||||
/// Returns whether the deque is full (i.e. if `len() == capacity()`.
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.full
|
||||
}
|
||||
|
||||
/// Returns a pair of slices which contain, in order, the contents of the `Deque`.
|
||||
pub fn as_slices(&self) -> (&[T], &[T]) {
|
||||
// NOTE(unsafe) avoid bound checks in the slicing operation
|
||||
unsafe {
|
||||
if self.is_empty() {
|
||||
(&[], &[])
|
||||
} else if self.back <= self.front {
|
||||
(
|
||||
slice::from_raw_parts(
|
||||
self.buffer.as_ptr().add(self.front) as *const T,
|
||||
N - self.front,
|
||||
),
|
||||
slice::from_raw_parts(self.buffer.as_ptr() as *const T, self.back),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
slice::from_raw_parts(
|
||||
self.buffer.as_ptr().add(self.front) as *const T,
|
||||
self.back - self.front,
|
||||
),
|
||||
&[],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pair of mutable slices which contain, in order, the contents of the `Deque`.
|
||||
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
|
||||
// NOTE(unsafe) avoid bound checks in the slicing operation
|
||||
unsafe {
|
||||
if self.is_empty() {
|
||||
(&mut [], &mut [])
|
||||
} else if self.back <= self.front {
|
||||
(
|
||||
slice::from_raw_parts_mut(
|
||||
self.buffer.as_mut_ptr().add(self.front) as *mut T,
|
||||
N - self.front,
|
||||
),
|
||||
slice::from_raw_parts_mut(self.buffer.as_mut_ptr() as *mut T, self.back),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
slice::from_raw_parts_mut(
|
||||
self.buffer.as_mut_ptr().add(self.front) as *mut T,
|
||||
self.back - self.front,
|
||||
),
|
||||
&mut [],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a reference to the front element, or None if the `Deque` is empty.
|
||||
pub fn front(&self) -> Option<&T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &*self.buffer.get_unchecked(self.front).as_ptr() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the front element, or None if the `Deque` is empty.
|
||||
pub fn front_mut(&mut self) -> Option<&mut T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { &mut *self.buffer.get_unchecked_mut(self.front).as_mut_ptr() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a reference to the back element, or None if the `Deque` is empty.
|
||||
pub fn back(&self) -> Option<&T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let index = Self::decrement(self.back);
|
||||
Some(unsafe { &*self.buffer.get_unchecked(index).as_ptr() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a mutable reference to the back element, or None if the `Deque` is empty.
|
||||
pub fn back_mut(&mut self) -> Option<&mut T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let index = Self::decrement(self.back);
|
||||
Some(unsafe { &mut *self.buffer.get_unchecked_mut(index).as_mut_ptr() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the item from the front of the deque and returns it, or `None` if it's empty
|
||||
pub fn pop_front(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.pop_front_unchecked() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the item from the back of the deque and returns it, or `None` if it's empty
|
||||
pub fn pop_back(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.pop_back_unchecked() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends an `item` to the front of the deque
|
||||
///
|
||||
/// Returns back the `item` if the deque is full
|
||||
pub fn push_front(&mut self, item: T) -> Result<(), T> {
|
||||
if self.is_full() {
|
||||
Err(item)
|
||||
} else {
|
||||
unsafe { self.push_front_unchecked(item) }
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends an `item` to the back of the deque
|
||||
///
|
||||
/// Returns back the `item` if the deque is full
|
||||
pub fn push_back(&mut self, item: T) -> Result<(), T> {
|
||||
if self.is_full() {
|
||||
Err(item)
|
||||
} else {
|
||||
unsafe { self.push_back_unchecked(item) }
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes an item from the front of the deque and returns it
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This assumes the deque is not empty.
|
||||
pub(crate) unsafe fn pop_front_unchecked(&mut self) -> T {
|
||||
debug_assert!(!self.is_empty());
|
||||
|
||||
let index = self.front;
|
||||
self.full = false;
|
||||
self.front = Self::increment(self.front);
|
||||
(self.buffer.get_unchecked_mut(index).as_ptr() as *const T).read()
|
||||
}
|
||||
|
||||
/// Removes an item from the back of the deque and returns it
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This assumes the deque is not empty.
|
||||
pub(crate) unsafe fn pop_back_unchecked(&mut self) -> T {
|
||||
debug_assert!(!self.is_empty());
|
||||
|
||||
self.full = false;
|
||||
self.back = Self::decrement(self.back);
|
||||
(self.buffer.get_unchecked_mut(self.back).as_ptr() as *const T).read()
|
||||
}
|
||||
|
||||
/// Appends an `item` to the front of the deque
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This assumes the deque is not full.
|
||||
pub unsafe fn push_front_unchecked(&mut self, item: T) {
|
||||
debug_assert!(!self.is_full());
|
||||
|
||||
let index = Self::decrement(self.front);
|
||||
// NOTE: the memory slot that we are about to write to is uninitialized. We assign
|
||||
// a `MaybeUninit` to avoid running `T`'s destructor on the uninitialized memory
|
||||
*self.buffer.get_unchecked_mut(index) = MaybeUninit::new(item);
|
||||
self.front = index;
|
||||
if self.front == self.back {
|
||||
self.full = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends an `item` to the back of the deque
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This assumes the deque is not full.
|
||||
pub unsafe fn push_back_unchecked(&mut self, item: T) {
|
||||
debug_assert!(!self.is_full());
|
||||
|
||||
// NOTE: the memory slot that we are about to write to is uninitialized. We assign
|
||||
// a `MaybeUninit` to avoid running `T`'s destructor on the uninitialized memory
|
||||
*self.buffer.get_unchecked_mut(self.back) = MaybeUninit::new(item);
|
||||
self.back = Self::increment(self.back);
|
||||
if self.front == self.back {
|
||||
self.full = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the deque.
|
||||
pub fn iter(&self) -> Iter<'_, T, N> {
|
||||
let done = self.is_empty();
|
||||
Iter {
|
||||
_phantom: PhantomData,
|
||||
buffer: &self.buffer as *const MaybeUninit<T>,
|
||||
front: self.front,
|
||||
back: self.back,
|
||||
done,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that allows modifying each value.
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
|
||||
let done = self.is_empty();
|
||||
IterMut {
|
||||
_phantom: PhantomData,
|
||||
buffer: &mut self.buffer[0] as *mut MaybeUninit<T>,
|
||||
front: self.front,
|
||||
back: self.back,
|
||||
done,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trait implementations
|
||||
|
||||
impl<T, const N: usize> Default for Deque<T, N> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Drop for Deque<T, N> {
|
||||
fn drop(&mut self) {
|
||||
// safety: `self` is left in an inconsistent state but it doesn't matter since
|
||||
// it's getting dropped. Nothing should be able to observe `self` after drop.
|
||||
unsafe { self.drop_contents() }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that moves out of a [`Deque`].
|
||||
///
|
||||
/// This struct is created by calling the `into_iter` method.
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct IntoIter<T, const N: usize> {
|
||||
deque: Deque<T, N>,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.deque.pop_front()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIterator for Deque<T, N> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T, N>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter { deque: self }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the elements of a [`Deque`].
|
||||
///
|
||||
/// This struct is created by calling the `iter` method.
|
||||
#[derive(Clone)]
|
||||
pub struct Iter<'a, T, const N: usize> {
|
||||
buffer: *const MaybeUninit<T>,
|
||||
_phantom: PhantomData<&'a T>,
|
||||
front: usize,
|
||||
back: usize,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> Iterator for Iter<'a, T, N> {
|
||||
type Item = &'a T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done {
|
||||
None
|
||||
} else {
|
||||
let index = self.front;
|
||||
self.front = Deque::<T, N>::increment(self.front);
|
||||
if self.front == self.back {
|
||||
self.done = true;
|
||||
}
|
||||
Some(unsafe { &*(self.buffer.add(index) as *const T) })
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = if self.done {
|
||||
0
|
||||
} else if self.back <= self.front {
|
||||
self.back + N - self.front
|
||||
} else {
|
||||
self.back - self.front
|
||||
};
|
||||
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> DoubleEndedIterator for Iter<'a, T, N> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.done {
|
||||
None
|
||||
} else {
|
||||
self.back = Deque::<T, N>::decrement(self.back);
|
||||
if self.front == self.back {
|
||||
self.done = true;
|
||||
}
|
||||
Some(unsafe { &*(self.buffer.add(self.back) as *const T) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> ExactSizeIterator for Iter<'a, T, N> {}
|
||||
impl<'a, T, const N: usize> FusedIterator for Iter<'a, T, N> {}
|
||||
|
||||
/// An iterator over the elements of a [`Deque`].
|
||||
///
|
||||
/// This struct is created by calling the `iter` method.
|
||||
pub struct IterMut<'a, T, const N: usize> {
|
||||
buffer: *mut MaybeUninit<T>,
|
||||
_phantom: PhantomData<&'a mut T>,
|
||||
front: usize,
|
||||
back: usize,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> Iterator for IterMut<'a, T, N> {
|
||||
type Item = &'a mut T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done {
|
||||
None
|
||||
} else {
|
||||
let index = self.front;
|
||||
self.front = Deque::<T, N>::increment(self.front);
|
||||
if self.front == self.back {
|
||||
self.done = true;
|
||||
}
|
||||
Some(unsafe { &mut *(self.buffer.add(index) as *mut T) })
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = if self.done {
|
||||
0
|
||||
} else if self.back <= self.front {
|
||||
self.back + N - self.front
|
||||
} else {
|
||||
self.back - self.front
|
||||
};
|
||||
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> DoubleEndedIterator for IterMut<'a, T, N> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.done {
|
||||
None
|
||||
} else {
|
||||
self.back = Deque::<T, N>::decrement(self.back);
|
||||
if self.front == self.back {
|
||||
self.done = true;
|
||||
}
|
||||
Some(unsafe { &mut *(self.buffer.add(self.back) as *mut T) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> ExactSizeIterator for IterMut<'a, T, N> {}
|
||||
impl<'a, T, const N: usize> FusedIterator for IterMut<'a, T, N> {}
|
||||
|
||||
impl<'a, T, const N: usize> IntoIterator for &'a Deque<T, N> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = Iter<'a, T, N>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> IntoIterator for &'a mut Deque<T, N> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = IterMut<'a, T, N>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Clone for Deque<T, N>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
let mut res = Deque::new();
|
||||
for i in self {
|
||||
// safety: the original and new deques have the same capacity, so it can
|
||||
// not become full.
|
||||
unsafe { res.push_back_unchecked(i.clone()) }
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Deque;
|
||||
|
||||
#[test]
|
||||
fn static_new() {
|
||||
static mut _V: Deque<i32, 4> = Deque::new();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stack_new() {
|
||||
let mut _v: Deque<i32, 4> = Deque::new();
|
||||
}
|
||||
|
||||
macro_rules! droppable {
|
||||
() => {
|
||||
struct Droppable;
|
||||
impl Droppable {
|
||||
fn new() -> Self {
|
||||
unsafe {
|
||||
COUNT += 1;
|
||||
}
|
||||
Droppable
|
||||
}
|
||||
}
|
||||
impl Drop for Droppable {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
COUNT -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut COUNT: i32 = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop() {
|
||||
droppable!();
|
||||
|
||||
{
|
||||
let mut v: Deque<Droppable, 2> = Deque::new();
|
||||
v.push_back(Droppable::new()).ok().unwrap();
|
||||
v.push_back(Droppable::new()).ok().unwrap();
|
||||
v.pop_front().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
|
||||
{
|
||||
let mut v: Deque<Droppable, 2> = Deque::new();
|
||||
v.push_back(Droppable::new()).ok().unwrap();
|
||||
v.push_back(Droppable::new()).ok().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
{
|
||||
let mut v: Deque<Droppable, 2> = Deque::new();
|
||||
v.push_front(Droppable::new()).ok().unwrap();
|
||||
v.push_front(Droppable::new()).ok().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
|
||||
v.push_back(0).unwrap();
|
||||
v.push_front(1).unwrap();
|
||||
v.push_back(2).unwrap();
|
||||
v.push_back(3).unwrap();
|
||||
|
||||
assert!(v.push_front(4).is_err());
|
||||
assert!(v.push_back(4).is_err());
|
||||
assert!(v.is_full());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
assert!(v.is_empty());
|
||||
|
||||
v.push_back(0).unwrap();
|
||||
assert!(!v.is_empty());
|
||||
|
||||
v.push_front(1).unwrap();
|
||||
assert!(!v.is_empty());
|
||||
|
||||
v.pop_front().unwrap();
|
||||
v.pop_front().unwrap();
|
||||
|
||||
assert!(v.pop_front().is_none());
|
||||
assert!(v.pop_back().is_none());
|
||||
assert!(v.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn front_back() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
assert_eq!(v.front(), None);
|
||||
assert_eq!(v.front_mut(), None);
|
||||
assert_eq!(v.back(), None);
|
||||
assert_eq!(v.back_mut(), None);
|
||||
|
||||
v.push_back(4).unwrap();
|
||||
assert_eq!(v.front(), Some(&4));
|
||||
assert_eq!(v.front_mut(), Some(&mut 4));
|
||||
assert_eq!(v.back(), Some(&4));
|
||||
assert_eq!(v.back_mut(), Some(&mut 4));
|
||||
|
||||
v.push_front(3).unwrap();
|
||||
assert_eq!(v.front(), Some(&3));
|
||||
assert_eq!(v.front_mut(), Some(&mut 3));
|
||||
assert_eq!(v.back(), Some(&4));
|
||||
assert_eq!(v.back_mut(), Some(&mut 4));
|
||||
|
||||
v.pop_back().unwrap();
|
||||
assert_eq!(v.front(), Some(&3));
|
||||
assert_eq!(v.front_mut(), Some(&mut 3));
|
||||
assert_eq!(v.back(), Some(&3));
|
||||
assert_eq!(v.back_mut(), Some(&mut 3));
|
||||
|
||||
v.pop_front().unwrap();
|
||||
assert_eq!(v.front(), None);
|
||||
assert_eq!(v.front_mut(), None);
|
||||
assert_eq!(v.back(), None);
|
||||
assert_eq!(v.back_mut(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
|
||||
v.push_back(0).unwrap();
|
||||
v.push_back(1).unwrap();
|
||||
v.push_front(2).unwrap();
|
||||
v.push_front(3).unwrap();
|
||||
v.pop_back().unwrap();
|
||||
v.push_front(4).unwrap();
|
||||
|
||||
let mut items = v.iter();
|
||||
|
||||
assert_eq!(items.next(), Some(&4));
|
||||
assert_eq!(items.next(), Some(&3));
|
||||
assert_eq!(items.next(), Some(&2));
|
||||
assert_eq!(items.next(), Some(&0));
|
||||
assert_eq!(items.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_mut() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
|
||||
v.push_back(0).unwrap();
|
||||
v.push_back(1).unwrap();
|
||||
v.push_front(2).unwrap();
|
||||
v.push_front(3).unwrap();
|
||||
v.pop_back().unwrap();
|
||||
v.push_front(4).unwrap();
|
||||
|
||||
let mut items = v.iter_mut();
|
||||
|
||||
assert_eq!(items.next(), Some(&mut 4));
|
||||
assert_eq!(items.next(), Some(&mut 3));
|
||||
assert_eq!(items.next(), Some(&mut 2));
|
||||
assert_eq!(items.next(), Some(&mut 0));
|
||||
assert_eq!(items.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_move() {
|
||||
let mut v: Deque<i32, 4> = Deque::new();
|
||||
v.push_back(0).unwrap();
|
||||
v.push_back(1).unwrap();
|
||||
v.push_back(2).unwrap();
|
||||
v.push_back(3).unwrap();
|
||||
|
||||
let mut items = v.into_iter();
|
||||
|
||||
assert_eq!(items.next(), Some(0));
|
||||
assert_eq!(items.next(), Some(1));
|
||||
assert_eq!(items.next(), Some(2));
|
||||
assert_eq!(items.next(), Some(3));
|
||||
assert_eq!(items.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_move_drop() {
|
||||
droppable!();
|
||||
|
||||
{
|
||||
let mut deque: Deque<Droppable, 2> = Deque::new();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
let mut items = deque.into_iter();
|
||||
// Move all
|
||||
let _ = items.next();
|
||||
let _ = items.next();
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
|
||||
{
|
||||
let mut deque: Deque<Droppable, 2> = Deque::new();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
let _items = deque.into_iter();
|
||||
// Move none
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
|
||||
{
|
||||
let mut deque: Deque<Droppable, 2> = Deque::new();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
deque.push_back(Droppable::new()).ok().unwrap();
|
||||
let mut items = deque.into_iter();
|
||||
let _ = items.next(); // Move partly
|
||||
}
|
||||
|
||||
assert_eq!(unsafe { COUNT }, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_and_pop() {
|
||||
let mut q: Deque<i32, 4> = Deque::new();
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
assert_eq!(q.pop_front(), None);
|
||||
assert_eq!(q.pop_back(), None);
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
q.push_back(0).unwrap();
|
||||
assert_eq!(q.len(), 1);
|
||||
|
||||
assert_eq!(q.pop_back(), Some(0));
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
q.push_back(0).unwrap();
|
||||
q.push_back(1).unwrap();
|
||||
q.push_front(2).unwrap();
|
||||
q.push_front(3).unwrap();
|
||||
assert_eq!(q.len(), 4);
|
||||
|
||||
// deque contains: 3 2 0 1
|
||||
assert_eq!(q.pop_front(), Some(3));
|
||||
assert_eq!(q.len(), 3);
|
||||
assert_eq!(q.pop_front(), Some(2));
|
||||
assert_eq!(q.len(), 2);
|
||||
assert_eq!(q.pop_back(), Some(1));
|
||||
assert_eq!(q.len(), 1);
|
||||
assert_eq!(q.pop_front(), Some(0));
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
// deque is now empty
|
||||
assert_eq!(q.pop_front(), None);
|
||||
assert_eq!(q.pop_back(), None);
|
||||
assert_eq!(q.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_slices() {
|
||||
let mut q: Deque<i32, 4> = Deque::new();
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
q.push_back(0).unwrap();
|
||||
q.push_back(1).unwrap();
|
||||
q.push_back(2).unwrap();
|
||||
q.push_back(3).unwrap();
|
||||
assert_eq!(q.as_slices(), (&[0, 1, 2, 3][..], &[][..]));
|
||||
|
||||
q.pop_front().unwrap();
|
||||
assert_eq!(q.as_slices(), (&[1, 2, 3][..], &[][..]));
|
||||
|
||||
q.push_back(4).unwrap();
|
||||
assert_eq!(q.as_slices(), (&[1, 2, 3][..], &[4][..]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear() {
|
||||
let mut q: Deque<i32, 4> = Deque::new();
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
q.push_back(0).unwrap();
|
||||
q.push_back(1).unwrap();
|
||||
q.push_back(2).unwrap();
|
||||
q.push_back(3).unwrap();
|
||||
assert_eq!(q.len(), 4);
|
||||
|
||||
q.clear();
|
||||
assert_eq!(q.len(), 0);
|
||||
|
||||
q.push_back(0).unwrap();
|
||||
assert_eq!(q.len(), 1);
|
||||
}
|
||||
}
|
@ -74,6 +74,7 @@
|
||||
#![deny(const_err)]
|
||||
|
||||
pub use binary_heap::BinaryHeap;
|
||||
pub use deque::Deque;
|
||||
pub use histbuf::HistoryBuffer;
|
||||
pub use indexmap::{Bucket, FnvIndexMap, IndexMap, Pos};
|
||||
pub use indexset::{FnvIndexSet, IndexSet};
|
||||
@ -81,7 +82,7 @@ pub use linear_map::LinearMap;
|
||||
pub use string::String;
|
||||
pub use vec::Vec;
|
||||
|
||||
// NOTE this code was last ported from v0.4.1 of the indexmap crate
|
||||
mod deque;
|
||||
mod histbuf;
|
||||
mod indexmap;
|
||||
mod indexset;
|
||||
|
@ -846,7 +846,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn stack_new() {
|
||||
static mut _V: Vec<i32, 4> = Vec::new();
|
||||
let mut _v: Vec<i32, 4> = Vec::new();
|
||||
}
|
||||
|
||||
macro_rules! droppable {
|
||||
|
Loading…
x
Reference in New Issue
Block a user