#![no_std]
extern crate alloc;
use core::{
iter::FusedIterator,
ops::{Bound, Deref, DerefMut, RangeBounds},
ptr::{self, drop_in_place},
};
use alloc::vec::Vec;
pub struct Entries<'a, T> {
read_head: usize,
write_head: usize,
read_tail: usize,
write_tail: usize,
vec: &'a mut Vec<T>,
}
impl<'a, T> Drop for Entries<'a, T> {
fn drop(&mut self) {
self.cleanup();
}
}
pub struct Entry<'a, 'b, T> {
entries: &'b mut Entries<'a, T>,
front: bool,
}
impl<'a, 'b, T> Entry<'a, 'b, T> {
fn shift_front(self) -> &'a mut T {
debug_assert!(self.front);
let e = self.entries;
let read_ptr = unsafe { e.vec.as_mut_ptr().add(e.read_head) };
let write_ptr = unsafe { e.vec.as_mut_ptr().add(e.write_head) };
if e.read_head != e.write_head {
unsafe {
ptr::copy_nonoverlapping(read_ptr, write_ptr, 1);
}
}
e.read_head += 1;
e.write_head += 1;
unsafe { &mut *write_ptr }
}
fn shift_back(self) -> &'a mut T {
debug_assert!(!self.front);
let e = self.entries;
e.read_tail -= 1;
e.write_tail -= 1;
let read_ptr = unsafe { e.vec.as_mut_ptr().add(e.read_tail) };
let write_ptr = unsafe { e.vec.as_mut_ptr().add(e.write_tail) };
if e.read_tail != e.write_tail {
unsafe {
ptr::copy_nonoverlapping(read_ptr, write_ptr, 1);
}
}
unsafe { &mut *write_ptr }
}
fn remove_front(self) -> T {
debug_assert!(self.front);
let e = self.entries;
let v = unsafe { ptr::read(e.vec.as_mut_ptr().add(e.read_head)) };
e.read_head += 1;
v
}
fn remove_back(mut self) -> T {
debug_assert!(!self.front);
let e = &mut self.entries;
e.read_tail -= 1;
let v = unsafe { ptr::read(e.vec.as_mut_ptr().add(e.read_tail)) };
v
}
#[inline]
pub fn shift(self) -> &'a mut T {
if self.front {
self.shift_front()
} else {
self.shift_back()
}
}
#[inline]
pub fn remove(self) -> T {
if self.front {
self.remove_front()
} else {
self.remove_back()
}
}
}
impl<'a, 'b, T> Deref for Entry<'a, 'b, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
let entries = &self.entries;
unsafe {
if self.front {
entries.vec.get_unchecked(entries.read_head)
} else {
entries.vec.get_unchecked(entries.read_tail - 1)
}
}
}
}
impl<'a, 'b, T> DerefMut for Entry<'a, 'b, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
let entries = &mut self.entries;
unsafe {
if self.front {
entries.vec.get_unchecked_mut(entries.read_head)
} else {
entries.vec.get_unchecked_mut(entries.read_tail - 1)
}
}
}
}
impl<'a, T> Entries<'a, T> {
fn start(start: Bound<usize>) -> usize {
match start {
Bound::Unbounded => 0,
Bound::Included(v) => v,
Bound::Excluded(v) => v + 1,
}
}
fn end(vec: &Vec<T>, end: Bound<usize>) -> usize {
match end {
Bound::Unbounded => vec.len(),
Bound::Included(v) => v + 1,
Bound::Excluded(v) => v,
}
}
fn new(vec: &'a mut Vec<T>, start: Bound<usize>, end: Bound<usize>) -> Self {
let start = Self::start(start);
let end = Self::end(vec, end);
Self {
read_head: start,
write_head: start,
read_tail: end,
write_tail: end,
vec,
}
}
fn cleanup(&mut self) {
let count_head = self.read_tail - self.read_head;
let count_tail = self.vec.len() - self.write_tail;
unsafe {
let src = self.vec.as_ptr().add(self.read_head);
let dst = self.vec.as_mut_ptr().add(self.write_head);
ptr::copy(src, dst, count_head);
let dst = dst.add(count_head);
let src = self.vec.as_ptr().add(self.write_tail);
ptr::copy(src, dst, count_tail);
let dst = dst.add(count_tail);
let len = dst.offset_from(self.vec.as_ptr()) as usize;
self.vec.set_len(len);
}
}
pub fn remaining(&mut self) -> &mut [T] {
unsafe { self.vec.get_unchecked_mut(self.read_head..self.read_tail) }
}
pub const fn remaining_len(&self) -> usize {
self.read_tail - self.read_head
}
pub const fn len_before(&self) -> usize {
self.write_head
}
pub fn len_after(&self) -> usize {
self.vec.len() - self.write_tail
}
pub fn clear(&mut self) {
while self.read_head != self.read_tail {
unsafe { drop_in_place(self.vec.as_mut_ptr().add(self.read_head)) }
self.read_head += 1;
}
}
#[inline]
pub fn front<'b>(&'b mut self) -> Option<Entry<'a, 'b, T>> {
if self.read_head == self.read_tail {
None
} else {
Some(Entry {
entries: self,
front: true,
})
}
}
#[inline]
pub fn back<'b>(&'b mut self) -> Option<Entry<'a, 'b, T>> {
if self.read_head == self.read_tail {
None
} else {
Some(Entry {
entries: self,
front: false,
})
}
}
#[inline]
pub fn shift(&mut self) -> Option<&'a mut T> {
self.front().map(Entry::shift_front)
}
#[inline]
pub fn shift_back(&mut self) -> Option<&'a mut T> {
self.back().map(Entry::shift_back)
}
#[inline]
pub fn remove(&mut self) -> Option<T> {
self.front().map(Entry::remove_front)
}
pub fn remove_back(&mut self) -> Option<T> {
self.back().map(Entry::remove_back)
}
pub fn try_insert_inside(&mut self, v: T) -> Result<&mut T, T> {
if self.read_head == self.write_head {
return Err(v);
}
self.read_head -= 1;
let v = unsafe {
let write_ptr = self.vec.as_mut_ptr().add(self.read_head);
ptr::write(write_ptr, v);
self.vec.get_unchecked_mut(self.read_head)
};
Ok(v)
}
pub fn try_insert_inside_back(&mut self, v: T) -> Result<&mut T, T> {
if self.read_tail == self.write_tail {
return Err(v);
}
let v = unsafe {
let write_ptr = self.vec.as_mut_ptr().add(self.read_tail);
ptr::write(write_ptr, v);
self.vec.get_unchecked_mut(self.read_tail)
};
self.read_tail += 1;
Ok(v)
}
pub fn try_insert_outside(&mut self, v: T) -> Result<&'a mut T, T> {
if self.read_head == self.write_head {
return Err(v);
}
let v = unsafe {
let write_ptr = self.vec.as_mut_ptr().add(self.write_head);
ptr::write(write_ptr, v);
&mut *write_ptr
};
self.write_head += 1;
Ok(v)
}
pub fn try_insert_outside_back(&mut self, v: T) -> Result<&'a mut T, T> {
if self.read_tail == self.write_tail {
return Err(v);
}
self.write_tail -= 1;
let v = unsafe {
let write_ptr = self.vec.as_mut_ptr().add(self.write_tail);
ptr::write(write_ptr, v);
&mut *write_ptr
};
Ok(v)
}
pub fn shift_iter<'b>(&'b mut self) -> ShiftIter<'a, 'b, T> {
ShiftIter { entries: self }
}
pub fn remove_iter<'b>(&'b mut self) -> RemoveIter<'a, 'b, T> {
RemoveIter { entries: self }
}
}
pub struct ShiftIter<'a, 'b, T> {
entries: &'b mut Entries<'a, T>,
}
impl<'a, 'b, T> Iterator for ShiftIter<'a, 'b, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.entries.shift()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'a, 'b, T> DoubleEndedIterator for ShiftIter<'a, 'b, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.entries.shift_back()
}
}
impl<'a, 'b, T> ExactSizeIterator for ShiftIter<'a, 'b, T> {
fn len(&self) -> usize {
self.entries.read_tail - self.entries.read_head
}
}
impl<'a, 'b, T> FusedIterator for ShiftIter<'a, 'b, T> {}
pub struct RemoveIter<'a, 'b, T> {
entries: &'b mut Entries<'a, T>,
}
impl<'a, 'b, T> Iterator for RemoveIter<'a, 'b, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.entries.remove()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'a, 'b, T> DoubleEndedIterator for RemoveIter<'a, 'b, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.entries.remove_back()
}
}
impl<'a, 'b, T> ExactSizeIterator for RemoveIter<'a, 'b, T> {
fn len(&self) -> usize {
self.entries.read_tail - self.entries.read_head
}
}
impl<'a, 'b, T> FusedIterator for RemoveIter<'a, 'b, T> {}
pub trait EntriesExt {
type T;
type Entries<'a, T: 'a>;
fn entries<'a, R, F, Ret>(&'a mut self, range: R, f: F) -> Ret
where
R: RangeBounds<usize>,
F: FnOnce(&mut Self::Entries<'a, Self::T>) -> Ret;
}
impl<T> EntriesExt for Vec<T> {
type T = T;
type Entries<'a, V: 'a> = Entries<'a, V>;
fn entries<'a, R, F, Ret>(&'a mut self, range: R, f: F) -> Ret
where
R: RangeBounds<usize>,
F: FnOnce(&mut Self::Entries<'a, Self::T>) -> Ret,
{
f(&mut Entries::new(
self,
range.start_bound().cloned(),
range.end_bound().cloned(),
))
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use super::*;
#[test]
fn nothing() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
});
assert_eq!(foo, [1, 2, 3, 4]);
}
#[test]
fn skip() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift(), Some(&mut 1));
assert_eq!(e.remaining(), [2, 3, 4]);
});
assert_eq!(foo, [1, 2, 3, 4]);
}
#[test]
fn skip_back() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift_back(), Some(&mut 4));
assert_eq!(e.remaining(), [1, 2, 3]);
});
assert_eq!(foo, [1, 2, 3, 4]);
}
#[test]
fn remove() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.remove(), Some(1));
assert_eq!(e.remaining(), [2, 3, 4]);
});
assert_eq!(foo, [2, 3, 4]);
}
#[test]
fn remove_back() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.remove_back(), Some(4));
assert_eq!(e.remaining(), [1, 2, 3]);
});
assert_eq!(foo, [1, 2, 3]);
}
#[test]
fn skip_remove() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift(), Some(&mut 1));
assert_eq!(e.remove(), Some(2));
});
assert_eq!(foo, [1, 3, 4]);
}
#[test]
fn skip_back_remove() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift_back(), Some(&mut 4));
assert_eq!(e.remove(), Some(1));
});
assert_eq!(foo, [2, 3, 4]);
}
#[test]
fn skip_remove_back() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift(), Some(&mut 1));
assert_eq!(e.remove_back(), Some(4));
});
assert_eq!(foo, [1, 2, 3]);
}
#[test]
fn skip_back_remove_back() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift_back(), Some(&mut 4));
assert_eq!(e.remove_back(), Some(3));
});
assert_eq!(foo, [1, 2, 4]);
}
#[test]
fn skip_iter() {
let mut foo = vec![1, 2, 3, 4];
foo.entries(.., |e| {
assert_eq!(e.remaining(), [1, 2, 3, 4]);
assert_eq!(e.shift_iter().next(), Some(&mut 1));
assert_eq!(e.remaining(), [2, 3, 4]);
});
assert_eq!(foo, [1, 2, 3, 4]);
}
}