use crate::{BackToFront, DropBehavior, FrontToBack, Middle, RebalanceBehavior, RebalanceStrategy};
use std::alloc::Layout;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
pub struct DeVec<T, DropOrder = FrontToBack, Rebalance = Middle>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
pub(crate) ptr: NonNull<T>,
pub(crate) start: usize,
pub(crate) cap: usize,
pub(crate) len: usize,
pub(crate) drop_order: DropOrder,
pub(crate) rebalance: Rebalance,
}
impl<T: Debug, DropOrder, Rebalance> Debug for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(self.as_slice(), f)
}
}
#[allow(dead_code)]
#[derive(Debug)]
pub(crate) struct DeVecDebug<T, DropOrder> {
pub(crate) ptr: NonNull<T>,
pub(crate) start: usize,
pub(crate) cap: usize,
pub(crate) len: usize,
pub(crate) drop_order: DropOrder,
}
impl<T, DropOrder, Rebalance> DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[allow(dead_code)]
pub(crate) fn debug(&self) -> DeVecDebug<T, DropOrder> {
DeVecDebug {
ptr: self.ptr,
start: self.start,
cap: self.cap,
len: self.len,
drop_order: self.drop_order,
}
}
}
unsafe impl<T: Send, DropOrder, Rebalance> Send for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
}
unsafe impl<T: Sync, DropOrder, Rebalance> Sync for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
}
impl<T> DeVec<T, FrontToBack> {
#[inline]
pub const fn new() -> Self {
let cap = if std::mem::size_of::<T>() == 0 {
usize::MAX
} else {
0
};
DeVec {
ptr: NonNull::dangling(),
start: 0,
len: 0,
cap,
drop_order: FrontToBack,
rebalance: Middle,
}
}
#[inline]
#[must_use = "This DeVec's drop order has been changed. Please make sure to use the new DeVec or drop it explicitly."]
pub fn as_back_to_front(self) -> DeVec<T, BackToFront> {
let this = std::mem::ManuallyDrop::new(self);
DeVec {
ptr: this.ptr,
start: this.start,
len: this.len,
cap: this.cap,
drop_order: BackToFront,
rebalance: this.rebalance,
}
}
#[inline]
#[must_use = "This DeVec's rebalance behavior has been changed. Please make sure to use the new DeVec or drop it explicitly."]
pub fn as_middle(self) -> DeVec<T, FrontToBack, Middle> {
let this = std::mem::ManuallyDrop::new(self);
DeVec {
ptr: this.ptr,
start: this.start,
len: this.len,
cap: this.cap,
drop_order: this.drop_order,
rebalance: Middle,
}
}
}
impl<T, DropOrder, Rebalance> DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
#[must_use]
pub fn new_with_drop_order<D>() -> DeVec<T, D>
where
D: DropBehavior + Default,
{
let cap = if std::mem::size_of::<T>() == 0 {
usize::MAX
} else {
0
};
DeVec {
ptr: NonNull::dangling(),
start: 0,
len: 0,
cap,
drop_order: Default::default(),
rebalance: Default::default(),
}
}
#[inline]
#[must_use]
pub fn new_with_rebalance_behavior<R>() -> DeVec<T, DropOrder, R>
where
R: RebalanceBehavior + Default,
{
let cap = if std::mem::size_of::<T>() == 0 {
usize::MAX
} else {
0
};
DeVec {
ptr: NonNull::dangling(),
start: 0,
len: 0,
cap,
drop_order: Default::default(),
rebalance: Default::default(),
}
}
#[inline]
#[must_use]
pub fn with_capacity(cap: usize) -> Self {
let (cap, ptr) = if std::mem::size_of::<T>() == 0 {
(usize::MAX, NonNull::dangling())
} else {
let layout = Layout::array::<T>(cap).unwrap();
let ptr = unsafe { std::alloc::alloc(layout) };
let ptr = match NonNull::new(ptr as *mut T) {
Some(p) => p,
None => std::alloc::handle_alloc_error(layout),
};
(cap, ptr)
};
let start = if cap == 0 { 0 } else { cap / 2 };
DeVec {
ptr,
start,
len: 0,
cap,
drop_order: Default::default(),
rebalance: Default::default(),
}
}
#[inline]
#[must_use]
pub fn with_capacity_and_drop_order<D>(cap: usize) -> DeVec<T, D>
where
D: DropBehavior + Default,
{
DeVec::<T, D>::with_capacity(cap)
}
#[inline]
#[must_use]
pub fn with_drop_order<D>(self) -> DeVec<T, D, Rebalance>
where
D: DropBehavior,
{
let this = std::mem::ManuallyDrop::new(self);
DeVec {
ptr: this.ptr,
start: this.start,
len: this.len,
cap: this.cap,
drop_order: Default::default(),
rebalance: this.rebalance,
}
}
#[inline]
#[must_use]
pub fn with_rebalance_behavior<R>(self) -> DeVec<T, DropOrder, R>
where
R: RebalanceBehavior,
{
let this = std::mem::ManuallyDrop::new(self);
DeVec {
ptr: this.ptr,
start: this.start,
len: this.len,
cap: this.cap,
drop_order: this.drop_order,
rebalance: Default::default(),
}
}
}
impl<T, DropOrder, Rebalance> DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
pub(crate) fn grow(&mut self) {
assert!(std::mem::size_of::<T>() != 0, "capacity overflow");
let (new_cap, new_start, new_layout) = if self.cap == 0 {
let starting_cap = 5;
let midpoint = starting_cap / 2;
(
starting_cap,
midpoint,
Layout::array::<T>(starting_cap).unwrap(),
)
} else {
let new_cap = 2 * self.cap;
let new_layout = Layout::array::<T>(new_cap).unwrap();
let nc = new_cap as f32;
let len = self.len as f32;
let new_start: usize =
match <Rebalance as crate::settings::seal_rebalance_behavior::Sealed>::BEHAVIOR {
RebalanceStrategy::StartAtFront => 0,
RebalanceStrategy::Middle => {
let midpoint = new_cap / 2;
midpoint - (self.len / 2)
}
RebalanceStrategy::FavorCrowdedSide => {
let back_space = self.space_back();
if back_space == 0 {
let new_offset = 0.2 * nc;
new_offset as usize
} else {
let new_end = 0.8 * nc;
let new_start = new_end - len;
new_start as usize
}
}
RebalanceStrategy::OnlyChangeCrowdedSide => {
let back_space = self.space_back();
if back_space == 0 {
self.start
} else {
new_cap - (self.len + back_space)
}
}
};
(new_cap, new_start, new_layout)
};
assert!(
new_layout.size() <= isize::MAX as usize,
"Allocation too large"
);
let new_ptr = if self.cap == 0 {
unsafe { std::alloc::alloc(new_layout) }
} else {
let old_layout = Layout::array::<T>(self.cap).unwrap();
let old_ptr = self.ptr.as_ptr() as *mut u8;
unsafe { std::alloc::realloc(old_ptr, old_layout, new_layout.size()) }
};
self.ptr = match NonNull::new(new_ptr as *mut T) {
Some(p) => p,
None => std::alloc::handle_alloc_error(new_layout),
};
if self.start != new_start {
unsafe {
let old_start_ptr = self.ptr.as_ptr().add(self.start);
let new_start_ptr = self.ptr.as_ptr().add(new_start);
std::ptr::copy(old_start_ptr, new_start_ptr, self.len);
}
self.start = new_start;
}
self.cap = new_cap;
}
#[inline]
pub fn push_back(&mut self, elem: T) {
if std::mem::size_of::<T>() == 0 {
self.len += 1;
return;
}
while self.len + self.start >= self.cap {
self.grow();
}
unsafe {
std::ptr::write(self.ptr.as_ptr().add(self.start + self.len), elem);
}
self.len += 1;
}
#[inline]
pub fn push_front(&mut self, elem: T) {
if std::mem::size_of::<T>() == 0 {
self.len += 1;
return;
}
while self.start == 0 {
self.grow();
}
unsafe {
if self.cap == 1 {
std::ptr::write(self.ptr.as_ptr(), elem);
} else {
std::ptr::write(self.ptr.as_ptr().add(self.start - 1), elem);
self.len += 1;
self.start -= 1;
}
}
}
#[inline]
pub fn pop_back(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
if std::mem::size_of::<T>() == 0 {
unsafe {
return Some(std::ptr::read(self.ptr.as_ptr()));
}
}
unsafe { Some(std::ptr::read(self.ptr.as_ptr().add(self.start + self.len))) }
}
}
#[inline]
pub fn pop_front(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
if std::mem::size_of::<T>() == 0 {
self.len -= 1;
unsafe {
return Some(std::ptr::read(self.ptr.as_ptr()));
}
}
let ret = unsafe {
Some(std::ptr::read(self.ptr.as_ptr().add(self.start)))
};
self.len -= 1;
self.start += 1;
ret
}
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn capacity(&self) -> usize {
self.cap
}
#[inline]
pub fn space_front(&self) -> usize {
self.start
}
#[inline]
pub fn space_back(&self) -> usize {
self.cap - (self.start + self.len)
}
#[inline]
pub fn starting_offset(&self) -> usize {
self.start
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn clear(&mut self) {
while (if DropOrder::IS_INVERTED {
self.pop_back()
} else {
self.pop_front()
})
.is_some()
{
}
}
#[inline]
pub fn clear_with_order(&mut self, drop_from_back: bool) {
while (if drop_from_back {
self.pop_back()
} else {
self.pop_front()
})
.is_some()
{
}
}
#[inline]
#[must_use]
pub fn as_slice(&self) -> &[T] {
self
}
#[inline]
#[must_use]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
#[inline]
pub fn reserve_back(&mut self, additional: usize) {
while self.cap - (self.start + self.len) < additional {
self.grow();
}
}
#[inline]
pub fn reserve_front(&mut self, additional: usize) {
while self.start < additional {
self.grow();
}
}
#[inline]
pub fn insert(&mut self, index: usize, elem: T) {
assert!(index <= self.len, "index out of bounds");
if index == self.len {
self.push_back(elem);
return;
}
if index == 0 {
self.push_front(elem);
return;
}
let shift_back = index >= (self.len / 2);
if shift_back {
if self.space_back() < 1 {
self.grow();
}
unsafe {
let ptr = self.ptr.as_ptr().add(self.start + index);
std::ptr::copy(ptr, ptr.add(1), self.len - index);
std::ptr::write(ptr, elem);
}
} else {
if self.space_front() < 1 {
self.grow();
}
unsafe {
let ptr = self.ptr.as_ptr().add(self.start);
std::ptr::copy(ptr, ptr.sub(1), index);
std::ptr::write(ptr, elem);
}
self.start -= 1;
}
self.len += 1;
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds");
if index == 0 {
return self.pop_front().unwrap();
}
if index == self.len - 1 {
return self.pop_back().unwrap();
}
unsafe {
let ptr = self.ptr.as_ptr().add(self.start + index);
let result = std::ptr::read(ptr);
std::ptr::copy(ptr.add(1), ptr, self.len - index - 1);
self.len -= 1;
result
}
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds");
if index == self.len - 1 {
return self.pop_back().unwrap();
}
let last_index = self.len - 1;
self.as_mut_slice().swap(index, last_index);
self.pop_back().unwrap()
}
#[inline]
pub fn smart_swap_remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds");
if index == 0 {
return self.pop_front().unwrap();
}
if index == self.len - 1 {
return self.pop_back().unwrap();
}
let front_space = self.space_front();
let back_space = self.space_back();
if front_space > back_space {
let last_index = self.len - 1;
self.as_mut_slice().swap(index, last_index);
self.pop_back().unwrap()
} else {
let first_index = 0;
self.as_mut_slice().swap(first_index, index);
self.pop_front().unwrap()
}
}
#[inline]
pub(crate) fn drain_inner(
&mut self,
range: std::ops::Range<usize>,
) -> Drain<'_, T, DropOrder, Rebalance> {
let start = range.start;
let end = range.end;
assert!(start <= end, "start must be less than or equal to end");
assert!(
end <= self.len,
"end must be less than or equal to the length of the DeVec"
);
let devec_start = self.start + start;
let devec_target = self.start + end;
Drain {
devec: self,
start: devec_start,
current: devec_start,
target: devec_target,
}
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, DropOrder, Rebalance>
where
R: std::ops::RangeBounds<usize>,
{
let start = match range.start_bound() {
std::ops::Bound::Included(&s) => s,
std::ops::Bound::Excluded(&s) => s + 1,
std::ops::Bound::Unbounded => 0,
};
let end = match range.end_bound() {
std::ops::Bound::Included(&e) => e + 1,
std::ops::Bound::Excluded(&e) => e,
std::ops::Bound::Unbounded => self.len,
};
self.drain_inner(start..end)
}
#[inline]
pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<T, DropOrder, F, Rebalance>
where
F: FnMut(usize, &mut T) -> bool,
{
self.reserve_front(1);
ExtractIf {
f,
buffer_write_start: 0,
devec: self,
current_index: 0,
items_removed: 0,
}
}
#[inline]
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let extractor = self.extract_if(|_, elem| !f(elem));
drop(extractor)
}
#[inline]
#[must_use]
pub fn into_raw_parts(self) -> (*mut T, usize, usize, usize) {
let ptr = self.ptr.as_ptr();
let start = self.start;
let len = self.len;
let cap = self.cap;
std::mem::forget(self);
(ptr, start, len, cap)
}
#[inline]
#[must_use]
pub unsafe fn from_raw_parts(ptr: *mut T, start: usize, len: usize, cap: usize) -> Self {
DeVec {
ptr: NonNull::new(ptr).unwrap(),
start,
len,
cap,
drop_order: Default::default(),
rebalance: Default::default(),
}
}
#[inline]
pub fn copy_from_slice(&mut self, other: &[T])
where
T: Copy,
{
self.reserve_back(other.len());
unsafe {
std::ptr::copy_nonoverlapping(
other.as_ptr(),
self.ptr.as_ptr().add(self.start + self.len),
other.len(),
);
}
self.len += other.len();
}
#[inline]
pub fn extend_from_slice(&mut self, other: &[T])
where
T: Clone,
{
self.reserve_back(other.len());
for elem in other {
self.push_back(elem.clone());
}
}
#[inline]
pub fn rebalance(&mut self) {
let midpoint = self.len / 2;
let new_start = self.cap / 2 - midpoint;
if self.start == new_start {
return;
}
unsafe {
std::ptr::copy(
self.ptr.as_ptr().add(self.start),
self.ptr.as_ptr().add(new_start),
self.len,
);
}
self.start = new_start;
}
#[inline]
#[must_use]
pub fn leak<'a>(self) -> &'a mut [T] {
unsafe {
let slice = std::slice::from_raw_parts_mut(self.ptr.as_ptr().add(self.start), self.len);
std::mem::forget(self);
slice
}
}
#[inline]
#[must_use]
pub fn spare_capacity_mut(
&mut self,
) -> (
&mut [std::mem::MaybeUninit<T>],
&mut [std::mem::MaybeUninit<T>],
) {
let start = self.start;
let end = self.start + self.len;
let spare_front = unsafe {
std::slice::from_raw_parts_mut(
self.ptr.as_ptr() as *mut std::mem::MaybeUninit<T>,
start,
)
};
let spare_back = unsafe {
std::slice::from_raw_parts_mut(
self.ptr.as_ptr().add(end) as *mut std::mem::MaybeUninit<T>,
self.cap - end,
)
};
(spare_front, spare_back)
}
}
impl<T, DropOrder: DropBehavior, Rebalance> Default for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn default() -> Self {
let cap = if std::mem::size_of::<T>() == 0 {
usize::MAX
} else {
0
};
DeVec {
ptr: NonNull::dangling(),
start: 0,
len: 0,
cap,
drop_order: DropOrder::default(),
rebalance: Rebalance::default(),
}
}
}
pub struct IntoIter<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
devec: DeVec<T, DropOrder, Rebalance>,
}
impl<T, DropOrder, Rebalance> IntoIterator for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Item = T;
type IntoIter = IntoIter<T, DropOrder, Rebalance>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter { devec: self }
}
}
impl<'a, T, DropOrder, Rebalance> IntoIterator for &'a DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<'a, T, DropOrder, Rebalance> IntoIterator for &'a mut DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Item = &'a mut T;
type IntoIter = std::slice::IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_mut_slice().iter_mut()
}
}
impl<T, DropOrder, Rebalance> Iterator for IntoIter<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.devec.is_empty() {
None
} else {
self.devec.pop_front()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.devec.len(), Some(self.devec.len()))
}
}
impl<T, DropOrder, Rebalance> std::iter::FusedIterator for IntoIter<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
}
impl<T, DropOrder, Rebalance> ExactSizeIterator for IntoIter<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn len(&self) -> usize {
self.devec.len()
}
}
impl<T, DropOrder, Rebalance> DoubleEndedIterator for IntoIter<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.devec.pop_back()
}
}
impl<T, DropOrder, Rebalance> Drop for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn drop(&mut self) {
if std::mem::size_of::<T>() == 0 {
return;
}
if self.cap != 0 {
while (if DropOrder::IS_INVERTED {
self.pop_back()
} else {
self.pop_front()
})
.is_some()
{}
let layout = Layout::array::<T>(self.cap).unwrap();
unsafe {
std::alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
}
}
}
}
impl<T, DropOrder, Rebalance> Clone for DeVec<T, DropOrder, Rebalance>
where
T: Clone,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn clone(&self) -> Self {
let mut new: DeVec<T, DropOrder, Rebalance> = DeVec::with_capacity(self.cap);
new.start = (new.cap / 2).saturating_sub(new.len / 2);
new.len = 0;
for (i, elem) in self.iter().enumerate() {
let elem = elem.clone();
unsafe {
new.ptr.as_ptr().add(new.start + i).write(elem);
}
}
new.len = self.len;
new
}
}
impl<T, DropOrder, Rebalance> Deref for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().add(self.start), self.len) }
}
}
impl<T, DropOrder, Rebalance> DerefMut for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr().add(self.start), self.len) }
}
}
impl<T, DropOrder: DropBehavior, Rebalance, R> std::ops::Index<R> for DeVec<T, DropOrder, Rebalance>
where
R: std::slice::SliceIndex<[T]>,
Rebalance: RebalanceBehavior,
{
type Output = <[T] as std::ops::Index<R>>::Output;
#[inline]
fn index(&self, index: R) -> &Self::Output {
self.as_slice().index(index)
}
}
impl<T, DropOrder, Rebalance> AsRef<[T]> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn as_ref(&self) -> &[T] {
self
}
}
impl<T, DropOrder, Rebalance> AsMut<[T]> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self
}
}
impl<T, DropOrder, Rebalance> std::borrow::Borrow<[T]> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn borrow(&self) -> &[T] {
self
}
}
impl<T, DropOrder, Rebalance> std::borrow::BorrowMut<[T]> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn borrow_mut(&mut self) -> &mut [T] {
self
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
#[doc(hidden)]
pub(crate) mod serde_impls {
use super::*;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
impl<T, DropOrder, Rebalance> Serialize for DeVec<T, DropOrder, Rebalance>
where
T: Serialize,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.as_slice().serialize(serializer)
}
}
impl<'src, T, DropOrder, Rebalance> Deserialize<'src> for DeVec<T, DropOrder, Rebalance>
where
T: Deserialize<'src>,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn deserialize<D: Deserializer<'src>>(deserializer: D) -> Result<Self, D::Error> {
let vec = <Vec<T> as Deserialize<'src>>::deserialize(deserializer)?;
Ok(DeVec::from(vec).with_drop_order().with_rebalance_behavior())
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json;
#[test]
fn test_serde() {
let input_sequences = [vec![0, 1, 2, 3, 4, 5, 6], vec![3, 2, 1], vec![]];
for sequence in input_sequences.iter() {
let devec = DeVec::from(sequence.clone());
let serialized = serde_json::to_string(&devec).unwrap();
let deserialized: DeVec<i32> = serde_json::from_str(&serialized).unwrap();
assert_eq!(devec, deserialized);
}
}
}
}
pub struct Drain<'a, T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
pub(crate) devec: &'a mut DeVec<T, DropOrder, Rebalance>,
pub(crate) start: usize,
pub(crate) current: usize,
pub(crate) target: usize,
}
impl<'a, T, DropOrder, Rebalance> Iterator for Drain<'a, T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.target {
None
} else {
let val = unsafe { Some(std::ptr::read(self.devec.ptr.as_ptr().add(self.current))) };
self.current += 1;
val
}
}
}
impl<'a, T, DropOrder, Rebalance> Drop for Drain<'a, T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn drop(&mut self) {
for _ in self.by_ref() {}
if self.devec.len + self.devec.start <= self.target {
self.devec.len -= self.target - self.start;
return;
}
let start_of_remaining_elements = self.target;
let where_they_need_to_go = self.start;
let num_items_after_end = (self.devec.start + self.devec.len) - self.target;
unsafe {
std::ptr::copy(
self.devec.ptr.as_ptr().add(start_of_remaining_elements),
self.devec.ptr.as_ptr().add(where_they_need_to_go),
num_items_after_end,
);
}
self.devec.len -= self.target - self.start;
}
}
pub struct ExtractIf<'a, T, D, F, R>
where
D: DropBehavior,
F: FnMut(usize, &mut T) -> bool,
R: RebalanceBehavior,
{
f: F,
devec: &'a mut DeVec<T, D, R>,
current_index: usize,
buffer_write_start: usize,
items_removed: usize,
}
impl<'a, T, D, F, R> Iterator for ExtractIf<'a, T, D, F, R>
where
D: DropBehavior,
F: FnMut(usize, &mut T) -> bool,
R: RebalanceBehavior,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while self.current_index < self.devec.len {
let current_index = self.current_index;
let current_ptr = unsafe {
self.devec
.ptr
.as_ptr()
.add(self.devec.start + current_index)
};
let mut result = unsafe { std::ptr::read(current_ptr) };
#[cfg(test)]
{
println!(
"starting iteration with current index {current_index} and buffer write start {}",
self.buffer_write_start
);
}
let should_extract = (self.f)(current_index, &mut result);
if should_extract {
#[cfg(test)]
{
println!("extracting");
}
self.current_index += 1;
self.items_removed += 1;
return Some(result);
} else {
#[cfg(test)]
{
println!(
"moving element {} to position {}",
self.current_index, self.buffer_write_start
);
}
let front_of_buffer_ptr = unsafe {
self.devec
.ptr
.as_ptr()
.add(self.devec.start + self.buffer_write_start)
};
unsafe {
std::ptr::write(front_of_buffer_ptr, result);
}
self.buffer_write_start += 1;
self.current_index += 1;
}
}
let old_len = self.devec.len;
let new_len = old_len - self.items_removed;
self.devec.len = new_len;
self.items_removed = 0;
None
}
}
impl<'a, T, D, F, R> Drop for ExtractIf<'a, T, D, F, R>
where
D: DropBehavior,
R: RebalanceBehavior,
F: FnMut(usize, &mut T) -> bool,
{
#[inline]
fn drop(&mut self) {
for _ in self.by_ref() {}
}
}
impl<T, DropOrder, Rebalance> FromIterator<T> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
DeVec::from(iter.into_iter().collect::<Vec<T>>())
.with_drop_order()
.with_rebalance_behavior()
}
}
impl<T, DropOrder, Rebalance> Extend<T> for DeVec<T, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.push_back(item);
}
}
}
impl<T> From<Vec<T>> for DeVec<T> {
#[inline]
fn from(vec: Vec<T>) -> Self {
let (ptr, len, cap) = (vec.as_ptr(), vec.len(), vec.capacity());
std::mem::forget(vec);
DeVec {
ptr: NonNull::new(ptr as *mut T).unwrap(),
start: 0,
len,
cap,
drop_order: Default::default(),
rebalance: Default::default(),
}
}
}
impl<T, const N: usize> From<[T; N]> for DeVec<T> {
#[inline]
fn from(array: [T; N]) -> Self {
From::from(Vec::from(array))
}
}
#[cfg(test)]
mod devec_test_from {
use super::*;
#[test]
fn test_from_vec() {
let vec = vec![1, 2, 3, 4, 5];
let devec: DeVec<i32> = DeVec::from(vec);
assert_eq!(devec.len(), 5);
assert_eq!(devec.capacity(), 5);
assert_eq!(devec[0], 1);
assert_eq!(devec[1], 2);
assert_eq!(devec[2], 3);
assert_eq!(devec[3], 4);
assert_eq!(devec[4], 5);
}
#[test]
fn test_from_vec2() {
let vec = vec![2, 3, 5];
let mut devec: DeVec<i32> = DeVec::from(vec);
assert_eq!(devec.len(), 3);
assert_eq!((&*devec), &[2, 3, 5][..]);
devec.pop_back();
devec.push_front(1);
devec.push_back(6);
assert_eq!(devec.len(), 4);
assert_eq!(&devec, &[1, 2, 3, 6][..]);
}
}
impl<T, DropOrder, Rebalance> PartialEq for DeVec<T, DropOrder, Rebalance>
where
T: PartialEq,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().eq(other.iter())
}
}
impl<T, DropOrder, Rebalance> PartialEq<[T]> for DeVec<T, DropOrder, Rebalance>
where
T: PartialEq,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn eq(&self, other: &[T]) -> bool {
self.len() == other.len() && self.iter().eq(other.iter())
}
}
impl<T, DropOrder, Rebalance> Eq for DeVec<T, DropOrder, Rebalance>
where
T: Eq,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
}
impl<T, DropOrder, Rebalance> PartialOrd for DeVec<T, DropOrder, Rebalance>
where
T: PartialOrd,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T, DropOrder, Rebalance> PartialOrd<[T]> for DeVec<T, DropOrder, Rebalance>
where
T: PartialOrd,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<std::cmp::Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T, DropOrder, Rebalance> Ord for DeVec<T, DropOrder, Rebalance>
where
T: Ord,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.iter().cmp(other.iter())
}
}
impl<T, DropOrder, Rebalance> std::hash::Hash for DeVec<T, DropOrder, Rebalance>
where
T: std::hash::Hash,
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl<DropOrder, Rebalance> std::io::Write for DeVec<u8, DropOrder, Rebalance>
where
DropOrder: DropBehavior,
Rebalance: RebalanceBehavior,
{
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.copy_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[macro_export]
macro_rules! devec {
() => {
$crate::devec::DeVec::<_>::new()
};
($elem:expr; $n:expr) => {
$crate::devec::DeVec::<_>::from(std::iter::repeat($elem).take($n))
};
($($x:expr),+ $(,)?) => {
$crate::devec::DeVec::<_>::from(vec![$($x),+])
};
}
#[cfg(test)]
mod devec_tests {
use super::*;
#[test]
pub fn push_back_order() {
let mut devec: DeVec<i32> = DeVec::new();
devec.push_back(1);
devec.push_back(2);
devec.push_back(3);
assert_eq!(&*devec, &[1, 2, 3]);
}
#[test]
pub fn pop_back_order() {
let mut devec = DeVec::new();
devec.push_back(1);
devec.push_back(2);
devec.push_back(3);
assert_eq!(devec.pop_back(), Some(3));
assert_eq!(devec.pop_back(), Some(2));
assert_eq!(devec.pop_back(), Some(1));
assert_eq!(devec.pop_back(), None);
}
#[test]
pub fn push_front_order() {
let mut devec = DeVec::new();
devec.push_front(1);
devec.push_front(2);
devec.push_front(3);
assert_eq!(&*devec, &[3, 2, 1]);
}
#[test]
pub fn pop_front_order() {
let mut devec = DeVec::new();
devec.push_front(1i32);
devec.push_front(2);
devec.push_front(3);
assert_eq!(devec.pop_front(), Some(3));
assert_eq!(devec.pop_front(), Some(2));
assert_eq!(devec.pop_front(), Some(1));
assert_eq!(devec.pop_front(), None);
}
#[test]
pub fn test_interleave_push_order() {
let mut devec = DeVec::new();
devec.push_front(1i32);
devec.push_back(2);
devec.push_front(3);
devec.push_back(4);
devec.push_front(5);
devec.push_back(6);
assert_eq!(&*devec, &[5, 3, 1, 2, 4, 6]);
}
#[test]
pub fn test_interleave_pop_order() {
let mut devec = DeVec::new();
devec.push_front(1i32);
devec.push_back(2);
devec.push_front(3);
devec.push_back(4);
devec.push_front(5);
devec.push_back(6);
assert_eq!(devec.pop_front(), Some(5));
assert_eq!(devec.pop_back(), Some(6));
assert_eq!(devec.pop_front(), Some(3));
assert_eq!(devec.pop_front(), Some(1));
assert_eq!(devec.pop_back(), Some(4));
assert_eq!(devec.pop_back(), Some(2));
assert_eq!(devec.pop_front(), None);
assert_eq!(devec.pop_back(), None);
}
#[test]
pub fn test_zst_operations() {
let mut devec = DeVec::<()>::new();
devec.push_back(());
devec.push_front(());
devec.push_back(());
devec.push_front(());
devec.push_back(());
devec.push_back(());
devec.push_front(());
devec.push_back(());
devec.push_front(());
let target_len = 9;
assert_eq!(devec.len(), target_len);
assert_eq!(devec.pop_front(), Some(()));
assert_eq!(devec.len(), target_len - 1);
}
#[test]
pub fn test_collect() {
let devec: DeVec<i32> = (0..10).collect();
assert_eq!(&*devec, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
pub fn test_extract_if() {
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let extracted: Vec<i32> = devec.extract_if(|_, x| *x % 2 == 1).collect();
assert_eq!(extracted, vec![1, 3, 5, 7, 9]);
assert_eq!(&*devec, &[0, 2, 4, 6, 8]);
}
#[test]
pub fn test_extract_if2() {
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let mut is_first = true;
let extracted: Vec<i32> = devec
.extract_if(|_, _x| {
if is_first {
is_first = false;
true
} else {
false
}
})
.collect();
assert_eq!(extracted, vec![0]);
assert_eq!(&*devec, &[1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
pub fn test_extract_if3() {
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let index_range = 0..3;
let extracted: Vec<i32> = devec.extract_if(|i, _| index_range.contains(&i)).collect();
assert_eq!(&*extracted, &[0, 1, 2]);
assert_eq!(&*devec, &[3, 4, 5, 6, 7, 8, 9]);
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let keep_everything_before = 6;
let extracted: Vec<i32> = devec
.extract_if(|i, _| i >= keep_everything_before)
.collect();
assert_eq!(&*extracted, &[6, 7, 8, 9]);
assert_eq!(&*devec, &[0, 1, 2, 3, 4, 5]);
let empty_i32_slice: &[i32] = &[];
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let keep_everything_before = 42;
let extracted: Vec<i32> = devec
.extract_if(|i, _| i >= keep_everything_before)
.collect();
assert_eq!(&*extracted, empty_i32_slice);
assert_eq!(&*devec, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let mut devec: DeVec<_> = DeVec::from_iter(0..10);
let keep_everything_before = 0;
let extracted: Vec<i32> = devec
.extract_if(|i, _| i >= keep_everything_before)
.collect();
assert_eq!(&*extracted, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(&*devec, empty_i32_slice);
}
}