weavatrix_graph/payload/stable_undirected/
core.rs1use super::incidence::{IncidentEdges, NONE_SLOT};
2use crate::Vec;
3use crate::payload::stable::core::next_slot;
4use crate::{EdgeEndpoints, GraphError, Result, StableEdgeKey, StableNodeKey};
5
6#[derive(Debug, Clone)]
7pub(super) struct NodeSlot<NodePayload> {
8 pub(super) generation: u32,
9 pub(super) value: Option<NodePayload>,
10 pub(super) first_edge: u32,
11 pub(super) last_edge: u32,
12 pub(super) degree: usize,
13}
14
15#[derive(Debug, Clone)]
16pub(super) struct EdgeSlot<EdgePayload> {
17 pub(super) generation: u32,
18 pub(super) value: Option<EdgePayload>,
19 pub(super) source: u32,
20 pub(super) target: u32,
21 pub(super) source_previous: u32,
22 pub(super) source_next: u32,
23 pub(super) target_previous: u32,
24 pub(super) target_next: u32,
25}
26
27#[derive(Debug, Clone)]
29pub struct StableUndirectedPayloadGraph<NodePayload, EdgePayload> {
30 pub(super) nodes: Vec<NodeSlot<NodePayload>>,
31 pub(super) edges: Vec<EdgeSlot<EdgePayload>>,
32 pub(super) free_nodes: Vec<u32>,
33 pub(super) free_edges: Vec<u32>,
34 pub(super) node_count: usize,
35 pub(super) edge_count: usize,
36}
37
38impl<NodePayload, EdgePayload> Default for StableUndirectedPayloadGraph<NodePayload, EdgePayload> {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44impl<NodePayload, EdgePayload> StableUndirectedPayloadGraph<NodePayload, EdgePayload> {
45 #[must_use]
46 pub const fn new() -> Self {
47 Self {
48 nodes: Vec::new(),
49 edges: Vec::new(),
50 free_nodes: Vec::new(),
51 free_edges: Vec::new(),
52 node_count: 0,
53 edge_count: 0,
54 }
55 }
56
57 #[must_use]
58 pub fn with_capacity(nodes: usize, edges: usize) -> Self {
59 Self {
60 nodes: Vec::with_capacity(nodes),
61 edges: Vec::with_capacity(edges),
62 free_nodes: Vec::new(),
63 free_edges: Vec::new(),
64 node_count: 0,
65 edge_count: 0,
66 }
67 }
68
69 pub fn add_node(&mut self, payload: NodePayload) -> Result<StableNodeKey> {
75 let key = if let Some(slot) = self.free_nodes.pop() {
76 let entry = &mut self.nodes[slot as usize];
77 entry.value = Some(payload);
78 entry.first_edge = NONE_SLOT;
79 entry.last_edge = NONE_SLOT;
80 entry.degree = 0;
81 StableNodeKey::new(slot, entry.generation)
82 } else {
83 let slot = next_slot(self.nodes.len(), "stable undirected nodes")?;
84 self.nodes.push(NodeSlot {
85 generation: 0,
86 value: Some(payload),
87 first_edge: NONE_SLOT,
88 last_edge: NONE_SLOT,
89 degree: 0,
90 });
91 StableNodeKey::new(slot, 0)
92 };
93 self.node_count += 1;
94 Ok(key)
95 }
96
97 pub fn add_edge(
103 &mut self,
104 source: StableNodeKey,
105 target: StableNodeKey,
106 payload: EdgePayload,
107 ) -> Result<StableEdgeKey> {
108 self.require_node(source)?;
109 self.require_node(target)?;
110 let key = self.allocate_edge(source, target, payload)?;
111 self.link(source, key);
112 if source != target {
113 self.link(target, key);
114 }
115 self.edge_count += 1;
116 Ok(key)
117 }
118
119 #[must_use]
120 pub fn node(&self, key: StableNodeKey) -> Option<&NodePayload> {
121 self.node_slot(key)?.value.as_ref()
122 }
123
124 #[must_use]
125 pub fn node_mut(&mut self, key: StableNodeKey) -> Option<&mut NodePayload> {
126 self.node_slot_mut(key)?.value.as_mut()
127 }
128
129 #[must_use]
130 pub fn edge(&self, key: StableEdgeKey) -> Option<&EdgePayload> {
131 self.edge_slot(key)?.value.as_ref()
132 }
133
134 #[must_use]
135 pub fn edge_mut(&mut self, key: StableEdgeKey) -> Option<&mut EdgePayload> {
136 self.edge_slot_mut(key)?.value.as_mut()
137 }
138
139 #[must_use]
140 pub fn edge_endpoints(&self, key: StableEdgeKey) -> Option<EdgeEndpoints<StableNodeKey>> {
141 let edge = self.edge_slot(key)?;
142 Some(EdgeEndpoints::new(
143 self.node_key_at(edge.source)?,
144 self.node_key_at(edge.target)?,
145 ))
146 }
147
148 pub fn nodes(&self) -> impl Iterator<Item = (StableNodeKey, &NodePayload)> {
149 self.nodes.iter().enumerate().filter_map(|(slot, entry)| {
150 Some((
151 StableNodeKey::new(u32::try_from(slot).ok()?, entry.generation),
152 entry.value.as_ref()?,
153 ))
154 })
155 }
156
157 pub fn edges(&self) -> impl Iterator<Item = (StableEdgeKey, &EdgePayload)> {
158 self.edges.iter().enumerate().filter_map(|(slot, entry)| {
159 Some((
160 StableEdgeKey::new(u32::try_from(slot).ok()?, entry.generation),
161 entry.value.as_ref()?,
162 ))
163 })
164 }
165
166 #[must_use]
167 pub fn incident_edges(
168 &self,
169 node: StableNodeKey,
170 ) -> impl DoubleEndedIterator<Item = StableEdgeKey> + ExactSizeIterator + '_ {
171 IncidentEdges::new(self, node)
172 }
173
174 #[must_use]
175 pub const fn node_count(&self) -> usize {
176 self.node_count
177 }
178
179 #[must_use]
180 pub const fn edge_count(&self) -> usize {
181 self.edge_count
182 }
183
184 #[must_use]
185 pub const fn is_empty(&self) -> bool {
186 self.node_count == 0 && self.edge_count == 0
187 }
188
189 pub(super) fn node_slot(&self, key: StableNodeKey) -> Option<&NodeSlot<NodePayload>> {
190 let slot = self.nodes.get(key.index())?;
191 (slot.generation == key.generation() && slot.value.is_some()).then_some(slot)
192 }
193
194 pub(super) fn node_slot_mut(
195 &mut self,
196 key: StableNodeKey,
197 ) -> Option<&mut NodeSlot<NodePayload>> {
198 let slot = self.nodes.get_mut(key.index())?;
199 (slot.generation == key.generation() && slot.value.is_some()).then_some(slot)
200 }
201
202 pub(super) fn edge_slot(&self, key: StableEdgeKey) -> Option<&EdgeSlot<EdgePayload>> {
203 let slot = self.edges.get(key.index())?;
204 (slot.generation == key.generation() && slot.value.is_some()).then_some(slot)
205 }
206
207 pub(super) fn edge_slot_mut(
208 &mut self,
209 key: StableEdgeKey,
210 ) -> Option<&mut EdgeSlot<EdgePayload>> {
211 let slot = self.edges.get_mut(key.index())?;
212 (slot.generation == key.generation() && slot.value.is_some()).then_some(slot)
213 }
214
215 pub(super) fn require_node(&self, key: StableNodeKey) -> Result<()> {
216 self.node_slot(key)
217 .map(|_| ())
218 .ok_or(GraphError::InvalidStableKey {
219 category: "undirected node",
220 slot: key.slot(),
221 generation: key.generation(),
222 })
223 }
224
225 fn allocate_edge(
226 &mut self,
227 source: StableNodeKey,
228 target: StableNodeKey,
229 payload: EdgePayload,
230 ) -> Result<StableEdgeKey> {
231 if let Some(slot) = self.free_edges.pop() {
232 let entry = &mut self.edges[slot as usize];
233 entry.value = Some(payload);
234 entry.source = source.slot();
235 entry.target = target.slot();
236 entry.source_previous = NONE_SLOT;
237 entry.source_next = NONE_SLOT;
238 entry.target_previous = NONE_SLOT;
239 entry.target_next = NONE_SLOT;
240 return Ok(StableEdgeKey::new(slot, entry.generation));
241 }
242 let slot = next_slot(self.edges.len(), "stable undirected edges")?;
243 self.edges.push(EdgeSlot {
244 generation: 0,
245 value: Some(payload),
246 source: source.slot(),
247 target: target.slot(),
248 source_previous: NONE_SLOT,
249 source_next: NONE_SLOT,
250 target_previous: NONE_SLOT,
251 target_next: NONE_SLOT,
252 });
253 Ok(StableEdgeKey::new(slot, 0))
254 }
255
256 pub(super) fn node_key_at(&self, slot: u32) -> Option<StableNodeKey> {
257 let entry = self.nodes.get(slot as usize)?;
258 entry
259 .value
260 .as_ref()
261 .map(|_| StableNodeKey::new(slot, entry.generation))
262 }
263}