#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
extern crate alloc;
use alloc::{
collections::TryReserveError,
vec::{self, Vec},
};
use core::{fmt, mem};
#[cfg(feature = "allocator_api")]
use alloc::alloc::{Allocator, Global};
#[cfg(feature = "allocator_api")]
#[derive(Clone)]
pub struct Partition<T, A: Allocator = Global> {
inner: Vec<T, A>,
partition: usize,
}
#[cfg(not(feature = "allocator_api"))]
#[derive(Clone)]
pub struct Partition<T> {
inner: Vec<T>,
partition: usize,
}
impl<T: fmt::Debug> fmt::Debug for Partition<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Partition")
.field("left", &self.left())
.field("right", &self.right())
.finish()
}
}
impl<T> Default for Partition<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "allocator_api")]
impl<T, A: Allocator> Partition<T, A> {
#[cfg(feature = "allocator_api")]
pub const fn new_in(alloc: A) -> Self {
Self {
inner: Vec::new_in(alloc),
partition: 0,
}
}
#[cfg(feature = "allocator_api")]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
Self {
inner: Vec::with_capacity_in(capacity, alloc),
partition: 0,
}
}
#[cfg(feature = "allocator_api")]
pub fn from_raw_parts(inner: Vec<T, A>, partition: usize) -> Self {
assert!(
partition <= inner.len(),
"partition index {partition} is out of bounds (vector len: {})",
inner.len()
);
unsafe { Self::from_raw_parts_unchecked(inner, partition) }
}
#[cfg(feature = "allocator_api")]
pub unsafe fn from_raw_parts_unchecked(inner: Vec<T, A>, partition: usize) -> Self {
Self { inner, partition }
}
}
impl<T> Partition<T> {
pub const fn new() -> Self {
Self {
inner: Vec::new(),
partition: 0,
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: Vec::with_capacity(capacity),
partition: 0,
}
}
pub fn to_raw_parts(self) -> (Vec<T>, usize) {
(self.inner, self.partition)
}
#[cfg(not(feature = "allocator_api"))]
pub fn from_raw_parts(inner: Vec<T>, partition: usize) -> Self {
assert!(
partition <= inner.len(),
"partition index {partition} is out of bounds (vector len: {})",
inner.len()
);
unsafe { Self::from_raw_parts_unchecked(inner, partition) }
}
#[cfg(not(feature = "allocator_api"))]
pub unsafe fn from_raw_parts_unchecked(inner: Vec<T>, partition: usize) -> Self {
Self { inner, partition }
}
pub unsafe fn set_partition(&mut self, new_partition: usize) {
assert!(
new_partition <= self.inner.len(),
"new partition index ({}) is out of bounds (vector len: {})",
new_partition,
self.inner.len()
);
self.partition = new_partition;
}
pub fn partitions(&self) -> (&[T], &[T]) {
(self.left(), self.right())
}
pub fn partitions_mut(&mut self) -> (&mut [T], &mut [T]) {
self.inner.split_at_mut(self.partition)
}
pub fn left(&self) -> &[T] {
unsafe { self.inner.get_unchecked(..self.partition) }
}
pub fn left_mut(&mut self) -> &mut [T] {
unsafe { self.inner.get_unchecked_mut(..self.partition) }
}
pub fn right(&self) -> &[T] {
unsafe { self.inner.get_unchecked(self.partition..) }
}
pub fn right_mut(&mut self) -> &mut [T] {
unsafe { self.inner.get_unchecked_mut(self.partition..) }
}
pub fn push_left(&mut self, mut value: T) {
if self.partition < self.inner.len() {
mem::swap(
unsafe { self.inner.get_unchecked_mut(self.partition) },
&mut value,
);
}
self.inner.push(value);
self.partition += 1;
}
pub fn pop_left(&mut self) -> Option<T> {
if self.partition > 0 {
self.partition -= 1;
let ret = self.inner.swap_remove(self.partition);
Some(ret)
} else {
None
}
}
pub fn swap_remove_left(&mut self, index: usize) -> T {
if index >= self.partition {
panic!(
"swap_remove_left: index {} out of bounds for left partition (length {})",
index, self.partition
);
}
if index == self.partition - 1 {
self.partition -= 1;
self.inner.swap_remove(index)
} else {
self.inner.swap(index, self.partition - 1);
self.partition -= 1;
self.inner.swap_remove(self.partition)
}
}
pub fn push_right(&mut self, value: T) {
self.inner.push(value);
}
pub fn pop_right(&mut self) -> Option<T> {
if self.partition < self.inner.len() {
self.inner.pop()
} else {
None
}
}
pub fn swap_remove_right(&mut self, index: usize) -> T {
let absolute_index = self.partition + index;
if index >= self.right().len() {
panic!(
"swap_remove_right: index {} out of bounds for right partition (length {})",
index,
self.right().len()
);
}
if absolute_index == self.inner.len() - 1 {
self.inner.pop().unwrap()
} else {
self.inner.swap_remove(absolute_index)
}
}
pub fn drain_left(&mut self) -> vec::Drain<'_, T> {
let old_partition = self.partition;
self.partition = 0;
self.inner.drain(0..old_partition)
}
pub fn drain_right(&mut self) -> vec::Drain<'_, T> {
self.inner.drain(self.partition..)
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional);
}
#[inline]
pub fn spare_capacity_mut(&mut self) -> &mut [mem::MaybeUninit<T>] {
self.inner.spare_capacity_mut()
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.capacity());
unsafe {
self.inner.set_len(new_len);
}
}
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit();
}
pub fn shrink_to(&mut self, min_capacity: usize) {
self.inner.shrink_to(min_capacity);
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve(additional)
}
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve_exact(additional)
}
pub fn append(&mut self, other: &mut Self) {
self.reserve(other.len());
let left_elements = other.drain_left();
for element in left_elements {
self.push_left(element);
}
let right_elements = other.drain_right();
for element in right_elements {
self.push_right(element);
}
debug_assert!(other.is_empty());
debug_assert_eq!(other.left().len(), 0);
debug_assert_eq!(other.right().len(), 0);
}
pub fn clear(&mut self) {
self.inner.clear();
self.partition = 0;
}
pub fn retain_left<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
if self.partition == 0 {
return; }
let mut keep_idx = 0;
for i in 0..self.partition {
if f(&self.inner[i]) {
if keep_idx != i {
self.inner.swap(keep_idx, i);
}
keep_idx += 1;
}
}
if keep_idx < self.partition {
let removed = self.partition - keep_idx;
for i in 0..self.right().len() {
let right_idx = self.partition + i;
let new_idx = keep_idx + i;
if right_idx != new_idx {
self.inner.swap(right_idx, new_idx);
}
}
self.partition = keep_idx;
self.inner.truncate(self.inner.len() - removed);
}
}
pub fn retain_right<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
if self.partition >= self.inner.len() {
return; }
let right_len = self.inner.len() - self.partition;
let mut indices_to_remove = Vec::with_capacity(right_len);
for i in 0..right_len {
let idx = self.partition + i;
if !f(&self.inner[idx]) {
indices_to_remove.push(idx);
}
}
for &idx in indices_to_remove.iter().rev() {
self.inner.swap_remove(idx);
}
}
}
impl<T: Copy> Partition<T> {
pub fn move_to_left(&mut self) -> Option<T> {
if let Some(moved) = self.inner.get(self.partition) {
self.partition += 1;
Some(*moved)
} else {
None
}
}
pub fn move_to_right(&mut self) -> Option<T> {
if self.partition > 0 {
self.partition -= 1;
Some(self.inner[self.partition])
} else {
None
}
}
pub fn drain_to_right(&mut self) -> DrainToRight<T> {
let elements = self.left().to_vec();
let old_partition = self.partition;
self.partition = 0;
let right_elements = self.inner.split_off(old_partition);
self.inner = right_elements;
for item in &elements {
self.push_right(*item);
}
DrainToRight { elements, index: 0 }
}
pub fn drain_to_left(&mut self) -> DrainToLeft<T> {
let elements = self.right().to_vec();
self.inner.truncate(self.partition);
for item in &elements {
self.push_left(*item);
}
DrainToLeft { elements, index: 0 }
}
}
pub struct DrainToRight<T: Copy> {
elements: Vec<T>,
index: usize,
}
impl<T: Copy> Iterator for DrainToRight<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.elements.len() {
let val = self.elements[self.index];
self.index += 1;
Some(val)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.elements.len() - self.index;
(remaining, Some(remaining))
}
}
pub struct DrainToLeft<T: Copy> {
elements: Vec<T>,
index: usize,
}
impl<T: Copy> Iterator for DrainToLeft<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.elements.len() {
let val = self.elements[self.index];
self.index += 1;
Some(val)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.elements.len() - self.index;
(remaining, Some(remaining))
}
}
#[cfg(test)]
mod tests;