use core::hash::BuildHasher;
use core::hash::Hash;
use crate::Ptr;
use crate::arena::ActiveSlotRef;
use crate::linked_hash_map::Entry;
use crate::linked_hash_map::Iter;
use crate::linked_hash_map::LinkedHashMap;
use crate::linked_hash_map::RemovedEntry;
#[derive(Debug)]
pub struct CursorMut<'m, K, T, S> {
pub(crate) ptr: Option<ActiveSlotRef<K, T>>,
pub(crate) map: &'m mut LinkedHashMap<K, T, S>,
}
impl<'m, K: Hash + Eq, T, S: BuildHasher> CursorMut<'m, K, T, S> {
pub fn insert_after_move_to(&mut self, key: K, value: T) -> Option<T> {
let ptr = if self.ptr.is_none() {
self.map.head_tail.as_ref().map(|ht| ht.tail)
} else {
self.ptr
};
match self.map.entry(key) {
Entry::Occupied(occupied_entry) => {
let mut map_ptr = *occupied_entry.entry.get();
if Some(map_ptr) != ptr {
self.map.move_after_internal(map_ptr, ptr.unwrap());
}
self.ptr = Some(map_ptr);
Some(core::mem::replace(
&mut map_ptr.data_mut(&mut self.map.nodes).value,
value,
))
}
Entry::Vacant(vacant_entry) => {
self.ptr = Some(vacant_entry.insert_after_internal(value, ptr).0);
None
}
}
}
pub fn insert_before_move_to(&mut self, key: K, value: T) -> Option<T> {
let ptr = if self.ptr.is_none() {
self.map.head_tail.as_ref().map(|ht| ht.head)
} else {
self.ptr
};
match self.map.entry(key) {
Entry::Occupied(occupied_entry) => {
let mut map_ptr = *occupied_entry.entry.get();
if Some(map_ptr) != ptr {
self.map.move_before_internal(map_ptr, ptr.unwrap());
}
self.ptr = Some(map_ptr);
Some(core::mem::replace(
&mut map_ptr.data_mut(&mut self.map.nodes).value,
value,
))
}
Entry::Vacant(vacant_entry) => {
self.ptr = Some(vacant_entry.insert_before_internal(value, ptr).0);
None
}
}
}
pub fn get_ptr(&self, key: &K) -> Option<Ptr> {
self.map.get_ptr(key)
}
}
impl<'m, K: Hash + Eq, T, S: BuildHasher> CursorMut<'m, K, T, S> {
pub fn remove_prev(&mut self) -> Option<(Ptr, RemovedEntry<K, T>)> {
let prev = self.ptr.map(|slot| slot.prev(&self.map.nodes))?;
Some(self.map.remove_ptr_internal(prev))
}
pub fn remove_next(&mut self) -> Option<(Ptr, RemovedEntry<K, T>)> {
let next = self.ptr.map(|slot| slot.next(&self.map.nodes))?;
Some(self.map.remove_ptr_internal(next))
}
pub fn remove(self) -> Option<(Ptr, RemovedEntry<K, T>)> {
let ptr = self.ptr?;
Some(self.map.remove_ptr_internal(ptr))
}
}
impl<'m, K, T, S> CursorMut<'m, K, T, S> {
pub fn iter(&self) -> Iter<'_, K, T> {
Iter {
forward_ptr: self.ptr,
reverse_ptr: self.ptr.map(|slot| slot.prev(&self.map.nodes)),
nodes: &self.map.nodes,
}
}
pub fn move_next(&mut self) {
self.ptr = self.ptr.map(|slot| slot.next(&self.map.nodes));
}
pub fn move_prev(&mut self) {
self.ptr = self.ptr.map(|slot| slot.prev(&self.map.nodes));
}
pub fn ptr(&self) -> Option<Ptr> {
self.ptr.map(|slot| slot.this(&self.map.nodes))
}
pub fn at_tail(&self) -> bool {
self.ptr == self.map.head_tail.as_ref().map(|ht| ht.tail)
}
pub fn at_head(&self) -> bool {
self.ptr == self.map.head_tail.as_ref().map(|ht| ht.head)
}
pub fn current(&self) -> Option<(&K, &T)> {
let ptr = self.ptr?;
let data = ptr.data(&self.map.nodes);
Some((&data.key, &data.value))
}
pub fn current_mut(&mut self) -> Option<(&K, &mut T)> {
let mut ptr = self.ptr?;
let data = ptr.data_mut(&mut self.map.nodes);
Some((&data.key, &mut data.value))
}
pub fn next_ptr(&self) -> Option<Ptr> {
self.ptr
.map(|slot| slot.next(&self.map.nodes).this(&self.map.nodes))
}
pub fn next(&self) -> Option<(&K, &T)> {
let ptr = self.next_ptr()?;
self.map.ptr_get_entry(ptr)
}
pub fn next_mut(&mut self) -> Option<(&K, &mut T)> {
let ptr = self.next_ptr()?;
self.map.ptr_get_entry_mut(ptr)
}
pub fn prev_ptr(&self) -> Option<Ptr> {
self.ptr
.map(|slot| slot.prev(&self.map.nodes).this(&self.map.nodes))
}
pub fn prev(&self) -> Option<(&K, &T)> {
let ptr = self.prev_ptr()?;
self.map.ptr_get_entry(ptr)
}
pub fn prev_mut(&mut self) -> Option<(&K, &mut T)> {
let ptr = self.prev_ptr()?;
self.map.ptr_get_entry_mut(ptr)
}
}