#![no_std]
#![cfg_attr(
any(feature = "allocator_api", has_allocator_api),
feature(allocator_api)
)]
#![cfg_attr(feature = "dropck_eyepatch", feature(dropck_eyepatch))]
#![deny(unsafe_op_in_unsafe_fn)]
extern crate alloc;
#[cfg(feature = "allocator_api")]
use alloc::alloc as allocator;
#[cfg(not(feature = "allocator_api"))]
#[cfg(feature = "allocator-fallback")]
use allocator_fallback as allocator;
#[cfg(not(any_allocator_api))]
#[path = "alloc_fallback.rs"]
mod allocator;
use alloc::boxed::Box;
use allocator::{Allocator, Global};
use core::cmp::Ordering;
use core::fmt::{self, Debug, Formatter};
use core::iter::{ExactSizeIterator, FusedIterator};
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::ptr::NonNull;
#[cfg(btree_vec_debug)]
pub mod debug;
mod insert;
mod node;
mod remove;
mod verified_alloc;
use insert::{ItemInsertion, insert};
use node::{LeafRef, Mutable, Node, NodeRef};
use node::{PrefixCast, PrefixPtr, PrefixRef};
use remove::remove;
use verified_alloc::VerifiedAlloc;
pub struct BTreeVec<T, const B: usize = 12, A: Allocator = Global> {
root: Option<PrefixPtr<T, B>>,
size: usize,
alloc: VerifiedAlloc<A>,
phantom: PhantomData<Box<T>>,
}
unsafe impl<T, const B: usize, A> Send for BTreeVec<T, B, A>
where
T: Send,
A: Allocator,
{
}
unsafe impl<T, const B: usize, A> Sync for BTreeVec<T, B, A>
where
T: Sync,
A: Allocator,
{
}
fn leaf_for<T, const B: usize, R>(
mut root: PrefixRef<T, B, R>,
mut index: usize,
) -> (LeafRef<T, B, R>, usize) {
loop {
let node = match root.cast() {
PrefixCast::Leaf(node) => return (node, index),
PrefixCast::Internal(node) => node,
};
let last = node.length() - 1;
let mut sizes = node.sizes.iter().copied().take(last);
let index = sizes
.position(|size| {
if let Some(n) = index.checked_sub(size) {
index = n;
false
} else {
true
}
})
.unwrap_or(last);
root = node.into_child(index);
}
}
impl<T> BTreeVec<T> {
pub fn new() -> Self {
Self::create()
}
}
impl<T, A: Allocator> BTreeVec<T, 12, A> {
#[cfg_attr(
not(any(feature = "allocator_api", feature = "allocator-fallback")),
doc(hidden)
)]
pub fn new_in(alloc: A) -> Self {
Self::create_in(alloc)
}
}
impl<T, const B: usize> BTreeVec<T, B> {
pub fn create() -> Self {
Self::create_in(Global)
}
}
impl<T, const B: usize, A: Allocator> BTreeVec<T, B, A> {
#[cfg_attr(
not(any(feature = "allocator_api", feature = "allocator-fallback")),
doc(hidden)
)]
pub fn create_in(alloc: A) -> Self {
assert!(B >= 3);
let alloc = unsafe { VerifiedAlloc::new(alloc) };
Self {
root: None,
size: 0,
alloc,
phantom: PhantomData,
}
}
unsafe fn leaf_for(&self, index: usize) -> (LeafRef<T, B>, usize) {
leaf_for(unsafe { NodeRef::new(self.root.unwrap()) }, index)
}
unsafe fn leaf_for_mut(
&mut self,
index: usize,
) -> (LeafRef<T, B, Mutable>, usize) {
leaf_for(unsafe { NodeRef::new_mutable(self.root.unwrap()) }, index)
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn get(&self, index: usize) -> Option<&T> {
(index < self.size).then(|| {
let (leaf, index) = unsafe { self.leaf_for(index) };
&leaf.into_children()[index]
})
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
(index < self.size).then(|| {
let (leaf, index) = unsafe { self.leaf_for_mut(index) };
&mut leaf.into_children_mut()[index]
})
}
pub fn first(&self) -> Option<&T> {
self.get(0)
}
pub fn first_mut(&mut self) -> Option<&mut T> {
self.get_mut(0)
}
pub fn last(&self) -> Option<&T> {
self.size.checked_sub(1).and_then(|s| self.get(s))
}
pub fn last_mut(&mut self) -> Option<&mut T> {
self.size.checked_sub(1).and_then(move |s| self.get_mut(s))
}
pub fn insert(&mut self, index: usize, item: T) {
assert!(index <= self.size);
self.root.get_or_insert_with(|| {
LeafRef::alloc(&self.alloc).into_prefix().as_ptr()
});
let (leaf, index) = unsafe { self.leaf_for_mut(index) };
let root = insert(
ItemInsertion {
node: leaf,
index,
item,
root_size: self.size,
},
&self.alloc,
);
self.root = Some(root.as_ptr());
self.size += 1;
}
pub fn push(&mut self, item: T) {
self.insert(self.size, item);
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.size);
let (leaf, index) = unsafe { self.leaf_for_mut(index) };
let (root, item) = remove(leaf, index, &self.alloc);
self.root = Some(root.as_ptr());
self.size -= 1;
item
}
pub fn pop(&mut self) -> Option<T> {
self.size.checked_sub(1).map(|s| self.remove(s))
}
pub fn iter(&self) -> Iter<'_, T, B> {
Iter {
leaf: self.root.map(|_| unsafe { self.leaf_for(0) }.0),
index: 0,
remaining: self.len(),
phantom: PhantomData,
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, T, B> {
IterMut {
leaf: self.root.map(|_| unsafe { self.leaf_for_mut(0) }.0),
index: 0,
remaining: self.len(),
phantom: PhantomData,
}
}
}
impl<T, const B: usize, A> Default for BTreeVec<T, B, A>
where
A: Allocator + Default,
{
fn default() -> Self {
Self::create_in(A::default())
}
}
impl<T, const B: usize, A: Allocator> Index<usize> for BTreeVec<T, B, A> {
type Output = T;
fn index(&self, index: usize) -> &T {
self.get(index).unwrap()
}
}
impl<T, const B: usize, A: Allocator> IndexMut<usize> for BTreeVec<T, B, A> {
fn index_mut(&mut self, index: usize) -> &mut T {
self.get_mut(index).unwrap()
}
}
impl<T: Debug, const B: usize, A: Allocator> Debug for BTreeVec<T, B, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
#[cfg_attr(feature = "dropck_eyepatch", add_syntax::prepend(unsafe))]
impl<#[cfg_attr(feature = "dropck_eyepatch", may_dangle)] T, const B: usize, A>
Drop for BTreeVec<T, B, A>
where
A: Allocator,
{
fn drop(&mut self) {
if let Some(root) = self.root {
unsafe { NodeRef::new_mutable(root) }.destroy(&self.alloc);
}
}
}
impl<T, const B: usize, A> Clone for BTreeVec<T, B, A>
where
T: Clone,
A: Clone + Allocator,
{
fn clone(&self) -> Self {
let root = self.root.map(|root| {
unsafe { NodeRef::new(root) }
.clone_node(None, &self.alloc)
.0
.as_ptr()
});
Self {
root,
size: self.size,
alloc: self.alloc.clone(),
phantom: self.phantom,
}
}
}
impl<T, const B: usize, A1, A2> PartialEq<BTreeVec<T, B, A2>>
for BTreeVec<T, B, A1>
where
T: PartialEq,
A1: Allocator,
A2: Allocator,
{
fn eq(&self, other: &BTreeVec<T, B, A2>) -> bool {
self.iter().eq(other.iter())
}
}
impl<T: Eq, const B: usize, A: Allocator> Eq for BTreeVec<T, B, A> {}
impl<T, const B: usize, A1, A2> PartialOrd<BTreeVec<T, B, A2>>
for BTreeVec<T, B, A1>
where
T: PartialOrd,
A1: Allocator,
A2: Allocator,
{
fn partial_cmp(&self, other: &BTreeVec<T, B, A2>) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T, const B: usize, A> Ord for BTreeVec<T, B, A>
where
T: Ord,
A: Allocator,
{
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
fn nth<T, const B: usize, R>(
leaf: LeafRef<T, B, R>,
index: usize,
mut n: usize,
) -> Option<(LeafRef<T, B, R>, usize)> {
if let Some(new) = n.checked_sub(leaf.length() - index) {
n = new;
} else {
return Some((leaf, index + n));
};
let mut child_index = leaf.index();
let mut parent = leaf.into_parent().ok()?;
loop {
let sizes = parent.sizes[..parent.length()].iter().copied();
for (i, size) in sizes.enumerate().skip(child_index + 1) {
if let Some(new) = n.checked_sub(size) {
n = new;
} else {
return Some(leaf_for(parent.into_child(i), n));
}
}
child_index = parent.index();
parent = parent.into_parent().ok()?;
}
}
pub struct Iter<'a, T, const B: usize> {
leaf: Option<LeafRef<T, B>>,
index: usize,
remaining: usize,
phantom: PhantomData<&'a T>,
}
impl<'a, T, const B: usize> Iterator for Iter<'a, T, B> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let mut leaf = self.leaf?;
if self.index == leaf.length() {
self.leaf = self.leaf.take().unwrap().into_next().ok();
leaf = self.leaf?;
self.index = 0;
}
let index = self.index;
self.index += 1;
self.remaining -= 1;
Some(&leaf.into_children()[index])
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let remaining = core::mem::replace(&mut self.remaining, 0);
let (leaf, i) = nth(self.leaf.take()?, self.index, n)?;
self.index = i + 1;
self.remaining = remaining - n - 1;
Some(&self.leaf.insert(leaf).into_children()[i])
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, const B: usize> FusedIterator for Iter<'_, T, B> {}
impl<T, const B: usize> ExactSizeIterator for Iter<'_, T, B> {
fn len(&self) -> usize {
let (lower, upper) = self.size_hint();
debug_assert_eq!(Some(lower), upper);
lower
}
}
impl<T, const B: usize> Clone for Iter<'_, T, B> {
fn clone(&self) -> Self {
Self {
leaf: self.leaf,
index: self.index,
remaining: self.remaining,
phantom: self.phantom,
}
}
}
unsafe impl<T: Sync, const B: usize> Send for Iter<'_, T, B> {}
unsafe impl<T: Sync, const B: usize> Sync for Iter<'_, T, B> {}
impl<'a, T, const B: usize, A> IntoIterator for &'a BTreeVec<T, B, A>
where
A: Allocator,
{
type Item = &'a T;
type IntoIter = Iter<'a, T, B>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct IterMut<'a, T, const B: usize> {
leaf: Option<LeafRef<T, B, Mutable>>,
index: usize,
remaining: usize,
phantom: PhantomData<&'a mut T>,
}
impl<'a, T, const B: usize> Iterator for IterMut<'a, T, B> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let mut leaf = self.leaf.as_mut()?;
if self.index == leaf.length() {
self.leaf = self.leaf.take().unwrap().into_next().ok();
leaf = self.leaf.as_mut()?;
self.index = 0;
}
let index = self.index;
self.index += 1;
self.remaining -= 1;
let item = &mut leaf.children_mut()[index];
Some(unsafe { NonNull::from(item).as_mut() })
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let remaining = core::mem::replace(&mut self.remaining, 0);
let (leaf, i) = nth(self.leaf.take()?, self.index, n)?;
self.index = i + 1;
self.remaining = remaining - n - 1;
let item = &mut self.leaf.insert(leaf).children_mut()[i];
Some(unsafe { NonNull::from(item).as_mut() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, const B: usize> FusedIterator for IterMut<'_, T, B> {}
impl<T, const B: usize> ExactSizeIterator for IterMut<'_, T, B> {
fn len(&self) -> usize {
let (lower, upper) = self.size_hint();
debug_assert_eq!(Some(lower), upper);
lower
}
}
unsafe impl<T: Send, const B: usize> Send for IterMut<'_, T, B> {}
unsafe impl<T, const B: usize> Sync for IterMut<'_, T, B> {}
impl<'a, T, const B: usize, A> IntoIterator for &'a mut BTreeVec<T, B, A>
where
A: Allocator,
{
type Item = &'a mut T;
type IntoIter = IterMut<'a, T, B>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
pub struct IntoIter<T, const B: usize, A: Allocator = Global> {
leaf: Option<LeafRef<T, B, Mutable>>,
length: usize,
index: usize,
remaining: usize,
_tree: BTreeVec<T, B, A>,
}
impl<T, const B: usize, A: Allocator> Iterator for IntoIter<T, B, A> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let mut leaf = self.leaf.as_mut()?;
if self.index == self.length {
self.leaf = self.leaf.take().unwrap().into_next().ok();
leaf = self.leaf.as_mut()?;
self.index = 0;
self.length = leaf.length();
leaf.set_zero_length();
}
let index = self.index;
self.index += 1;
self.remaining -= 1;
Some(unsafe { leaf.take_raw_child(index).assume_init() })
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, const B: usize, A: Allocator> FusedIterator for IntoIter<T, B, A> {}
impl<T, const B: usize> ExactSizeIterator for IntoIter<T, B> {
fn len(&self) -> usize {
let (lower, upper) = self.size_hint();
debug_assert_eq!(Some(lower), upper);
lower
}
}
unsafe impl<T, const B: usize, A> Send for IntoIter<T, B, A>
where
T: Send,
A: Allocator,
{
}
unsafe impl<T, const B: usize, A: Allocator> Sync for IntoIter<T, B, A> {}
impl<T, const B: usize, A: Allocator> Drop for IntoIter<T, B, A> {
fn drop(&mut self) {
let mut leaf = if let Some(leaf) = self.leaf.take() {
leaf
} else {
return;
};
for i in self.index..self.length {
unsafe {
leaf.take_raw_child(i).assume_init();
}
}
}
}
impl<T, const B: usize, A: Allocator> IntoIterator for BTreeVec<T, B, A> {
type Item = T;
type IntoIter = IntoIter<T, B, A>;
fn into_iter(mut self) -> Self::IntoIter {
let leaf = self.root.map(|_| unsafe { self.leaf_for_mut(0) }.0);
IntoIter {
index: 0,
length: leaf.as_ref().map_or(0, |leaf| leaf.length()),
leaf,
remaining: self.len(),
_tree: self,
}
}
}