use std::{
cmp::Ordering,
collections::HashMap,
fmt::Debug,
ops::{Index, IndexMut},
slice::{GetDisjointMutError, Iter},
vec::Drain,
};
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "rkyv",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
pub(crate) struct Node<K, V> {
key: Option<K>,
sub_keys: Vec<NodeIndex>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
value: Option<V>,
}
impl<K, V> Node<K, V> {
pub const fn root() -> Self {
Node {
key: None,
sub_keys: Vec::new(),
value: None,
}
}
pub fn keyed(key: K) -> Self {
Self {
sub_keys: Vec::default(),
value: None,
key: Some(key),
}
}
}
impl<K, V> Node<K, V> {
pub fn key(&self) -> &Option<K> {
&self.key
}
pub fn get_with<'a, F>(
&'a self,
buffer: &'a Slots<K, V>,
mut functor: F,
) -> Option<&'a NodeIndex>
where
F: FnMut(&'a K) -> Ordering,
{
let result = self
.sub_keys
.binary_search_by(|k| {
let sub = buffer[*k].key().as_ref().expect("Node key was null.");
functor(sub)
})
.ok()?;
Some(&self.sub_keys[result])
}
pub fn value_mut_unchecked(&mut self) -> &mut V {
self.value_mut()
.as_mut()
.expect("Tried to get the value as some value but was None.")
}
pub fn subkeys(&self) -> Iter<'_, NodeIndex> {
self.sub_keys.iter()
}
pub fn remove_subkey(&mut self, result: NodeIndex) -> Option<NodeIndex> {
if result == NodeIndex::ROOT {
return Some(NodeIndex::ROOT);
}
let position = self.subkeys().position(|s| *s == result)?;
Some(self.sub_keys.remove(position))
}
fn bin_search(&self, reference: NodeIndex, buffer: &Slots<K, V>) -> Result<usize, usize>
where
K: Ord,
{
let key = buffer[reference]
.key()
.as_ref()
.expect("Reference node was the root node.");
self.sub_keys.binary_search_by(|node|
buffer[*node].key.as_ref().expect("Node key was null").cmp(key))
}
pub fn sub_key_len(&self) -> usize {
self.sub_keys.len()
}
pub fn into_value(self) -> Option<V> {
self.value
}
pub fn value(&self) -> &Option<V> {
&self.value
}
pub fn value_mut(&mut self) -> &mut Option<V> {
&mut self.value
}
pub fn semantic_equals(
&self,
other: &Self,
list_self: &Slots<K, V>,
list_other: &Slots<K, V>,
) -> bool
where
K: PartialEq,
V: PartialEq,
{
if !(self.key.eq(&other.key) && self.value.eq(&other.value)) {
return false;
}
if self.sub_keys.len() != other.sub_keys.len() {
return false;
}
for i in 0..self.sub_keys.len() {
if !list_self[self.sub_keys[i]].semantic_equals(
&list_other[other.sub_keys[i]],
list_self,
list_other,
) {
return false;
}
}
true
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "rkyv",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
pub(crate) struct Slots<K, V> {
slots: Vec<Option<Node<K, V>>>,
free_list: Vec<usize>,
}
impl<K, V> PartialEq for Slots<K, V>
where
K: PartialEq,
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self[NodeIndex::ROOT].semantic_equals(&other[NodeIndex::ROOT], self, other)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "rkyv",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
rkyv(derive(PartialEq, Debug))
)]
pub(crate) struct NodeIndex(u64);
impl NodeIndex {
pub const ROOT: NodeIndex = NodeIndex(0);
}
impl NodeIndex {
pub fn position(&self) -> usize {
self.0 as usize
}
}
impl<K, V> Slots<K, V> {
pub fn with_capacity(cap: usize) -> Self {
let mut new = Self {
slots: Vec::with_capacity(cap),
free_list: vec![],
};
new.slots.insert(0, Some(Node::root()));
new
}
pub fn capacity(&self) -> usize {
self.slots.capacity()
}
pub fn slot_iter(&self) -> std::slice::Iter<'_, Option<Node<K, V>>> {
self.slots.iter()
}
pub fn slot_iter_mut(&mut self) -> SlotsIterMut<'_, K, V> {
SlotsIterMut {
inner: self.slots.iter_mut(),
}
}
pub fn reserve(&mut self, quantity: usize) {
self.slots.reserve(quantity);
}
pub fn drain_slots(&mut self) -> Drain<'_, Option<Node<K, V>>> {
self.slots.insert(0, Some(Node::root()));
self.slots.drain(1..self.slots.len())
}
pub fn get_disjoint_mut<const N: usize>(
&mut self,
nodes: [NodeIndex; N],
) -> Result<DisjointMutIndices<'_, K, V, N>, GetDisjointMutError> {
let translated: [usize; N] = core::array::from_fn(|i| nodes[i].position());
let r = self.slots.get_disjoint_mut(translated)?;
Ok(DisjointMutIndices(r))
}
pub fn insert(&mut self, item: Node<K, V>) -> NodeIndex {
if !self.free_list.is_empty() {
let avail = self
.free_list
.pop()
.expect("List was not empty but could not pop.");
self.slots[avail] = Some(item);
NodeIndex(avail as u64)
} else {
self.slots.push(Some(item));
NodeIndex((self.slots.len() - 1) as u64)
}
}
pub fn remove(&mut self, index: NodeIndex) -> Option<Node<K, V>> {
if index.position() == 0 {
let root = core::mem::take(&mut self.slots[index.position()]);
self.slots[index.position()] = Some(Node::root());
return root;
}
let pos = &mut self.slots[index.position()];
if pos.is_some() {
self.free_list.push(index.position());
}
pos.take()
}
pub fn iter(&self) -> impl Iterator<Item = (NodeIndex, &Node<K, V>)> {
self.slots
.iter()
.enumerate()
.filter_map(|(i, f)| Some((NodeIndex(i as u64), f.as_ref()?)))
}
pub fn insert_subkey(&mut self, source: NodeIndex, value: NodeIndex) -> Option<NodeIndex>
where
K: Ord,
{
match self[source].bin_search(value, self) {
Ok(valid) => {
let old = std::mem::replace(&mut self[source].sub_keys[valid], value);
Some(old)
}
Err(invalid) => {
self[source].sub_keys.insert(invalid, value);
None
}
}
}
pub fn clear(&mut self) {
self.slots.clear();
self.slots.insert(0, Some(Node::root()));
}
pub fn shrink_to_fit(&mut self) {
while self.slots[self.slots.len() - 1].is_none() {
self.slots.remove(self.slots.len() - 1);
}
self.slots.shrink_to_fit();
}
fn get_defrag_map(&mut self) -> HashMap<NodeIndex, NodeIndex> {
let mut remapper = HashMap::<NodeIndex, NodeIndex>::new();
let mut drag = 0;
for index in 0..self.slots.len() {
if self.slots[index].is_some() && drag == index {
drag += 1;
} else if self.slots[index].is_some() {
remapper.insert(NodeIndex(index as u64), NodeIndex(drag as u64));
self.slots.swap(index, drag);
drag += 1;
}
}
remapper
}
pub fn defragment(&mut self) {
let remapper = self.get_defrag_map();
self.free_list.clear();
for node in self
.slots
.iter_mut()
.filter_map(<Option<Node<K, V>>>::as_mut)
{
for key in &mut node.sub_keys {
if let Some(new_k) = remapper.get(key) {
*key = *new_k;
}
}
}
}
}
pub(crate) struct SlotsIterMut<'a, K, V> {
inner: core::slice::IterMut<'a, Option<Node<K, V>>>,
}
impl<'a, K, V> Iterator for SlotsIterMut<'a, K, V> {
type Item = &'a mut Node<K, V>;
fn next(&mut self) -> Option<Self::Item> {
let mut current = self.inner.next()?;
while current.is_none() {
current = self.inner.next()?;
}
current.as_mut()
}
}
impl<K, V> Index<NodeIndex> for Slots<K, V> {
type Output = Node<K, V>;
fn index(&self, index: NodeIndex) -> &Self::Output {
self.slots[index.position()]
.as_ref()
.expect("Could not find node at requested index.")
}
}
impl<K, V> IndexMut<NodeIndex> for Slots<K, V> {
fn index_mut(&mut self, index: NodeIndex) -> &mut Self::Output {
self.slots[index.position()]
.as_mut()
.expect("Could not find node at requested index.")
}
}
pub struct DisjointMutIndices<'a, K, V, const N: usize>([&'a mut Option<Node<K, V>>; N]);
impl<'a, K, V, const N: usize> DisjointMutIndices<'a, K, V, N> {
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<'a, K, V, const N: usize> Index<usize> for DisjointMutIndices<'a, K, V, N> {
type Output = Option<V>;
fn index(&self, index: usize) -> &Self::Output {
self.0[index]
.as_ref()
.expect("Could not find node at requested index.")
.value()
}
}
impl<'a, K, V, const N: usize> IndexMut<usize> for DisjointMutIndices<'a, K, V, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let inner = self.0[index]
.as_mut()
.expect("Could not find node at requested index.");
&mut inner.value
}
}
#[cfg(test)]
mod tests {
use crate::{Node, NodeIndex};
use super::Slots;
#[test]
pub fn basic_nodelist() {
let mut list = Slots::<char, String>::with_capacity(0);
let key = list.insert(Node::root());
assert_eq!(list.free_list.len(), 0);
assert_eq!(list.slots.len(), 2);
list.remove(key).unwrap();
assert_eq!(list.free_list.len(), 1);
assert_eq!(list.slots.len(), 2);
list.insert(Node::root());
assert_eq!(list.free_list.len(), 0);
assert_eq!(list.slots.len(), 2);
}
#[test]
pub fn remove_root() {
let mut list = Slots::<char, String>::with_capacity(0);
assert!(list.remove(super::NodeIndex::ROOT).unwrap().key().is_none());
}
#[test]
pub fn root_exists_post_drain() {
let mut list = Slots::<char, usize>::with_capacity(1);
list.insert(Node::keyed('a'));
for _ in list.drain_slots() {}
assert!(list[NodeIndex::ROOT].key().is_none());
}
fn check_map_integrity_defragmented(map: &Slots<char, String>) {
for slot in map.slots.iter().filter_map(Option::as_ref) {
for key in slot.subkeys() {
if map.slots[key.position()].is_none() {
panic!("Key reference invalid!");
}
}
}
let mut has_seen_none = false;
for slot in &map.slots {
if slot.is_none() {
has_seen_none = true;
} else if slot.is_some() && has_seen_none {
panic!("There is an empty slot not at end of list.");
}
}
}
#[test]
pub fn test_remap_shrink() {
let mut list = Slots::<char, String>::with_capacity(0);
let _ = list.insert(Node::root());
let bruha = list.insert(Node::keyed('a'));
let bruh = list.insert(Node::keyed('b'));
let bruhc = list.insert(Node::keyed('c'));
let bruhd = list.insert(Node::keyed('d'));
let bruhe = list.insert(Node::keyed('e'));
let bruhf = list.insert(Node::keyed('f'));
list.insert_subkey(bruhf, bruhd);
list.remove(bruh);
list.remove(bruhc);
list.remove(bruha);
list.remove(bruhe);
list.defragment();
check_map_integrity_defragmented(&list);
list.shrink_to_fit();
check_map_integrity_defragmented(&list);
}
}