#![allow(dead_code)]
use allocated::DropGuard;
use allocated::FromIteratorIn;
use core::borrow::Borrow;
use core::mem::ManuallyDrop;
use core::ops::Add;
use core::ops::Mul;
use core::ptr::NonNull;
extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use allocator_api2::alloc::Allocator;
use generic_array::ArrayLength;
use typenum::Prod;
use typenum::Sum;
use typenum::U1;
use typenum::U2;
use typenum::U6;
use allocated::AllocResult;
use allocated::DropGuardResult;
use allocated::DropIn;
use allocated::IntoIteratorIn;
use allocated::RecursiveDropIn;
mod entry;
mod node;
mod wrapper;
pub use entry::{Entry, OccupiedEntry, VacantEntry};
use node::{
ChildPtr, IntoIter as NodeIntoIter, Iter as NodeIter, LeafNode, MutNodeRef, Node, NodeEntry,
NodeRef, NodeRefT, OccupiedNodeEntry,
};
pub use wrapper::CompressedBTreeMap;
pub struct AllocatedBTreeMap<K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength = U6>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
root: Option<ManuallyDrop<Node<K, V, B>>>,
n: usize,
}
impl<K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength> AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
fn root_node_ref(&self) -> NodeRef<'_, K, V, B> {
self.root.as_ref().unwrap().as_ref()
}
fn root_mut_node_ref(&mut self) -> MutNodeRef<'_, K, V, B> {
self.root.as_mut().unwrap().as_mut()
}
}
impl<K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength> AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
pub fn new_in<A: Allocator>(alloc: &A) -> DropGuardResult<Self, &A> {
Ok(LeafNode::new_in(alloc).map(|root| AllocatedBTreeMap {
root: Some(ManuallyDrop::new(Node::Leaf(root))),
n: 0,
}))
}
pub fn is_empty(&self) -> bool {
self.n == 0
}
pub fn len(&self) -> usize {
self.n
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q> + core::cmp::PartialOrd + core::fmt::Debug,
Q: core::cmp::PartialOrd + core::fmt::Debug,
{
let root = self.root_node_ref();
match root.ref_entry(key, vec![]) {
NodeEntry::Vacant(_) => false,
NodeEntry::Occupied(_) => true,
}
}
pub unsafe fn insert_in<A: Allocator>(
&mut self,
alloc: &A,
key: K,
value: V,
) -> AllocResult<Option<V>> {
let entry = unsafe { self.entry_in(alloc, key) };
entry.insert(value)
}
pub unsafe fn clear_in<A: Allocator>(&mut self, alloc: &A) -> AllocResult<()> {
if let Some(mut r) = self.root.take() {
unsafe { r.drop_in(alloc) };
}
self.n = 0;
self.root = Some(LeafNode::new_in(alloc).map(|n| Node::Leaf(n)).into_inner());
Ok(())
}
pub fn get<'s, Q>(&'s self, key: &Q) -> Option<&'s V>
where
K: Borrow<Q> + core::cmp::PartialOrd,
Q: core::cmp::PartialOrd + core::fmt::Debug,
{
let root = self.root_node_ref();
match root.ref_entry(key, vec![]) {
NodeEntry::Vacant(_) => None,
NodeEntry::Occupied(o) => Some(o.into_value()),
}
}
pub fn get_key_value<'s, Q>(&'s self, key: &'s Q) -> Option<(&'s K, &'s V)>
where
K: Borrow<Q> + core::cmp::PartialOrd,
Q: core::cmp::PartialOrd + core::fmt::Debug,
{
let root = self.root_node_ref();
match root.ref_entry(key, vec![]) {
NodeEntry::Vacant(_) => None,
NodeEntry::Occupied(o) => Some(o.into_key_value()),
}
}
pub fn get_mut<'s, Q>(&'s mut self, key: &'s Q) -> Option<&'s mut V>
where
K: Borrow<Q> + core::cmp::PartialOrd,
Q: core::cmp::PartialOrd + core::fmt::Debug,
{
let root = self.root_mut_node_ref();
match root.ref_entry(key, vec![]) {
NodeEntry::Vacant(_) => None,
NodeEntry::Occupied(o) => Some(o.into_mut()),
}
}
pub fn iter(&self) -> Iter<'_, K, V, B> {
let mut stack = Vec::new();
if self.n > 0 {
stack.push((ChildPtr::from_node_ref(self.root_node_ref()), 0));
}
Iter {
inner: NodeIter::<K, V, B, NodeRef<K, V, B>>::new(stack),
}
}
pub fn keys(&self) -> Keys<'_, K, V, B> {
let mut stack = Vec::new();
if self.n > 0 {
stack.push((ChildPtr::from_node_ref(self.root_node_ref()), 0));
}
Keys {
inner: NodeIter::<K, V, B, NodeRef<K, V, B>>::new(stack),
}
}
unsafe fn into_keys_in<A: Allocator>(self, alloc: &A) -> IntoKeys<'_, K, V, B, A> {
IntoKeys {
inner: NodeIntoIter::new(alloc, ManuallyDrop::into_inner(self.root.unwrap())),
}
}
pub fn values(&self) -> Values<'_, K, V, B> {
let mut stack = Vec::new();
if self.n > 0 {
stack.push((ChildPtr::from_node_ref(self.root_node_ref()), 0));
}
Values {
inner: NodeIter::<K, V, B, NodeRef<K, V, B>>::new(stack),
}
}
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V, B> {
let mut stack = Vec::new();
if self.n > 0 {
stack.push((
ChildPtr::from_mut_node_ref(&mut self.root_mut_node_ref()),
0,
));
}
ValuesMut {
inner: NodeIter::<K, V, B, MutNodeRef<K, V, B>>::new(stack),
}
}
unsafe fn into_values_in<A: Allocator>(self, alloc: &A) -> IntoValues<'_, K, V, B, A> {
IntoValues {
inner: NodeIntoIter::new(alloc, ManuallyDrop::into_inner(self.root.unwrap())),
}
}
pub unsafe fn entry_in<'a, 's, A: Allocator>(
&'s mut self,
alloc: &'a A,
key: K,
) -> Entry<'a, 's, A, K, V, B> {
let map: NonNull<AllocatedBTreeMap<K, V, B>> = NonNull::from_mut(self);
let node_ref: MutNodeRef<'s, K, V, B> = self.root_mut_node_ref();
let inner_entry: NodeEntry<'s, K, K, V, B, MutNodeRef<'s, K, V, B>> =
unsafe { node_ref.entry_in(key, vec![]) };
Entry::new(alloc, inner_entry, map)
}
pub unsafe fn first_entry_in<'a, 's, A: Allocator>(
&'s mut self,
alloc: &'a A,
) -> Option<OccupiedEntry<'a, 's, A, K, V, B>> {
if self.n == 0 {
return None;
}
let map = NonNull::new(self)?;
let root = self.root_mut_node_ref();
let inner_entry: OccupiedNodeEntry<'s, K, V, B, MutNodeRef<'s, K, V, B>> =
root.first_entry_in(vec![]);
unsafe { Some(OccupiedEntry::new(alloc, inner_entry, map)) }
}
pub fn first_key_value<'s>(&'s self) -> Option<(&'s K, &'s V)> {
if self.n == 0 {
return None;
}
let root = self.root_node_ref();
let inner_entry: OccupiedNodeEntry<'s, K, V, B, NodeRef<'s, K, V, B>> =
root.first_entry_in(vec![]);
Some(inner_entry.into_key_value())
}
pub unsafe fn last_entry_in<'a, 's, A: Allocator>(
&'s mut self,
alloc: &'a A,
) -> Option<OccupiedEntry<'a, 's, A, K, V, B>> {
if self.n == 0 {
return None;
}
let map = NonNull::new(self)?;
let root = self.root_mut_node_ref();
let inner_entry: OccupiedNodeEntry<'s, K, V, B, MutNodeRef<'s, K, V, B>> =
root.last_entry_in(vec![]);
unsafe { Some(OccupiedEntry::new(alloc, inner_entry, map)) }
}
pub fn last_key_value<'s>(&'s self) -> Option<(&'s K, &'s V)> {
if self.n == 0 {
return None;
}
let root = self.root_node_ref();
let inner_entry: OccupiedNodeEntry<'s, K, V, B, NodeRef<'s, K, V, B>> =
root.last_entry_in(vec![]);
Some(inner_entry.into_key_value())
}
pub fn first(&self) -> Option<&K> {
self.first_key_value().map(|(k, _)| k)
}
pub fn last(&self) -> Option<&K> {
self.last_key_value().map(|(k, _)| k)
}
pub unsafe fn entry_ref_in<'a, 's, A: Allocator, Q>(
&'s mut self,
alloc: &'a A,
key: &Q,
) -> Option<OccupiedEntry<'a, 's, A, K, V, B>>
where
K: Borrow<Q>,
Q: PartialOrd + core::fmt::Debug + ?Sized,
{
let map = NonNull::from_mut(self);
let root = self.root_mut_node_ref();
match root.ref_entry(key, vec![]) {
NodeEntry::Vacant(_) => None,
NodeEntry::Occupied(inner) => {
Some(unsafe { OccupiedEntry::new(alloc, inner, map) })
}
}
}
pub unsafe fn remove_in<A: Allocator, Q>(&mut self, alloc: &A, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: PartialOrd + core::fmt::Debug + ?Sized,
{
unsafe { self.remove_entry_in(alloc, key).map(|(_, v)| v) }
}
pub unsafe fn remove_entry_in<A: Allocator, Q>(&mut self, alloc: &A, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: PartialOrd + core::fmt::Debug + ?Sized,
{
unsafe {
self.entry_ref_in(alloc, key)
.map(|entry| entry.remove_entry())
}
}
}
impl<'a, K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength, A: Allocator>
FromIteratorIn<'a, (K, V), A> for AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
fn from_iter_in<T>(alloc: &'a A, iter: T) -> DropGuardResult<Self, &'a A>
where
T: IntoIterator<Item = (K, V)>,
{
let mut btree: DropGuard<Self, &'a A> = Self::new_in(alloc)?;
for (k, v) in iter {
unsafe {
btree.insert_in(alloc, k, v)?;
}
}
Ok(btree)
}
}
impl<K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength> DropIn
for AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
unsafe fn drop_in<A: Allocator>(&mut self, alloc: &A) {
unsafe {
if let Some(r) = self.root.as_mut() {
r.drop_in(alloc);
}
}
}
}
impl<K, V, B> RecursiveDropIn for AllocatedBTreeMap<K, V, B>
where
K: core::cmp::PartialOrd + core::fmt::Debug + DropIn,
V: DropIn,
B: ArrayLength,
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
unsafe fn recursive_drop_in<A: Allocator>(&mut self, alloc: &A) {
if let Some(root) = self.root.as_mut() {
let root_owned = unsafe { ManuallyDrop::take(root) };
for (mut k, mut v) in NodeIntoIter::new(alloc, root_owned) {
unsafe { k.drop_in(alloc) };
unsafe { v.drop_in(alloc) };
}
}
unsafe { self.drop_in(alloc) };
}
}
impl<'a, K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength, A: Allocator + 'a>
IntoIteratorIn<'a, A> for AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
type Item = (K, V);
type IntoIter = IntoIter<'a, K, V, B, A>;
unsafe fn into_iter_in(self, alloc: &'a A) -> Self::IntoIter {
IntoIter {
inner: NodeIntoIter::new(alloc, ManuallyDrop::into_inner(self.root.unwrap())),
}
}
}
impl<'s, K: core::cmp::PartialOrd + core::fmt::Debug, V, B: ArrayLength> IntoIterator
for &'s AllocatedBTreeMap<K, V, B>
where
U2: Mul<B>,
Prod<U2, B>: ArrayLength,
U1: Add<Prod<U2, B>>,
Sum<U1, Prod<U2, B>>: ArrayLength,
{
type IntoIter = Iter<'s, K, V, B>;
type Item = (&'s K, &'s V);
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
mod iters;
#[cfg(test)]
mod tests;
pub use iters::{IntoIter, IntoKeys, IntoValues, Iter, Keys, Values, ValuesMut};