use crate::alloc_proxy::proxy::{Allocator, Layout, handle_alloc_error};
use crate::policy::internal_details::TreePolicy;
use crate::{
augmented_rbtree::{OutOfMemoryError, internal_details::AugmentedRBTreeInt},
node::Node,
};
use core::ptr::NonNull;
#[derive(Debug)]
pub enum Entry<'a, K, V, S, A: Allocator, P: TreePolicy<K = K, V = V, S = S>>
where
K: Ord,
{
Occupied(OccupiedEntry<'a, K, V, S, A, P>),
Vacant(VacantEntry<'a, K, V, S, A, P>),
}
#[derive(Debug)]
pub struct OccupiedEntry<'a, K, V, S, A, P>
where
K: Ord,
P: TreePolicy<K = K, V = V, S = S>,
A: Allocator,
{
tree: &'a mut AugmentedRBTreeInt<K, V, S, A, P>,
node: NonNull<Node<K, V, S>>,
}
#[derive(Debug)]
pub struct VacantEntry<'a, K, V, S, A, P>
where
P: TreePolicy<K = K, V = V, S = S>,
K: Ord,
A: Allocator,
{
tree: &'a mut AugmentedRBTreeInt<K, V, S, A, P>,
key: K,
}
impl<'a, K, V, S, A: Allocator, P: TreePolicy<K = K, V = V, S = S>> Entry<'a, K, V, S, A, P>
where
K: Ord,
{
pub(crate) fn new(tree: &'a mut AugmentedRBTreeInt<K, V, S, A, P>, key: K) -> Self {
if let Some(node) = tree.layout.find_node(&key) {
drop(key);
Entry::Occupied(OccupiedEntry {
tree,
node: node.ptr,
})
} else {
Entry::Vacant(VacantEntry { tree, key })
}
}
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(default),
}
}
pub fn or_insert_with(self, default: impl FnOnce() -> V) -> &'a mut V {
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(default()),
}
}
pub fn or_default(self) -> &'a mut V
where
V: Default,
{
self.or_insert_with(V::default)
}
pub fn key(&self) -> &K {
match self {
Entry::Occupied(e) => e.key(),
Entry::Vacant(e) => &e.key,
}
}
#[must_use]
pub fn and_modify(self, f: impl FnOnce(&mut V)) -> Self {
match self {
Entry::Occupied(mut e) => {
f(e.get_mut());
Entry::Occupied(e)
}
Entry::Vacant(e) => Entry::Vacant(e),
}
}
}
impl<'a, K, V, S, A, P> OccupiedEntry<'a, K, V, S, A, P>
where
K: Ord,
P: TreePolicy<K = K, V = V, S = S>,
A: Allocator,
{
#[must_use]
pub fn key(&self) -> &K {
unsafe { &(*self.node.as_ptr()).key }
}
#[must_use]
pub fn get(&self) -> &V {
unsafe { &(*self.node.as_ptr()).value }
}
pub fn get_mut(&mut self) -> &mut V {
unsafe { &mut (*self.node.as_ptr()).value }
}
#[must_use]
pub fn into_mut(self) -> &'a mut V {
unsafe { &mut (*self.node.as_ptr()).value }
}
pub fn insert(&mut self, value: V) -> V {
unsafe { core::mem::replace(&mut (*self.node.as_ptr()).value, value) }
}
#[must_use]
pub fn remove(self) -> V
where
K: Clone,
{
let key = self.key().clone();
self.tree
.remove(&key)
.expect("occupied entry must have a value")
}
}
impl<'a, K, V, S, A, P> VacantEntry<'a, K, V, S, A, P>
where
K: Ord,
P: TreePolicy<K = K, V = V, S = S>,
A: Allocator,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn try_insert(self, value: V) -> Result<&'a mut V, OutOfMemoryError>
where
P: TreePolicy<K = K, V = V, S = S>,
{
let node = self.tree.layout.try_insert_node_get_ref(self.key, value)?;
self.tree.len += 1;
Ok(unsafe { &mut (*node.ptr.as_ptr()).value })
}
pub fn insert(self, value: V) -> &'a mut V {
self.try_insert(value)
.unwrap_or_else(|_| handle_alloc_error(Layout::new::<Node<K, V, S>>()))
}
}