weavatrix_graph/graph/
builder.rs1use super::core::Graph;
2use super::index::canonicalize_edges;
3use super::validate::{validate_edge, validate_node};
4use crate::{Edge, GraphError, Node, NodeId, Result};
5use crate::{ToString, Vec};
6#[cfg(not(feature = "std"))]
7use alloc::collections::BTreeMap as NodeMap;
8#[cfg(feature = "std")]
9use std::collections::HashMap as NodeMap;
10
11#[derive(Debug, Default)]
12pub struct GraphBuilder {
13 nodes: NodeMap<NodeId, Node>,
14 edges: Vec<Edge>,
15}
16
17#[cfg(feature = "std")]
18fn node_map_with_capacity(capacity: usize) -> NodeMap<NodeId, Node> {
19 NodeMap::with_capacity(capacity)
20}
21
22#[cfg(not(feature = "std"))]
23fn node_map_with_capacity(_: usize) -> NodeMap<NodeId, Node> {
24 NodeMap::new()
25}
26
27impl GraphBuilder {
28 #[must_use]
29 pub fn new() -> Self {
30 Self {
31 nodes: NodeMap::new(),
32 edges: Vec::new(),
33 }
34 }
35
36 #[must_use]
38 pub fn with_capacity(nodes: usize, edges: usize) -> Self {
39 Self {
40 nodes: node_map_with_capacity(nodes),
41 edges: Vec::with_capacity(edges),
42 }
43 }
44
45 pub fn add_node(&mut self, node: Node) -> Result<&mut Self> {
52 validate_node(&node)?;
53 if let Some(existing) = self.nodes.get(&node.id) {
54 if existing == &node {
55 return Ok(self);
56 }
57 return Err(GraphError::ConflictingNode {
58 id: node.id.to_string(),
59 });
60 }
61 self.nodes.insert(node.id.clone(), node);
62 Ok(self)
63 }
64
65 pub fn add_edge(&mut self, edge: Edge) -> Result<&mut Self> {
72 validate_edge(&edge)?;
73 self.edges.push(edge);
74 Ok(self)
75 }
76
77 pub fn build(self) -> Result<Graph> {
83 let mut nodes = self.nodes.into_values().collect::<Vec<_>>();
84 nodes.sort_unstable_by(|left, right| left.id.cmp(&right.id));
85 let (edges, topology) = canonicalize_edges(&nodes, self.edges)?;
86 Ok(Graph::from_indexed_parts(nodes, edges, topology))
87 }
88}