god_graph/graph/
builders.rs1use crate::errors::{GraphError, GraphResult};
6use crate::graph::traits::GraphOps;
7use crate::graph::Graph;
8
9pub struct GraphBuilder<T, E> {
13 graph: Graph<T, E>,
14 nodes: Vec<T>,
15 edges: Vec<(usize, usize, E)>,
16}
17
18impl<T, E> GraphBuilder<T, E>
19where
20 T: Clone,
21 E: Clone,
22{
23 pub fn directed() -> Self {
25 Self {
26 graph: Graph::directed(),
27 nodes: Vec::new(),
28 edges: Vec::new(),
29 }
30 }
31
32 pub fn undirected() -> Self {
34 Self {
35 graph: Graph::undirected(),
36 nodes: Vec::new(),
37 edges: Vec::new(),
38 }
39 }
40
41 pub fn with_node(mut self, data: T) -> Self {
43 self.nodes.push(data);
44 self
45 }
46
47 pub fn with_nodes<I>(mut self, iter: I) -> Self
49 where
50 I: IntoIterator<Item = T>,
51 {
52 self.nodes.extend(iter);
53 self
54 }
55
56 pub fn with_edge(mut self, from: usize, to: usize, data: E) -> Self {
58 self.edges.push((from, to, data));
59 self
60 }
61
62 pub fn with_edges<I>(mut self, iter: I) -> Self
64 where
65 I: IntoIterator<Item = (usize, usize, E)>,
66 {
67 self.edges.extend(iter);
68 self
69 }
70
71 pub fn build(mut self) -> GraphResult<Graph<T, E>> {
73 let mut node_indices = Vec::with_capacity(self.nodes.len());
75 for data in self.nodes {
76 let idx = self.graph.add_node(data)?;
77 node_indices.push(idx);
78 }
79
80 for (from, to, data) in self.edges {
82 if from >= node_indices.len() || to >= node_indices.len() {
83 return Err(GraphError::IndexOutOfBounds {
84 index: from.max(to),
85 bound: node_indices.len(),
86 });
87 }
88 self.graph
89 .add_edge(node_indices[from], node_indices[to], data)?;
90 }
91
92 Ok(self.graph)
93 }
94}
95
96impl<T, E> Default for GraphBuilder<T, E>
97where
98 T: Clone,
99 E: Clone,
100{
101 fn default() -> Self {
102 Self::directed()
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::graph::traits::GraphBase;
110
111 #[test]
112 fn test_builder_basic() {
113 let graph = GraphBuilder::directed()
114 .with_node("A")
115 .with_node("B")
116 .with_node("C")
117 .with_edge(0, 1, 1.0)
118 .with_edge(1, 2, 2.0)
119 .build()
120 .unwrap();
121
122 assert_eq!(graph.node_count(), 3);
123 assert_eq!(graph.edge_count(), 2);
124 }
125
126 #[test]
127 fn test_builder_with_nodes() {
128 let graph: Graph<i32, f64> = GraphBuilder::directed()
129 .with_nodes(vec![1, 2, 3, 4])
130 .build()
131 .unwrap();
132
133 assert_eq!(graph.node_count(), 4);
134 }
135
136 #[test]
137 fn test_builder_with_edges() {
138 use crate::graph::traits::GraphBase;
139
140 let graph = GraphBuilder::directed()
141 .with_nodes(vec!["A", "B", "C"])
142 .with_edges(vec![(0, 1, 1.0), (1, 2, 2.0), (0, 2, 3.0)])
143 .build()
144 .unwrap();
145
146 assert_eq!(graph.node_count(), 3);
147 assert_eq!(graph.edge_count(), 3);
148 }
149}