weavatrix_graph/payload/stable_undirected/
freeze.rs1use super::core::StableUndirectedPayloadGraph;
2use crate::payload::stable::mapped_node;
3use crate::{
4 EdgeEndpoints, EdgeIndex, NodeIndex, PayloadFreezeMap, Result, UndirectedPayloadGraph, Vec,
5};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct FrozenUndirectedPayloadGraph<NodePayload, EdgePayload> {
9 graph: UndirectedPayloadGraph<NodePayload, EdgePayload>,
10 indices: PayloadFreezeMap,
11}
12
13impl<NodePayload, EdgePayload> FrozenUndirectedPayloadGraph<NodePayload, EdgePayload> {
14 #[must_use]
15 pub const fn graph(&self) -> &UndirectedPayloadGraph<NodePayload, EdgePayload> {
16 &self.graph
17 }
18
19 #[must_use]
20 pub const fn indices(&self) -> &PayloadFreezeMap {
21 &self.indices
22 }
23
24 #[must_use]
25 pub fn into_parts(
26 self,
27 ) -> (
28 UndirectedPayloadGraph<NodePayload, EdgePayload>,
29 PayloadFreezeMap,
30 ) {
31 (self.graph, self.indices)
32 }
33}
34
35impl<NodePayload, EdgePayload> StableUndirectedPayloadGraph<NodePayload, EdgePayload> {
36 pub fn freeze(self) -> Result<FrozenUndirectedPayloadGraph<NodePayload, EdgePayload>> {
42 let mut node_map = vec![None; self.nodes.len()];
43 let mut nodes = Vec::with_capacity(self.node_count);
44 for (slot, entry) in self.nodes.into_iter().enumerate() {
45 let Some(payload) = entry.value else {
46 continue;
47 };
48 let compact = compact_node(nodes.len())?;
49 node_map[slot] = Some((entry.generation, compact));
50 nodes.push(payload);
51 }
52 let mut edge_map = vec![None; self.edges.len()];
53 let mut edges = Vec::with_capacity(self.edge_count);
54 for (slot, entry) in self.edges.into_iter().enumerate() {
55 let Some(payload) = entry.value else {
56 continue;
57 };
58 let source = mapped_node(&node_map, entry.source)?;
59 let target = mapped_node(&node_map, entry.target)?;
60 let compact = compact_edge(edges.len())?;
61 edge_map[slot] = Some((entry.generation, compact));
62 edges.push((EdgeEndpoints::new(source, target), payload));
63 }
64 let graph = UndirectedPayloadGraph::try_from_edges(nodes, edges)?;
65 Ok(FrozenUndirectedPayloadGraph {
66 graph,
67 indices: PayloadFreezeMap::from_slots(node_map, edge_map),
68 })
69 }
70}
71
72fn compact_node(count: usize) -> Result<NodeIndex> {
73 Ok(NodeIndex::new(u32::try_from(count).map_err(|_| {
74 crate::GraphError::IndexCapacityExceeded {
75 category: "frozen undirected nodes",
76 count,
77 }
78 })?))
79}
80
81fn compact_edge(count: usize) -> Result<EdgeIndex> {
82 Ok(EdgeIndex::new(u32::try_from(count).map_err(|_| {
83 crate::GraphError::IndexCapacityExceeded {
84 category: "frozen undirected edges",
85 count,
86 }
87 })?))
88}