1use std::ops::{Index, IndexMut};
4
5use blitz_traits::node_id::NodeId;
6use slotmap::{Key as _, KeyData, SlotMap};
7
8use crate::Node;
9
10slotmap::new_key_type! {
11 struct NodeKey;
14}
15
16#[inline(always)]
17fn to_key(id: NodeId) -> NodeKey {
18 NodeKey::from(KeyData::from_ffi(id.as_u64()))
19}
20
21#[inline(always)]
22fn to_id(key: NodeKey) -> NodeId {
23 NodeId::from_u64(key.data().as_ffi())
24}
25
26pub struct NodeTree(SlotMap<NodeKey, Node>);
34
35impl NodeTree {
36 pub(crate) fn new() -> Self {
37 Self(SlotMap::with_key())
38 }
39
40 pub fn len(&self) -> usize {
42 self.0.len()
43 }
44
45 pub fn is_empty(&self) -> bool {
46 self.0.is_empty()
47 }
48
49 pub fn contains_key(&self, id: NodeId) -> bool {
51 self.0.contains_key(to_key(id))
52 }
53
54 pub fn get(&self, id: NodeId) -> Option<&Node> {
56 self.0.get(to_key(id))
57 }
58
59 pub fn get_mut(&mut self, id: NodeId) -> Option<&mut Node> {
61 self.0.get_mut(to_key(id))
62 }
63
64 pub(crate) fn insert_with_key(&mut self, f: impl FnOnce(NodeId) -> Node) -> NodeId {
66 to_id(self.0.insert_with_key(|key| f(to_id(key))))
67 }
68
69 pub(crate) fn remove(&mut self, id: NodeId) -> Option<Node> {
71 self.0.remove(to_key(id))
72 }
73
74 pub fn iter(&self) -> impl Iterator<Item = (NodeId, &Node)> {
76 self.0.iter().map(|(key, node)| (to_id(key), node))
77 }
78
79 pub fn iter_mut(&mut self) -> impl Iterator<Item = (NodeId, &mut Node)> {
81 self.0.iter_mut().map(|(key, node)| (to_id(key), node))
82 }
83}
84
85impl Index<NodeId> for NodeTree {
86 type Output = Node;
87
88 #[track_caller]
89 #[inline]
90 fn index(&self, id: NodeId) -> &Node {
91 &self.0[to_key(id)]
92 }
93}
94
95impl IndexMut<NodeId> for NodeTree {
96 #[track_caller]
97 #[inline]
98 fn index_mut(&mut self, id: NodeId) -> &mut Node {
99 &mut self.0[to_key(id)]
100 }
101}