1use crate::{node::Node, tree::Tree};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub(crate) enum Entry<T> {
5 Free { next_free: Option<usize> },
6 Occupied(Node<T>),
7}
8
9impl<T> Entry<T> {
10 pub fn replace(&mut self, val: Self) -> Self {
11 std::mem::replace(self, val)
12 }
13
14 pub fn is_node(&self) -> bool {
15 matches!(self, Entry::Occupied(..))
16 }
17
18 pub fn unwrap(self) -> Node<T> {
19 match self {
20 Entry::Free { .. } => panic!("the entry is free"),
21 Entry::Occupied(node) => node,
22 }
23 }
24
25 pub fn unwrap_ref(&self) -> &Node<T> {
26 match self {
27 Entry::Free { .. } => panic!("the entry is free"),
28 Entry::Occupied(node) => node,
29 }
30 }
31
32 pub fn unwrap_mut(&mut self) -> &mut Node<T> {
33 match self {
34 Entry::Free { .. } => panic!("the entry is free"),
35 Entry::Occupied(node) => node,
36 }
37 }
38
39 pub fn unwrap_free(&self) -> Option<usize> {
40 match self {
41 Entry::Free { next_free } => *next_free,
42 Entry::Occupied(_) => panic!("the entry is occupied"),
43 }
44 }
45
46 pub fn map_ref<'a, U, F>(&'a self, f: F) -> Option<U>
47 where
48 F: FnOnce(&'a Node<T>) -> U,
49 {
50 match self {
51 Entry::Free { .. } => None,
52 Entry::Occupied(node) => Some(f(node)),
53 }
54 }
55
56 pub fn map_mut<'a, U, F>(&'a mut self, f: F) -> Option<U>
57 where
58 F: FnOnce(&'a mut Node<T>) -> U,
59 {
60 match self {
61 Entry::Free { .. } => None,
62 Entry::Occupied(node) => Some(f(node)),
63 }
64 }
65}
66
67impl<T> Tree<T> {
68 pub(crate) fn get_first_free(&self) -> usize {
69 self.first_free.unwrap_or(self.nodes.len())
70 }
71
72 pub(crate) fn allocate_node(&mut self, node: Node<T>) -> usize {
73 match self.first_free {
74 Some(index) => {
75 let entry = self.nodes[index].replace(Entry::Occupied(node));
76
77 self.first_free = entry.unwrap_free();
78
79 index
80 }
81 None => {
82 let index = self.nodes.len();
83
84 self.nodes.push(Entry::Occupied(node));
85
86 index
87 }
88 }
89 }
90
91 pub(super) fn free_node(&mut self, index: usize) -> Entry<T> {
92 let next_free = self.first_free.replace(index);
93
94 self.nodes[index].replace(Entry::Free { next_free })
95 }
96}