arraydeque-0.5.1/.cargo_vcs_info.json0000644000000001360000000000100132010ustar { "git": { "sha1": "2ccf30574a2fac91311a0fca7b32f99d41f5680e" }, "path_in_vcs": "" }arraydeque-0.5.1/.github/workflows/ci.yml000064400000000000000000000017640072674642500165440ustar 00000000000000on: push: branches: [ master ] pull_request: branches: [ master ] name: Continuous integration env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 jobs: tests: runs-on: ubuntu-latest strategy: matrix: include: - rust: 1.59.0 # MSRV - rust: stable - rust: beta - rust: nightly steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - name: Tests run: | cargo test --verbose --no-default-features cargo test --verbose --no-default-features --features "std" miri: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Miri run: | rustup toolchain install nightly --component miri rustup override set nightly cargo miri setup - name: Test with Miri run: cargo miri test arraydeque-0.5.1/.gitignore000064400000000000000000000000220072674642500140030ustar 00000000000000target Cargo.lock arraydeque-0.5.1/.travis.yml000064400000000000000000000004370072674642500141360ustar 00000000000000language: rust sudo: required matrix: include: - rust: 1.20.0 - rust: stable - rust: beta - rust: nightly branches: only: - master script: - | cargo test --verbose && cargo build --verbose && cargo build --verbose --no-default-features && arraydeque-0.5.1/Cargo.toml0000644000000020510000000000100111750ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "arraydeque" version = "0.5.1" authors = ["andylokandy"] description = "A ring buffer with a fixed capacity, which can be stored on the stack." homepage = "https://github.com/andylokandy/arraydeque" documentation = "https://docs.rs/arraydeque" readme = "README.md" keywords = [ "ring", "circular", "stack", "deque", "array", ] categories = [ "no-std", "data-structures", "memory-management", ] license = "MIT/Apache-2.0" repository = "https://github.com/andylokandy/arraydeque" resolver = "2" [features] default = ["std"] std = [] arraydeque-0.5.1/Cargo.toml.orig000064400000000000000000000010160072674642500147060ustar 00000000000000[package] name = "arraydeque" version = "0.5.1" authors = ["andylokandy"] license = "MIT/Apache-2.0" edition = "2021" description = "A ring buffer with a fixed capacity, which can be stored on the stack." documentation = "https://docs.rs/arraydeque" repository = "https://github.com/andylokandy/arraydeque" homepage = "https://github.com/andylokandy/arraydeque" keywords = ["ring", "circular", "stack", "deque", "array"] categories = ["no-std", "data-structures", "memory-management"] [features] default = ["std"] std = [] arraydeque-0.5.1/LICENSE000064400000000000000000000021150072674642500130250ustar 00000000000000The MIT License (MIT) Copyright (c) 2018 Andy Lok Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. arraydeque-0.5.1/README.md000064400000000000000000000043210072674642500133000ustar 00000000000000# `arraydeque` [![build status](https://travis-ci.org/andylokandy/arraydeque.svg?branch=master)](https://travis-ci.org/andylokandy/arraydeque) [![crates.io](https://img.shields.io/crates/v/arraydeque.svg)](https://crates.io/crates/arraydeque) [![docs.rs](https://docs.rs/arraydeque/badge.svg)](https://docs.rs/arraydeque) A circular buffer with fixed capacity. Requires Rust 1.59+. This crate is inspired by [**bluss/arrayvec**](https://github.com/bluss/arrayvec) ### [**Documentation**](https://docs.rs/arraydeque) ## Usage First, add the following to your `Cargo.toml`: ```toml [dependencies] arraydeque = "0.5" ``` Next, add this to your crate root: ```rust 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 } ``` ## Example ```rust extern crate arraydeque; use arraydeque::ArrayDeque; fn main() { let mut deque: ArrayDeque<_, 2> = ArrayDeque::new(); assert_eq!(deque.capacity(), 2); assert_eq!(deque.len(), 0); 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.pop_front(), None); } ``` ## Changelog - 0.5.1 Make `ArrayDeque::new()` a const fn. - 0.5.0 Support consnt generic capacity. Remove `use_generic_array` feature. - 0.4.5 Update `generic-array` to `0.12`. - 0.4.4 Fix UB: `Some(ArrayDeque::new(xs)).is_some() == false`. ([#12](https://github.com/andylokandy/arraydeque/issues/12)) - 0.4.3 Add support for `generic-array` under `use_generic_array` feature. - 0.4.1 Capacity now equal to backend_array.len(). - 0.3.1 Add behaviors: `Saturating` and `Wrapping`. ## Contribution All kinds of contribution are welcomed. - **Issues.** Feel free to open an issue when you find typos, bugs, or have any question. - **Pull requests**. New collection, better implementation, more tests, more documents and typo fixes are all welcomed. ## License Licensed under MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) arraydeque-0.5.1/src/behavior.rs000064400000000000000000000031020072674642500147510ustar 00000000000000//! Behavior semantics for `ArrayDeque`. //! //! `ArrayDeque` provides two different behaviors, `Saturating` and `Wrapping`, //! determining whether to remove existing element automatically when pushing //! to a full deque. //! //! The behavior is indicated by a marker type parameter of `ArrayDeque`, //! which defaults to `Saturating`. //! //! ## Saturating //! //! Pushing any element when `ArrayDeque` is full will directly return an `Err(CapacityError)` //! containing the element attempting to push, leaving the `ArrayDeque` unchanged. //! //! ``` //! use arraydeque::{ArrayDeque, Saturating, CapacityError}; //! //! let mut tester: ArrayDeque<_, 2, Saturating> = ArrayDeque::new(); //! //! assert_eq!(tester.push_back(1), Ok(())); //! assert_eq!(tester.push_back(2), Ok(())); //! assert_eq!(tester.push_back(3), Err(CapacityError { element: 3 })); //! ``` //! //! ## Wrapping //! //! Pushing any element when `ArrayDeque` is full will pop an element at //! the other side to spare room. //! //! ``` //! use arraydeque::{ArrayDeque, Wrapping}; //! //! let mut tester: ArrayDeque<_, 2, Wrapping> = ArrayDeque::new(); //! //! assert_eq!(tester.push_back(1), None); //! assert_eq!(tester.push_back(2), None); //! assert_eq!(tester.push_back(3), Some(1)); //! ``` /// Marker trait for indicating behaviors of `ArrayDeque`. pub trait Behavior {} /// Behavior for `ArrayDeque` that specifies saturating write semantics. pub struct Saturating; impl Behavior for Saturating {} /// Behavior for `ArrayDeque` that specifies wrapping write semantics. pub struct Wrapping; impl Behavior for Wrapping {} arraydeque-0.5.1/src/error.rs000064400000000000000000000013450072674642500143120ustar 00000000000000#[cfg(feature = "std")] use std::error::Error; use std::fmt; /// Error value indicating insufficient capacity /// /// This error only occur to `ArrayDeque<_, Saturating>`. #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] pub struct CapacityError { /// The element that caused the error. pub element: T, } const CAPERROR: &str = "insufficient capacity"; #[cfg(feature = "std")] impl Error for CapacityError {} impl fmt::Display for CapacityError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(CAPERROR) } } impl fmt::Debug for CapacityError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "CapacityError: {}", CAPERROR) } } arraydeque-0.5.1/src/lib.rs000064400000000000000000002670760072674642500137460ustar 00000000000000//! 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_attr(not(any(feature = "std", test)), no_std)] #![deny(missing_docs)] #[cfg(not(any(feature = "std", test)))] extern crate 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; use behavior::Behavior; pub mod behavior; mod error; mod range; pub use behavior::{Saturating, Wrapping}; pub use error::CapacityError; pub use range::RangeArgument; /// 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. pub struct ArrayDeque { xs: MaybeUninit<[T; CAP]>, tail: usize, len: usize, marker: marker::PhantomData, } impl ArrayDeque { /// 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)); /// ``` pub fn push_front(&mut self, element: T) -> Result<(), CapacityError> { 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)); /// ``` pub fn push_back(&mut self, element: T) -> Result<(), CapacityError> { 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] pub fn insert(&mut self, index: usize, element: T) -> Result<(), CapacityError> { assert!(index <= self.len(), "index out of bounds"); if self.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)] pub fn extend_front(&mut self, iter: I) where I: IntoIterator, { 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)] pub fn extend_back(&mut self, iter: I) where I: IntoIterator, { let take = self.capacity() - self.len(); for element in iter.into_iter().take(take) { self.push_back(element); } } } #[allow(unused_must_use)] impl Extend for ArrayDeque { fn extend(&mut self, iter: I) where I: IntoIterator, { self.extend_back(iter); } } impl FromIterator for ArrayDeque { fn from_iter(iter: I) -> Self where I: IntoIterator, { let mut array: ArrayDeque<_, CAP, Saturating> = ArrayDeque::new(); array.extend_back(iter); array } } impl Clone for ArrayDeque where T: Clone, { fn clone(&self) -> Self { self.iter().cloned().collect() } } impl ArrayDeque { /// Add an element to the front of the deque. /// /// Return `None` if deque still has capacity, or `Some(existing)` /// if the deque is full, where `existing` is the backmost element being kicked out. /// /// # Examples /// /// ``` /// // 1 -(+)-> [_, _, _] => [1, _, _] -> None /// // 2 -(+)-> [1, _, _] => [2, 1, _] -> None /// // 3 -(+)-> [2, 1, _] => [3, 2, 1] -> None /// // 4 -(+)-> [3, 2, 1] => [4, 3, 2] -> Some(1) /// /// use arraydeque::{ArrayDeque, Wrapping}; /// /// let mut buf: ArrayDeque<_, 3, Wrapping> = ArrayDeque::new(); /// /// buf.push_front(1); /// buf.push_front(2); /// buf.push_front(3); /// /// let existing = buf.push_front(4); /// /// assert_eq!(existing, Some(1)); /// assert_eq!(buf.back(), Some(&2)); /// ``` pub fn push_front(&mut self, element: T) -> Option { let existing = if self.is_full() { if self.capacity() == 0 { return Some(element); } else { self.pop_back() } } else { None }; unsafe { self.push_front_unchecked(element); } existing } /// Appends an element to the back of a buffer /// /// Return `None` if deque still has capacity, or `Some(existing)` /// if the deque is full, where `existing` is the frontmost element being kicked out. /// /// # Examples /// /// ``` /// // [_, _, _] <-(+)- 1 => [_, _, 1] -> None /// // [_, _, 1] <-(+)- 2 => [_, 1, 2] -> None /// // [_, 1, 2] <-(+)- 3 => [1, 2, 3] -> None /// // [1, 2, 3] <-(+)- 4 => [2, 3, 4] -> Some(1) /// /// use arraydeque::{ArrayDeque, Wrapping}; /// /// let mut buf: ArrayDeque<_, 3, Wrapping> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// /// let existing = buf.push_back(4); /// /// assert_eq!(existing, Some(1)); /// assert_eq!(buf.back(), Some(&4)); /// ``` pub fn push_back(&mut self, element: T) -> Option { let existing = if self.is_full() { if self.capacity() == 0 { return Some(element); } else { self.pop_front() } } else { None }; unsafe { self.push_back_unchecked(element); } existing } /// Extend deque from front with the contents of an iterator. /// /// Extracts all items from iterator and kicks out the backmost element if necessary. /// /// # 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, _] => [1, 2, 3, 4, 5, 6, 7] /// /// use arraydeque::{ArrayDeque, Wrapping}; /// /// let mut buf: ArrayDeque<_, 7, Wrapping> = 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, [1, 2, 3, 4, 5, 6, 7].into()); /// ``` pub fn extend_front(&mut self, iter: I) where I: IntoIterator, { for element in iter.into_iter() { self.push_front(element); } } /// Extend deque from back with the contents of an iterator. /// /// Extracts all items from iterator and kicks out the frontmost element if necessary. /// /// # 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] => [3, 4, 5, 6, 7, 8, 9] /// /// use arraydeque::{ArrayDeque, Wrapping}; /// /// let mut buf: ArrayDeque<_, 7, Wrapping> = 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, [3, 4, 5, 6, 7, 8, 9].into()); /// ``` pub fn extend_back(&mut self, iter: I) where I: IntoIterator, { for element in iter.into_iter() { self.push_back(element); } } } #[allow(unused_must_use)] impl Extend for ArrayDeque { fn extend(&mut self, iter: I) where I: IntoIterator, { let take = self.capacity() - self.len(); for elt in iter.into_iter().take(take) { self.push_back(elt); } } } impl FromIterator for ArrayDeque { fn from_iter(iter: I) -> Self where I: IntoIterator, { let mut array: ArrayDeque<_, CAP, Wrapping> = ArrayDeque::new(); array.extend_back(iter); array } } impl Clone for ArrayDeque where T: Clone, { fn clone(&self) -> Self { self.iter().cloned().collect() } } // primitive private methods impl ArrayDeque { #[inline] fn wrap_add(index: usize, addend: usize) -> usize { wrap_add(index, addend, CAP) } #[inline] fn wrap_sub(index: usize, subtrahend: usize) -> usize { wrap_sub(index, subtrahend, CAP) } #[inline] fn ptr(&self) -> *const T { self.xs.as_ptr().cast() } #[inline] fn ptr_mut(&mut self) -> *mut T { self.xs.as_mut_ptr().cast() } #[inline] fn is_contiguous(&self) -> bool { self.tail() + self.len() < CAP } #[inline] fn head(&self) -> usize { let tail = self.tail(); let len = self.len(); Self::wrap_add(tail, len) } #[inline] fn tail(&self) -> usize { self.tail } #[inline] unsafe fn set_tail(&mut self, tail: usize) { debug_assert!(tail <= self.capacity()); self.tail = tail; } #[inline] unsafe fn set_len(&mut self, len: usize) { debug_assert!(len <= self.capacity()); self.len = len; } #[inline] unsafe fn set_tail_backward(&mut self) { let new_tail = Self::wrap_sub(self.tail(), 1); let new_len = self.len() + 1; self.tail = new_tail; self.len = new_len; } #[inline] unsafe fn set_tail_forward(&mut self) { debug_assert!(!self.is_empty()); let new_tail = Self::wrap_add(self.tail(), 1); let new_len = self.len() - 1; self.tail = new_tail; self.len = new_len; } #[inline] unsafe fn set_head_backward(&mut self) { debug_assert!(!self.is_empty()); let new_len = self.len() - 1; self.len = new_len; } #[inline] unsafe fn set_head_forward(&mut self) { debug_assert!(self.len() < CAP); let new_len = self.len() + 1; self.len = new_len; } #[inline] unsafe fn push_front_unchecked(&mut self, element: T) { debug_assert!(!self.is_full()); self.set_tail_backward(); let tail = self.tail(); self.buffer_write(tail, element); } #[inline] unsafe fn push_back_unchecked(&mut self, element: T) { debug_assert!(!self.is_full()); let head = self.head(); self.buffer_write(head, element); self.set_head_forward(); } #[allow(unused_unsafe)] #[inline] unsafe fn insert_unchecked(&mut self, index: usize, element: T) { debug_assert!(!self.is_full()); // 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] unsafe fn copy(&mut self, 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). unsafe fn wrap_copy(&mut self, 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] unsafe fn buffer_read(&mut self, offset: usize) -> T { ptr::read(self.ptr().add(offset)) } #[inline] unsafe fn buffer_write(&mut self, offset: usize, element: T) { ptr::write(self.ptr_mut().add(offset), element); } } impl ArrayDeque { /// Creates an empty `ArrayDeque`. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let buf: ArrayDeque = ArrayDeque::new(); /// ``` #[inline] pub const fn new() -> ArrayDeque { ArrayDeque { xs: MaybeUninit::uninit(), tail: 0, len: 0, marker: marker::PhantomData, } } /// Return the capacity of the `ArrayDeque`. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let buf: ArrayDeque = ArrayDeque::new(); /// /// assert_eq!(buf.capacity(), 2); /// ``` #[inline] pub const fn 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] pub fn 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] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Entire capacity of the underlying storage pub fn as_uninit_slice(&self) -> &[MaybeUninit] { unsafe { std::slice::from_raw_parts(self.xs.as_ptr().cast(), CAP) } } /// Entire capacity of the underlying storage pub fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit] { 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] pub fn 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); /// ``` pub fn contains(&self, x: &T) -> bool where T: PartialEq, { 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)); /// ``` pub fn 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)); /// ``` pub fn front_mut(&mut self) -> Option<&mut T> { if !self.is_empty() { Some(&mut self[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)); /// ``` pub fn 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)); /// ``` pub fn back_mut(&mut self) -> Option<&mut T> { let len = self.len(); if !self.is_empty() { Some(&mut self[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] pub fn 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] pub fn get_mut(&mut self, 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 } } /// Returns a front-to-back iterator. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 3> = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// let expected = [0, 1, 2]; /// /// assert!(buf.iter().eq(expected.iter())); /// ``` #[inline] pub fn iter(&self) -> Iter { Iter { tail: self.tail(), len: self.len(), ring: self.as_uninit_slice(), } } /// Returns a front-to-back iterator that returns mutable references. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque = ArrayDeque::new(); /// /// buf.push_back(0); /// buf.push_back(1); /// buf.push_back(2); /// /// let mut expected = [0, 1, 2]; /// /// assert!(buf.iter_mut().eq(expected.iter_mut())); /// ``` #[inline] pub fn iter_mut(&mut self) -> IterMut { IterMut { tail: self.tail(), len: self.len(), ring: self.as_uninit_slice_mut(), } } /// Make the buffer contiguous /// /// The linearization may be required when interacting with external /// interfaces requiring contiguous slices. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque = ArrayDeque::new(); /// buf.extend_back([1, 2, 3]); /// buf.extend_front([-1, -2, -3]); /// /// buf.linearize(); /// /// assert_eq!(buf.as_slices().1.len(), 0); /// ``` /// /// # Complexity /// /// Takes `O(len())` time and no extra space. pub fn linearize(&mut self) { if self.is_contiguous() { return; } let tail = self.tail(); let len = self.len(); let mut new_tail = tail; let mut dst: usize = 0; while dst < len { let mut src = new_tail; while src < CAP && dst < len { if dst == new_tail { new_tail = src; } let xs = self.ptr_mut(); unsafe { ptr::swap(xs.add(dst), xs.add(src)); } dst += 1; src += 1; } } unsafe { self.set_tail(0); } } /// Removes the first element and returns it, 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.pop_front(), Some(1)); /// assert_eq!(buf.pop_front(), Some(2)); /// assert_eq!(buf.pop_front(), None); /// ``` pub fn pop_front(&mut self) -> Option { if self.is_empty() { return None; } unsafe { let tail = self.tail(); self.set_tail_forward(); Some(self.buffer_read(tail)) } } /// Removes the last element from a buffer and returns it, or `None` if /// it is empty. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 2> = ArrayDeque::new(); /// assert_eq!(buf.pop_back(), None); /// /// buf.push_back(1); /// buf.push_back(2); /// /// assert_eq!(buf.pop_back(), Some(2)); /// assert_eq!(buf.pop_back(), Some(1)); /// ``` pub fn pop_back(&mut self) -> Option { if self.is_empty() { return None; } unsafe { self.set_head_backward(); let head = self.head(); Some(self.buffer_read(head)) } } /// Clears the buffer, removing all values. /// /// # Examples /// /// ``` /// use arraydeque::ArrayDeque; /// /// let mut buf: ArrayDeque<_, 1> = ArrayDeque::new(); /// /// buf.push_back(1); /// buf.clear(); /// /// assert!(buf.is_empty()); /// ``` #[inline] pub fn clear(&mut self) { self.drain(..); } /// 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] pub fn drain(&mut self, range: R) -> Drain where R: RangeArgument, { 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; unsafe { self.set_len(start) } Drain { deque: self as *mut _, after_tail: drain_head, after_len: len - end, iter: Iter { tail: drain_tail, len: drain_len, ring: self.as_uninit_slice_mut(), }, } } /// 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] pub fn swap(&mut self, 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()); /// ``` pub fn swap_remove_back(&mut self, index: usize) -> Option { let length = self.len(); if length > 0 && index < length - 1 { self.swap(index, length - 1); } else if 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()); /// ``` pub fn swap_remove_front(&mut self, index: usize) -> Option { let length = self.len(); if length > 0 && index < length && index != 0 { self.swap(index, 0); } else if 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()); /// ``` pub fn remove(&mut self, index: usize) -> Option { if self.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. if self.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] pub fn split_off(&mut self, at: usize) -> Self { let len = self.len(); assert!(at <= len, "`at` out of bounds"); let other_len = len - at; let mut other = Self::new(); unsafe { let (first_half, second_half) = self.as_slices(); let first_len = first_half.len(); let second_len = second_half.len(); if at < first_len { // `at` lies in the first half. let amount_in_first = first_len - at; ptr::copy_nonoverlapping( first_half.as_ptr().add(at), other.ptr_mut(), amount_in_first, ); // 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()); /// ``` pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, { let len = self.len(); let mut del = 0; for i in 0..len { if !f(&self[i]) { del += 1; } else if 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] pub fn 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); unsafe { (slice_assume_init_ref(right), slice_assume_init_ref(left)) } } } /// 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_mut_slices(), (&mut [0, 1][..], &mut[][..])); /// /// buf.push_front(2); /// /// assert_eq!(buf.as_mut_slices(), (&mut[2][..], &mut[0, 1][..])); /// ``` #[inline] pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { let contiguous = self.is_contiguous(); let head = self.head(); let tail = self.tail(); let buf = self.as_uninit_slice_mut(); if contiguous { let (empty, buf) = buf.split_at_mut(0); unsafe { ( slice_assume_init_mut(&mut buf[tail..head]), slice_assume_init_mut(empty), ) } } else { let (mid, right) = buf.split_at_mut(tail); let (left, _) = mid.split_at_mut(head); unsafe { (slice_assume_init_mut(right), slice_assume_init_mut(left)) } } } } /// Copy of currently-unstable `MaybeUninit::slice_assume_init_ref`. unsafe fn slice_assume_init_ref(slice: &[MaybeUninit]) -> &[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] as *const [T]) } /// Copy of currently-unstable `MaybeUninit::slice_assume_init_mut`. unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &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] as *mut [T]) } impl From> for ArrayDeque { fn from(buf: ArrayDeque) -> Self { buf.into_iter().collect() } } impl From> for ArrayDeque { fn from(buf: ArrayDeque) -> Self { buf.into_iter().collect() } } #[cfg(feature = "std")] impl From> for ArrayDeque where Self: FromIterator, { fn from(vec: Vec) -> Self { vec.into_iter().collect() } } impl From<[T; N]> for ArrayDeque where Self: FromIterator, { fn from(arr: [T; N]) -> Self { arr.into_iter().collect() } } #[cfg(feature = "std")] impl From> for Vec where Self: FromIterator, { fn from(deque: ArrayDeque) -> Self { deque.into_iter().collect() } } impl Drop for ArrayDeque { fn drop(&mut self) { self.clear(); } } impl Default for ArrayDeque { #[inline] fn default() -> Self { ArrayDeque::new() } } impl PartialEq for ArrayDeque where T: PartialEq, { fn eq(&self, other: &Self) -> bool { if self.len() != other.len() { return false; } let (sa, sb) = self.as_slices(); let (oa, ob) = other.as_slices(); match sa.len().cmp(&oa.len()) { Ordering::Equal => sa == oa && sb == ob, Ordering::Less => { // Always divisible in three sections, for example: // self: [a b c|d e f] // other: [0 1 2 3|4 5] // front = 3, mid = 1, // [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5] let front = sa.len(); let mid = oa.len() - front; let (oa_front, oa_mid) = oa.split_at(front); let (sb_mid, sb_back) = sb.split_at(mid); debug_assert_eq!(sa.len(), oa_front.len()); debug_assert_eq!(sb_mid.len(), oa_mid.len()); debug_assert_eq!(sb_back.len(), ob.len()); sa == oa_front && sb_mid == oa_mid && sb_back == ob } Ordering::Greater => { let front = oa.len(); let mid = sa.len() - front; let (sa_front, sa_mid) = sa.split_at(front); let (ob_mid, ob_back) = ob.split_at(mid); debug_assert_eq!(sa_front.len(), oa.len()); debug_assert_eq!(sa_mid.len(), ob_mid.len()); debug_assert_eq!(sb.len(), ob_back.len()); sa_front == oa && sa_mid == ob_mid && sb == ob_back } } } } impl Eq for ArrayDeque where T: Eq {} impl PartialOrd for ArrayDeque where T: PartialOrd, { fn partial_cmp(&self, other: &Self) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for ArrayDeque where T: Ord, { #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for ArrayDeque where T: Hash, { fn hash(&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 Index for ArrayDeque { 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 IndexMut for ArrayDeque { #[inline] fn index_mut(&mut self, 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 IntoIterator for ArrayDeque { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter { inner: self } } } impl<'a, T, const CAP: usize, B: Behavior> IntoIterator for &'a ArrayDeque { type Item = &'a T; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, T, const CAP: usize, B: Behavior> IntoIterator for &'a mut ArrayDeque { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl fmt::Debug for ArrayDeque where T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list().entries(self).finish() } } #[inline] fn wrap_add(index: usize, addend: usize, capacity: usize) -> usize { debug_assert!(addend <= capacity); (index + addend) % capacity } #[inline] fn wrap_sub(index: usize, subtrahend: usize, capacity: usize) -> usize { debug_assert!(subtrahend <= capacity); (index + capacity - subtrahend) % capacity } /// `ArrayDeque` iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { ring: &'a [MaybeUninit], tail: usize, len: usize, } impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; #[inline] fn next(&mut self) -> Option<&'a T> { if self.len == 0 { return None; } let tail = self.tail; self.tail = wrap_add(self.tail, 1, self.ring.len()); self.len -= 1; unsafe { Some(self.ring.get_unchecked(tail).assume_init_ref()) } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } } impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a T> { if self.len == 0 { return None; } self.len -= 1; let head = wrap_add(self.tail, self.len, self.ring.len()); unsafe { Some(self.ring.get_unchecked(head).assume_init_ref()) } } } impl<'a, T> ExactSizeIterator for Iter<'a, T> {} impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Self { Iter { ring: self.ring, tail: self.tail, len: self.len, } } } /// `ArrayDeque` mutable iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { ring: &'a mut [MaybeUninit], tail: usize, len: usize, } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; #[inline] fn next(&mut self) -> Option<&'a mut T> { if self.len == 0 { return None; } let tail = self.tail; self.tail = wrap_add(self.tail, 1, self.ring.len()); self.len -= 1; unsafe { let elem = self.ring.get_unchecked_mut(tail).assume_init_mut(); Some(std::mem::transmute::<&mut T, &'a mut T>(elem)) } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } } impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut T> { if self.len == 0 { return None; } self.len -= 1; let head = wrap_add(self.tail, self.len, self.ring.len()); unsafe { let elem = self.ring.get_unchecked_mut(head).assume_init_mut(); Some(std::mem::transmute::<&mut T, &'a mut T>(elem)) } } } impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} /// By-value `ArrayDeque` iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct IntoIter { inner: ArrayDeque, } impl Iterator for IntoIter { type Item = T; #[inline] fn next(&mut self) -> Option { self.inner.pop_front() } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.inner.len(); (len, Some(len)) } } impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.inner.pop_back() } } impl ExactSizeIterator for IntoIter {} /// Draining `ArrayDeque` iterator pub struct Drain<'a, T, const CAP: usize, B> where B: Behavior, { after_tail: usize, after_len: usize, iter: Iter<'a, T>, deque: *mut ArrayDeque, } impl<'a, T, const CAP: usize, B> Drop for Drain<'a, T, CAP, B> where B: Behavior, { fn drop(&mut self) { for _ in self.by_ref() {} let source_deque = unsafe { &mut *self.deque }; let tail_len = source_deque.len(); let head_len = self.after_len; let orig_tail = source_deque.tail(); let drain_tail = wrap_add(orig_tail, tail_len, CAP); let drain_head = self.after_tail; let orig_head = wrap_add(drain_head, head_len, CAP); let orig_len = wrap_sub(orig_head, orig_tail, CAP); // Restore the original len value unsafe { source_deque.set_len(orig_len) } match (tail_len, head_len) { (0, 0) => unsafe { source_deque.set_tail(0); source_deque.set_len(0); }, (0, _) => unsafe { source_deque.set_tail(drain_head); source_deque.set_len(head_len); }, (_, 0) => unsafe { source_deque.set_len(tail_len) }, _ => unsafe { if tail_len <= head_len { let new_tail = wrap_sub(drain_head, tail_len, CAP); source_deque.set_tail(new_tail); source_deque.set_len(tail_len + head_len); source_deque.wrap_copy(new_tail, orig_tail, tail_len); } else { source_deque.set_len(tail_len + head_len); source_deque.wrap_copy(drain_tail, drain_head, head_len); } }, } } } impl<'a, T, const CAP: usize, B: Behavior> Iterator for Drain<'a, T, CAP, B> { type Item = T; #[inline] fn next(&mut self) -> Option { self.iter.next().map(|elt| unsafe { ptr::read(elt) }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl<'a, T, const CAP: usize, B: Behavior> DoubleEndedIterator for Drain<'a, T, CAP, B> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) } } impl<'a, T, const CAP: usize, B: Behavior> ExactSizeIterator for Drain<'a, T, CAP, B> {} #[cfg(test)] mod tests { #![allow(unused_must_use)] use super::*; #[test] fn test_simple() { macro_rules! test { ($behavior:ident) => {{ let mut tester: ArrayDeque<_, 7, $behavior> = ArrayDeque::new(); assert_eq!(tester.capacity(), 7); assert_eq!(tester.len(), 0); tester.push_back(1); tester.push_back(2); tester.push_back(3); tester.push_back(4); assert_eq!(tester.len(), 4); assert_eq!(tester.pop_front(), Some(1)); assert_eq!(tester.pop_front(), Some(2)); assert_eq!(tester.len(), 2); assert_eq!(tester.pop_front(), Some(3)); assert_eq!(tester.pop_front(), Some(4)); assert_eq!(tester.pop_front(), None); }}; } test!(Saturating); test!(Wrapping); } #[test] fn test_simple_reversely() { macro_rules! test { ($behavior:ident) => {{ let mut tester: ArrayDeque<_, 7, $behavior> = ArrayDeque::new(); assert_eq!(tester.capacity(), 7); assert_eq!(tester.len(), 0); tester.push_front(1); tester.push_front(2); tester.push_front(3); tester.push_front(4); assert_eq!(tester.len(), 4); assert_eq!(tester.pop_back(), Some(1)); assert_eq!(tester.pop_back(), Some(2)); assert_eq!(tester.len(), 2); assert_eq!(tester.pop_back(), Some(3)); assert_eq!(tester.pop_back(), Some(4)); assert_eq!(tester.pop_back(), None); }}; } test!(Saturating); test!(Wrapping); } #[test] fn test_overflow_saturating() { let mut tester: ArrayDeque<_, 2, Saturating> = ArrayDeque::new(); assert_eq!(tester.push_back(1), Ok(())); assert_eq!(tester.push_back(2), Ok(())); assert_eq!(tester.push_back(3), Err(CapacityError { element: 3 })); let mut tester: ArrayDeque<_, 2, Saturating> = ArrayDeque::new(); assert_eq!(tester.insert(0, 1), Ok(())); assert_eq!(tester.insert(1, 2), Ok(())); assert_eq!(tester.insert(2, 3), Err(CapacityError { element: 3 })); } #[test] fn test_overflow_wrapping() { let mut tester: ArrayDeque<_, 2, Wrapping> = ArrayDeque::new(); assert_eq!(tester.push_back(1), None); assert_eq!(tester.push_back(2), None); assert_eq!(tester.push_back(3), Some(1)); } #[test] fn test_pop_empty() { let mut tester: ArrayDeque<_, 2> = ArrayDeque::new(); assert_eq!(tester.push_back(1), Ok(())); assert_eq!(tester.pop_front(), Some(1)); assert_eq!(tester.is_empty(), true); assert_eq!(tester.len(), 0); assert_eq!(tester.pop_front(), None); } #[test] fn test_index() { let mut tester: ArrayDeque<_, 3> = ArrayDeque::new(); tester.push_back(1); tester.push_back(2); tester.push_back(3); assert_eq!(tester[0], 1); // pop_front 1 <- [2, 3] assert_eq!(tester.pop_front(), Some(1)); assert_eq!(tester[0], 2); assert_eq!(tester.len(), 2); // push_front 0 -> [0, 2, 3] tester.push_front(0); assert_eq!(tester[0], 0); // [0, 2] -> 3 pop_back assert_eq!(tester.pop_back(), Some(3)); assert_eq!(tester[1], 2); } #[test] #[should_panic] fn test_index_overflow() { let mut tester: ArrayDeque<_, 3> = ArrayDeque::new(); tester.push_back(1); tester.push_back(2); tester[2]; } #[test] fn test_iter() { let mut tester: ArrayDeque<_, 2> = ArrayDeque::new(); tester.push_back(1); tester.push_back(2); { let mut iter = tester.iter(); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(iter.next(), Some(&1)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), None); assert_eq!(iter.size_hint(), (0, Some(0))); } tester.pop_front(); tester.push_back(3); { let mut iter = (&tester).into_iter(); assert_eq!(iter.next(), Some(&2)); // test clone let mut iter2 = iter.clone(); assert_eq!(iter.next(), Some(&3)); assert_eq!(iter.next(), None); assert_eq!(iter2.next(), Some(&3)); assert_eq!(iter2.next(), None); } } #[test] fn test_iter_mut() { let mut tester: ArrayDeque<_, 2> = ArrayDeque::new(); tester.push_back(1); tester.push_back(2); { let mut iter = tester.iter_mut(); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(iter.next(), Some(&mut 1)); assert_eq!(iter.next(), Some(&mut 2)); assert_eq!(iter.next(), None); assert_eq!(iter.size_hint(), (0, Some(0))); } tester.pop_front(); tester.push_back(3); { let mut iter = (&mut tester).into_iter(); assert_eq!(iter.next(), Some(&mut 2)); assert_eq!(iter.next(), Some(&mut 3)); assert_eq!(iter.next(), None); } { // mutation let mut iter = tester.iter_mut(); iter.next().map(|n| *n += 1); iter.next().map(|n| *n += 2); } assert_eq!(tester[0], 3); assert_eq!(tester[1], 5); } #[test] fn test_into_iter() { #[derive(Eq, PartialEq, Debug)] struct NoCopy(T); { let mut tester: ArrayDeque, 3> = ArrayDeque::new(); tester.push_back(NoCopy(1)); tester.push_back(NoCopy(2)); let mut iter = tester.into_iter(); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(iter.next(), Some(NoCopy(1))); assert_eq!(iter.next(), Some(NoCopy(2))); assert_eq!(iter.next(), None); assert_eq!(iter.size_hint(), (0, Some(0))); } { let mut tester: ArrayDeque, 3> = ArrayDeque::new(); tester.push_back(NoCopy(1)); tester.push_back(NoCopy(2)); tester.pop_front(); tester.push_back(NoCopy(3)); let mut iter = tester.into_iter(); assert_eq!(iter.next(), Some(NoCopy(2))); assert_eq!(iter.next(), Some(NoCopy(3))); assert_eq!(iter.next(), None); } { let mut tester: ArrayDeque, 3> = ArrayDeque::new(); tester.push_back(NoCopy(1)); tester.push_back(NoCopy(2)); tester.pop_front(); tester.push_back(NoCopy(3)); tester.pop_front(); tester.push_back(NoCopy(4)); let mut iter = tester.into_iter(); assert_eq!(iter.next(), Some(NoCopy(3))); assert_eq!(iter.next(), Some(NoCopy(4))); assert_eq!(iter.next(), None); } } #[test] #[cfg(feature = "std")] fn test_drain() { const CAP: usize = 8; let mut tester: ArrayDeque<_, CAP> = ArrayDeque::new(); for padding in 0..CAP { for drain_start in 0..CAP { for drain_end in drain_start..CAP { // deque starts from different tail position unsafe { tester.set_len(0); tester.set_tail(padding); } tester.extend_back(0..CAP); let mut expected = vec![0, 1, 2, 3, 4, 5, 6, 7]; let drains: Vec<_> = tester.drain(drain_start..drain_end).collect(); let expected_drains: Vec<_> = expected.drain(drain_start..drain_end).collect(); assert_eq!(drains, expected_drains); assert_eq!(tester, expected.into()); } } } } #[test] fn test_drop() { use std::cell::Cell; let flag = &Cell::new(0); struct Bump<'a>(&'a Cell); impl<'a> Drop for Bump<'a> { fn drop(&mut self) { let n = self.0.get(); self.0.set(n + 1); } } { let mut tester = ArrayDeque::::new(); tester.push_back(Bump(flag)); tester.push_back(Bump(flag)); } assert_eq!(flag.get(), 2); // test something with the nullable pointer optimization flag.set(0); { let mut tester = ArrayDeque::<_, 3>::new(); tester.push_back(vec![Bump(flag)]); tester.push_back(vec![Bump(flag), Bump(flag)]); tester.push_back(vec![]); tester.push_back(vec![Bump(flag)]); assert_eq!(flag.get(), 1); drop(tester.pop_back()); assert_eq!(flag.get(), 1); drop(tester.pop_back()); assert_eq!(flag.get(), 3); } assert_eq!(flag.get(), 4); } #[test] fn test_as_slice() { const CAP: usize = 10; let mut tester = ArrayDeque::<_, CAP>::new(); for len in 0..CAP + 1 { for padding in 0..CAP { // deque starts from different tail position unsafe { tester.set_len(0); tester.set_tail(padding); } let mut expected = vec![]; tester.extend_back(0..len); expected.extend(0..len); let split_idx = CAP - padding; if split_idx < len { assert_eq!(tester.as_slices(), expected[..].split_at(split_idx)); } else { assert_eq!(tester.as_slices(), (&expected[..], &[][..])); } } } } #[test] fn test_partial_equal() { const CAP: usize = 10; let mut tester = ArrayDeque::::new(); for len in 0..CAP + 1 { for padding in 0..CAP { // deque starts from different tail position unsafe { tester.set_len(0); tester.set_tail(padding); } let mut expected = ArrayDeque::::new(); for x in 0..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); } } } } #[test] fn test_fmt() { let mut tester = ArrayDeque::<_, 5>::new(); tester.extend_back(0..4); assert_eq!(format!("{:?}", tester), "[0, 1, 2, 3]"); } #[test] fn test_swap_front_back_remove() { fn test(back: bool) { const CAP: usize = 16; let mut tester = ArrayDeque::<_, CAP>::new(); let usable_cap = tester.capacity(); let final_len = usable_cap / 2; for len in 0..final_len { let expected = if back { (0..len).collect() } else { (0..len).rev().collect() }; for padding in 0..usable_cap { unsafe { tester.set_tail(padding); tester.set_len(0); } if back { for i in 0..len * 2 { tester.push_front(i); } for i in 0..len { assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); } } else { for i in 0..len * 2 { tester.push_back(i); } for i in 0..len { let idx = tester.len() - 1 - i; assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); } } assert!(tester.tail() < CAP); assert!(tester.head() < CAP); assert_eq!(tester, expected); } } } test(true); test(false); } #[test] fn test_retain() { const CAP: usize = 10; let mut tester: ArrayDeque<_, CAP> = ArrayDeque::new(); for padding in 0..CAP { unsafe { tester.set_tail(padding); tester.set_len(0); } tester.extend_back(0..CAP); tester.retain(|x| x % 2 == 0); assert_eq!(tester.iter().count(), CAP / 2); } } #[test] fn test_split_off() { const CAP: usize = 16; let mut tester = ArrayDeque::<_, CAP>::new(); for len in 0..CAP + 1 { // index to split at for at in 0..len + 1 { for padding in 0..CAP { let expected_self = (0..).take(at).collect(); let expected_other = (at..).take(len - at).collect(); unsafe { tester.set_len(0); tester.set_tail(padding); } for i in 0..len { tester.push_back(i); } let result = tester.split_off(at); assert!(tester.tail() < CAP); assert!(tester.head() < CAP); assert!(result.tail() < CAP); assert!(result.head() < CAP); assert_eq!(tester, expected_self); assert_eq!(result, expected_other); } } } } #[test] fn test_remove() { const CAP: usize = 16; let mut tester = ArrayDeque::<_, CAP>::new(); // len is the length *after* removal for len in 0..CAP { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect(); for padding in 0..CAP { for to_remove in 0..len + 1 { unsafe { tester.set_tail(padding); tester.set_len(0); } for i in 0..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) } #[test] fn test_option_encoding() { let tester: ArrayDeque, 100> = ArrayDeque::new(); assert!(Some(tester).is_some()); } #[test] fn test_insert_unchecked() { const CAP: usize = 16; let mut tester = ArrayDeque::<_, CAP>::new(); // len is the length *after* insertion for len in 1..CAP { // 0, 1, 2, .., len - 1 let expected = (0..).take(len).collect(); for padding in 0..CAP { for to_insert in 0..len { unsafe { tester.set_tail(padding); tester.set_len(0); } for i in 0..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); } } } } #[test] fn test_linearize() { let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); tester.extend_front([-1, -2]); assert_eq!(tester, [-2, -1, 1, 2, 3].into()); tester.linearize(); assert_eq!(tester, [-2, -1, 1, 2, 3].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2]); tester.extend_front([-1, -2, -3]); assert_eq!(tester, [-3, -2, -1, 1, 2].into()); tester.linearize(); assert_eq!(tester, [-3, -2, -1, 1, 2].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); tester.extend_front([-1, -2, -3]); assert_eq!(tester, [-3, -2, -1, 1, 2, 3].into()); tester.linearize(); assert_eq!(tester, [-3, -2, -1, 1, 2, 3].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); tester.extend_front([-1, -2]); assert_eq!(tester, [-2, -1, 1, 2, 3].into()); tester.linearize(); assert_eq!(tester, [-2, -1, 1, 2, 3].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2]); tester.extend_front([-1, -2, -3]); assert_eq!(tester, [-3, -2, -1, 1, 2].into()); tester.linearize(); assert_eq!(tester, [-3, -2, -1, 1, 2].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); tester.extend_front([-1, -2, -3]); assert_eq!(tester, [-3, -2, -1, 1, 2, 3].into()); tester.linearize(); assert_eq!(tester, [-3, -2, -1, 1, 2, 3].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3, 4, 5]); tester.extend_front([-1]); assert_eq!(tester, [-1, 1, 2, 3, 4, 5].into()); tester.linearize(); assert_eq!(tester, [-1, 1, 2, 3, 4, 5].into()); assert_eq!(tester.as_slices().1.len(), 0); let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1]); tester.extend_front([-1, -2, -3, -4, -5]); assert_eq!(tester, [-5, -4, -3, -2, -1, 1].into()); tester.linearize(); assert_eq!(tester, [-5, -4, -3, -2, -1, 1].into()); assert_eq!(tester.as_slices().1.len(), 0); } #[test] fn test_from_iterator_saturating() { assert_eq!( ArrayDeque::<_, 3, Saturating>::from_iter([1, 2, 3]), [1, 2, 3].into() ); assert_eq!( ArrayDeque::<_, 3, Saturating>::from_iter([1, 2, 3, 4, 5]), [1, 2, 3].into() ); } #[test] fn test_from_iterator_wrapping() { assert_eq!( ArrayDeque::<_, 3, Wrapping>::from_iter([1, 2, 3]), [1, 2, 3].into() ); assert_eq!( ArrayDeque::<_, 3, Wrapping>::from_iter([1, 2, 3, 4, 5]), [3, 4, 5].into() ); } #[test] fn test_extend_front_saturating() { let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_front([1, 2, 3]); assert_eq!(tester, [3, 2, 1].into()); tester.extend_front([4, 5]); assert_eq!(tester, [3, 2, 1].into()); } #[test] fn test_extend_back_saturating() { let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); assert_eq!(tester, [1, 2, 3].into()); tester.extend_back([4, 5]); assert_eq!(tester, [1, 2, 3].into()); } #[test] fn test_extend_front_wrapping() { let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_front([1, 2, 3]); assert_eq!(tester, [3, 2, 1].into()); tester.extend_front([4, 5]); assert_eq!(tester, [5, 4, 3].into()); } #[test] fn test_extend_back_wrapping() { let mut tester: ArrayDeque = ArrayDeque::new(); tester.extend_back([1, 2, 3]); assert_eq!(tester, [1, 2, 3].into()); tester.extend_back([4, 5]); assert_eq!(tester, [3, 4, 5].into()); } } arraydeque-0.5.1/src/range.rs000064400000000000000000000016430072674642500142560ustar 00000000000000use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; /// **RangeArgument** is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b` or `c..d`. pub trait RangeArgument { #[inline] /// Start index (inclusive) fn start(&self) -> Option { None } #[inline] /// End index (exclusive) fn end(&self) -> Option { None } } impl RangeArgument for RangeFull {} impl RangeArgument for RangeFrom { #[inline] fn start(&self) -> Option { Some(self.start) } } impl RangeArgument for RangeTo { #[inline] fn end(&self) -> Option { Some(self.end) } } impl RangeArgument for Range { #[inline] fn start(&self) -> Option { Some(self.start) } #[inline] fn end(&self) -> Option { Some(self.end) } }