#[cfg(not(feature = "std"))]
use alloc::{
vec,
vec::{IntoIter, Vec},
};
#[cfg(not(feature = "std"))]
use core::{
mem,
num::NonZeroUsize,
ops::{Index, IndexMut},
slice,
};
#[cfg(feature = "par_iter")]
use rayon::prelude::*;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::{
mem,
num::NonZeroUsize,
ops::{Index, IndexMut},
slice,
vec::IntoIter,
};
use crate::{Node, NodeId, node::NodeData};
#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct Arena<T> {
nodes: Vec<Node<T>>,
first_free_slot: Option<usize>,
last_free_slot: Option<usize>,
}
impl<T> Arena<T> {
#[must_use]
pub const fn new() -> Arena<T> {
Self {
nodes: Vec::new(),
first_free_slot: None,
last_free_slot: None,
}
}
#[must_use]
pub fn with_capacity(n: usize) -> Self {
Self {
nodes: Vec::with_capacity(n),
first_free_slot: None,
last_free_slot: None,
}
}
pub fn capacity(&self) -> usize {
self.nodes.capacity()
}
pub fn reserve(&mut self, additional: usize) {
self.nodes.reserve(additional);
}
pub fn get_node_id(&self, node: &Node<T>) -> Option<NodeId> {
let nodes_range = self.nodes.as_ptr_range();
let p = node as *const Node<T>;
if !nodes_range.contains(&p) {
return None;
}
let node_index = (p as usize - nodes_range.start as usize) / mem::size_of::<Node<T>>();
let node_id = NonZeroUsize::new(node_index.wrapping_add(1))?;
Some(NodeId::from_non_zero_usize(
node_id,
self.nodes[node_index].stamp,
))
}
pub fn get_node_id_at(&self, index: NonZeroUsize) -> Option<NodeId> {
let index0 = index.get() - 1; self.nodes
.get(index0)
.filter(|n| !n.is_removed())
.map(|node| NodeId::from_non_zero_usize(index, node.stamp))
}
pub fn new_node(&mut self, data: T) -> NodeId {
let (index, stamp) = if let Some(index) = self.pop_front_free_node() {
let node = &mut self.nodes[index];
node.reuse(data);
(index, node.stamp)
} else {
let index = self.nodes.len();
let node = Node::new(data);
let stamp = node.stamp;
self.nodes.push(node);
(index, stamp)
};
let next_index1 =
NonZeroUsize::new(index.wrapping_add(1)).expect("Too many nodes in the arena");
NodeId::from_non_zero_usize(next_index1, stamp)
}
#[deprecated(since = "4.9.0", note = "use len() instead")]
pub fn count(&self) -> usize {
self.nodes.len()
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
#[inline]
pub fn get(&self, id: NodeId) -> Option<&Node<T>> {
self.nodes
.get(id.index0())
.filter(|node| node.stamp == id.stamp())
}
#[inline]
pub fn get_mut(&mut self, id: NodeId) -> Option<&mut Node<T>> {
let stamp = id.stamp();
self.nodes
.get_mut(id.index0())
.filter(|node| node.stamp == stamp)
}
#[inline]
pub fn get_data(&self, id: NodeId) -> Option<&T> {
self.get(id).map(|n| n.get())
}
#[inline]
pub fn get_data_mut(&mut self, id: NodeId) -> Option<&mut T> {
self.get_mut(id).map(|n| n.get_mut())
}
pub fn iter(&self) -> slice::Iter<'_, Node<T>> {
self.nodes.iter()
}
pub fn iter_node_ids(&self) -> impl Iterator<Item = NodeId> + '_ {
self.nodes.iter().enumerate().filter_map(|(i, node)| {
if node.is_removed() {
return None;
}
let index1 = NonZeroUsize::new(i.wrapping_add(1))?;
Some(NodeId::from_non_zero_usize(index1, node.stamp))
})
}
pub fn iter_mut(&mut self) -> slice::IterMut<'_, Node<T>> {
self.nodes.iter_mut()
}
pub fn roots(&self) -> impl Iterator<Item = NodeId> + '_ {
self.iter_node_ids()
.filter(|&id| self[id].parent().is_none())
}
pub fn map<U>(&self, mut f: impl FnMut(&T) -> U) -> Arena<U> {
let nodes = self
.nodes
.iter()
.map(|node| Node {
parent: node.parent,
previous_sibling: node.previous_sibling,
next_sibling: node.next_sibling,
first_child: node.first_child,
last_child: node.last_child,
stamp: node.stamp,
data: match &node.data {
NodeData::Data(data) => NodeData::Data(f(data)),
NodeData::NextFree(next) => NodeData::NextFree(*next),
},
})
.collect();
Arena {
nodes,
first_free_slot: self.first_free_slot,
last_free_slot: self.last_free_slot,
}
}
pub fn shrink_to_fit(&mut self) {
self.nodes.shrink_to_fit();
}
pub fn live_count(&self) -> usize {
self.nodes.iter().filter(|n| !n.is_removed()).count()
}
pub fn clear(&mut self) {
self.nodes.clear();
self.first_free_slot = None;
self.last_free_slot = None;
}
pub fn as_slice(&self) -> &[Node<T>] {
self.nodes.as_slice()
}
#[must_use]
pub fn validate(&self) -> bool {
let len = self.nodes.len();
let is_valid = |id: NodeId| -> bool {
let idx = id.index0();
idx < len && self.nodes[idx].stamp == id.stamp() && !self.nodes[idx].is_removed()
};
let mut in_child_chain = vec![false; len];
for (i, node) in self.nodes.iter().enumerate() {
if node.is_removed() {
continue;
}
if !matches!(node.data, NodeData::Data(_)) {
return false;
}
if let Some(parent) = node.parent {
if !is_valid(parent) {
return false;
}
}
if let Some(prev) = node.previous_sibling {
if !is_valid(prev)
|| self.nodes[prev.index0()].next_sibling.map(|n| n.index0()) != Some(i)
{
return false;
}
}
if let Some(next) = node.next_sibling {
if !is_valid(next)
|| self.nodes[next.index0()]
.previous_sibling
.map(|n| n.index0())
!= Some(i)
{
return false;
}
}
if node.first_child.is_some() != node.last_child.is_some() {
return false;
}
if let Some(first) = node.first_child {
if !is_valid(first) {
return false;
}
let mut child = Some(first);
let mut last_seen = first;
let mut steps = 0;
while let Some(c) = child {
let idx = c.index0();
if idx >= len {
return false;
}
let child_node = &self.nodes[idx];
if child_node.parent.map(|n| n.index0()) != Some(i) {
return false;
}
in_child_chain[idx] = true;
last_seen = c;
child = child_node.next_sibling;
steps += 1;
if steps > len {
return false;
}
}
if node.last_child.map(|n| n.index0()) != Some(last_seen.index0()) {
return false;
}
}
}
for (i, node) in self.nodes.iter().enumerate() {
if !node.is_removed() && node.parent.is_some() && !in_child_chain[i] {
return false;
}
}
if self.first_free_slot.is_some() != self.last_free_slot.is_some() {
return false;
}
let mut free_count = 0;
let mut last_visited = None;
let mut slot = self.first_free_slot;
while let Some(idx) = slot {
if idx >= len {
return false;
}
let node = &self.nodes[idx];
if !node.is_removed() {
return false;
}
match node.data {
NodeData::NextFree(next) => slot = next,
_ => return false,
}
last_visited = Some(idx);
free_count += 1;
if free_count > len {
return false;
}
}
self.last_free_slot == last_visited
}
pub(crate) fn free_node(&mut self, id: NodeId) {
let node = &mut self[id];
if node.is_removed() {
return;
}
node.data = NodeData::NextFree(None);
node.stamp.mark_removed();
let stamp = node.stamp;
if stamp.reuseable() {
if let Some(index) = self.last_free_slot {
let new_last = id.index0();
self.nodes[index].data = NodeData::NextFree(Some(new_last));
self.last_free_slot = Some(new_last);
} else {
debug_assert!(self.first_free_slot.is_none());
debug_assert!(self.last_free_slot.is_none());
self.first_free_slot = Some(id.index0());
self.last_free_slot = Some(id.index0());
}
}
}
fn pop_front_free_node(&mut self) -> Option<usize> {
let first = self.first_free_slot.take();
if let Some(index) = first {
if let NodeData::NextFree(next_free) = self.nodes[index].data {
self.first_free_slot = next_free;
} else {
unreachable!("A data node considered as a freed node");
}
if self.first_free_slot.is_none() {
self.last_free_slot = None;
}
}
first
}
}
#[cfg(feature = "par_iter")]
impl<T: Sync> Arena<T> {
pub fn par_iter(&self) -> rayon::slice::Iter<'_, Node<T>> {
self.nodes.par_iter()
}
}
#[cfg(feature = "par_iter")]
impl<T: Send> Arena<T> {
pub fn par_iter_mut(&mut self) -> rayon::slice::IterMut<'_, Node<T>> {
self.nodes.par_iter_mut()
}
}
impl<'a, T> IntoIterator for &'a Arena<T> {
type Item = &'a Node<T>;
type IntoIter = slice::Iter<'a, Node<T>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut Arena<T> {
type Item = &'a mut Node<T>;
type IntoIter = slice::IterMut<'a, Node<T>>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> Extend<T> for Arena<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (lower, _) = iter.size_hint();
self.reserve(lower);
for item in iter {
self.new_node(item);
}
}
}
impl<T> core::iter::FromIterator<T> for Arena<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut arena = Arena::new();
arena.extend(iter);
arena
}
}
impl<T> IntoIterator for Arena<T> {
type Item = Node<T>;
type IntoIter = IntoIter<Node<T>>;
fn into_iter(self) -> Self::IntoIter {
self.nodes.into_iter()
}
}
impl<T> Default for Arena<T> {
fn default() -> Self {
Self {
nodes: Vec::new(),
first_free_slot: None,
last_free_slot: None,
}
}
}
impl<T> Index<NodeId> for Arena<T> {
type Output = Node<T>;
#[inline]
fn index(&self, node: NodeId) -> &Node<T> {
&self.nodes[node.index0()]
}
}
impl<T> IndexMut<NodeId> for Arena<T> {
#[inline]
fn index_mut(&mut self, node: NodeId) -> &mut Node<T> {
&mut self.nodes[node.index0()]
}
}
#[test]
fn reuse_node() {
let mut arena = Arena::new();
let n1_id = arena.new_node("1");
let n2_id = arena.new_node("2");
let n3_id = arena.new_node("3");
n1_id.remove(&mut arena);
n2_id.remove(&mut arena);
n3_id.remove(&mut arena);
let n1_id = arena.new_node("1");
let n2_id = arena.new_node("2");
let n3_id = arena.new_node("3");
assert_eq!(n1_id.index0(), 0);
assert_eq!(n2_id.index0(), 1);
assert_eq!(n3_id.index0(), 2);
assert_eq!(arena.nodes.len(), 3);
}
#[test]
fn conserve_capacity() {
let mut arena = Arena::with_capacity(5);
let cap = arena.capacity();
assert!(cap >= 5);
for i in 0..cap {
arena.new_node(i);
}
arena.clear();
assert!(arena.is_empty());
let n1_id = arena.new_node(1);
let n2_id = arena.new_node(2);
let n3_id = arena.new_node(3);
assert_eq!(n1_id.index0(), 0);
assert_eq!(n2_id.index0(), 1);
assert_eq!(n3_id.index0(), 2);
assert_eq!(arena.len(), 3);
assert_eq!(arena.capacity(), cap);
}
#[test]
fn stamp_no_cycle() {
let mut arena = Arena::new();
for _ in 0..=i16::MAX as u32 + 1 {
let id = arena.new_node(42);
assert!(!id.is_removed(&arena));
id.remove(&mut arena);
assert!(id.is_removed(&arena));
let new_id = arena.new_node(42);
assert!(!new_id.is_removed(&arena));
assert!(id.is_removed(&arena));
new_id.remove(&mut arena);
}
}