1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::fmt;
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8#[serde(tag = "type", rename = "Vertex")]
9pub struct Vertex {
10 pub guid: String,
12 pub name: String,
14 pub attribute: String,
16 pub index: i32,
18}
19
20impl Default for Vertex {
21 fn default() -> Self {
22 Self {
23 name: "my_vertex".to_string(),
24 guid: Uuid::new_v4().to_string(),
25 attribute: String::new(),
26 index: -1,
27 }
28 }
29}
30
31impl fmt::Display for Graph {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(
34 f,
35 "Graph({}, {}, vertices={}, edges={})",
36 self.name, self.guid, self.vertex_count, self.edge_count
37 )
38 }
39}
40
41impl fmt::Display for Vertex {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(
44 f,
45 "Vertex({}, {}, attr={}, index={})",
46 self.name, self.guid, self.attribute, self.index
47 )
48 }
49}
50
51impl fmt::Display for Edge {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(
54 f,
55 "Edge({}, {}, {} -> {}, attr={}, index={})",
56 self.name, self.guid, self.v0, self.v1, self.attribute, self.index
57 )
58 }
59}
60
61impl Vertex {
62 pub fn new(name: Option<String>, attribute: Option<String>) -> Self {
64 Self {
65 name: name.unwrap_or_default(),
66 attribute: attribute.unwrap_or_default(),
67 ..Default::default()
68 }
69 }
70
71 pub fn jsondump(&self) -> Result<String, Box<dyn std::error::Error>> {
77 Ok(serde_json::to_string_pretty(self)?)
78 }
79
80 pub fn jsonload(json_data: &str) -> Result<Self, Box<dyn std::error::Error>> {
82 Ok(serde_json::from_str(json_data)?)
83 }
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88#[serde(tag = "type", rename = "Edge")]
89pub struct Edge {
90 pub guid: String,
92 pub name: String,
94 pub v0: String,
96 pub v1: String,
98 pub attribute: String,
100 pub index: i32,
102}
103
104impl Default for Edge {
105 fn default() -> Self {
106 Self {
107 name: "my_edge".to_string(),
108 guid: Uuid::new_v4().to_string(),
109 v0: String::new(),
110 v1: String::new(),
111 attribute: String::new(),
112 index: -1,
113 }
114 }
115}
116
117impl Edge {
118 pub fn new(
120 name: Option<String>,
121 v0: Option<String>,
122 v1: Option<String>,
123 attribute: Option<String>,
124 ) -> Self {
125 Self {
126 name: name.unwrap_or_default(),
127 v0: v0.unwrap_or_default(),
128 v1: v1.unwrap_or_default(),
129 attribute: attribute.unwrap_or_default(),
130 ..Default::default()
131 }
132 }
133
134 pub fn jsondump(&self) -> Result<String, Box<dyn std::error::Error>> {
140 Ok(serde_json::to_string_pretty(self)?)
141 }
142
143 pub fn jsonload(json_data: &str) -> Result<Self, Box<dyn std::error::Error>> {
145 Ok(serde_json::from_str(json_data)?)
146 }
147
148 pub fn vertices(&self) -> (String, String) {
150 (self.v0.clone(), self.v1.clone())
151 }
152
153 pub fn connects(&self, vertex_id: &str) -> bool {
155 self.v0 == vertex_id || self.v1 == vertex_id
156 }
157
158 pub fn other_vertex(&self, vertex_id: &str) -> String {
160 if self.v0 == vertex_id {
161 self.v1.clone()
162 } else {
163 self.v0.clone()
164 }
165 }
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169#[serde(tag = "type", rename = "Graph")]
170pub struct Graph {
171 pub guid: String,
173 pub name: String,
174 pub vertex_count: i32,
175 pub edge_count: i32,
176
177 vertices: HashMap<String, Vertex>,
180 edges: HashMap<String, HashMap<String, Edge>>,
181}
182
183impl Default for Graph {
184 fn default() -> Self {
185 Self {
186 guid: Uuid::new_v4().to_string(),
187 name: "my_graph".to_string(),
188 vertex_count: 0,
189 edge_count: 0,
190 vertices: HashMap::new(),
191 edges: HashMap::new(),
192 }
193 }
194}
195
196impl Graph {
197 pub fn new(name: &str) -> Self {
199 Self {
200 name: name.to_string(),
201 ..Default::default()
202 }
203 }
204
205 pub fn has_node(&self, key: &str) -> bool {
207 self.vertices.contains_key(key)
208 }
209
210 pub fn add_node(&mut self, key: &str, attribute: &str) -> String {
212 if self.has_node(key) {
213 return self.vertices.get(key).unwrap().name.clone();
214 }
215
216 let mut vertex = Vertex::new(Some(key.to_string()), Some(attribute.to_string()));
217 vertex.index = self.vertices.len() as i32;
218 self.vertices.insert(key.to_string(), vertex.clone());
219 self.vertex_count = self.vertices.len() as i32;
220 vertex.name
221 }
222
223 pub fn add_edge(&mut self, u: &str, v: &str, attribute: &str) -> (String, String) {
225 if !self.has_node(u) {
227 self.add_node(u, "");
228 }
229 if !self.has_node(v) {
230 self.add_node(v, "");
231 }
232
233 if self.has_edge((u, v)) {
234 return (u.to_string(), v.to_string());
235 }
236
237 let mut edge = Edge::new(
238 Some("my_edge".to_string()),
239 Some(u.to_string()),
240 Some(v.to_string()),
241 Some(attribute.to_string()),
242 );
243 edge.index = self.edge_count;
244
245 self.edges
246 .entry(u.to_string())
247 .or_default()
248 .insert(v.to_string(), edge.clone());
249 self.edges
250 .entry(v.to_string())
251 .or_default()
252 .insert(u.to_string(), edge);
253
254 self.edge_count += 1;
255
256 (u.to_string(), v.to_string())
257 }
258
259 pub fn has_edge(&self, edge: (&str, &str)) -> bool {
261 let (u, v) = edge;
262 self.edges
263 .get(u)
264 .is_some_and(|neighbors| neighbors.contains_key(v))
265 }
266
267 pub fn number_of_vertices(&self) -> usize {
269 self.vertices.len()
270 }
271
272 pub fn number_of_edges(&self) -> usize {
274 let mut count = 0;
275 let mut seen = std::collections::HashSet::new();
276 for (u, neighbors) in &self.edges {
277 for v in neighbors.keys() {
278 let edge = if u < v {
279 (u.clone(), v.clone())
280 } else {
281 (v.clone(), u.clone())
282 };
283 if seen.insert(edge) {
284 count += 1;
285 }
286 }
287 }
288 count
289 }
290
291 pub fn get_vertices(&self) -> Vec<Vertex> {
293 self.vertices.values().cloned().collect()
294 }
295
296 pub fn get_edges(&self) -> Vec<(String, String)> {
298 let mut result = Vec::new();
299 let mut seen = std::collections::HashSet::new();
300 for (u, neighbors) in &self.edges {
301 for v in neighbors.keys() {
302 let edge = if u < v {
303 (u.clone(), v.clone())
304 } else {
305 (v.clone(), u.clone())
306 };
307 if seen.insert(edge.clone()) {
308 result.push(edge);
309 }
310 }
311 }
312 result
313 }
314
315 pub fn neighbors(&self, node: &str) -> Vec<String> {
317 self.edges
318 .get(node)
319 .map_or(Vec::new(), |neighbors| neighbors.keys().cloned().collect())
320 }
321
322 pub fn get_neighbors(&self, node: &str) -> Vec<String> {
324 self.neighbors(node)
325 }
326
327 pub fn remove_node(&mut self, key: &str) {
329 if !self.has_node(key) {
330 return;
331 }
332
333 if let Some(neighbors) = self.edges.remove(key) {
334 for neighbor_key in neighbors.keys() {
335 if let Some(neighbor_edges) = self.edges.get_mut(neighbor_key) {
336 neighbor_edges.remove(key);
337 }
338 }
339 }
340
341 self.vertices.remove(key);
342 self.vertex_count = self.vertices.len() as i32;
343 self.edge_count = self.number_of_edges() as i32;
344 }
345
346 pub fn remove_edge(&mut self, edge: (&str, &str)) {
348 let (u, v) = edge;
349 let mut edge_removed = false;
350
351 if let Some(neighbors) = self.edges.get_mut(u) {
352 if neighbors.remove(v).is_some() {
353 edge_removed = true;
354 }
355 }
356 if let Some(neighbors) = self.edges.get_mut(v) {
357 neighbors.remove(u);
358 }
359
360 if edge_removed {
361 self.edge_count = self.number_of_edges() as i32;
362 }
363 }
364
365 pub fn clear(&mut self) {
367 self.vertices.clear();
368 self.edges.clear();
369 self.vertex_count = 0;
370 self.edge_count = 0;
371 }
372
373 pub fn node_attribute(&mut self, node: &str, value: Option<&str>) -> Option<String> {
375 if !self.has_node(node) {
376 return None;
377 }
378 let vertex = self.vertices.get_mut(node).unwrap();
379 if let Some(val) = value {
380 vertex.attribute = val.to_string();
381 Some(vertex.attribute.clone())
382 } else {
383 Some(vertex.attribute.clone())
384 }
385 }
386
387 pub fn jsondump(&self) -> Result<String, serde_json::Error> {
393 let mut vertices: Vec<&Vertex> = self.vertices.values().collect();
395 vertices.sort_by_key(|v| v.index);
396
397 let mut edges = Vec::new();
399 let mut seen = std::collections::HashSet::new();
400 for (u, neighbors) in &self.edges {
401 for (v, edge) in neighbors {
402 let edge_tuple = if u < v { (u, v) } else { (v, u) };
403 if seen.insert(edge_tuple) {
404 edges.push(edge);
405 }
406 }
407 }
408 edges.sort_by_key(|e| e.index);
409
410 let json_obj = serde_json::json!({
411 "type": "Graph",
412 "name": self.name,
413 "guid": self.guid,
414 "vertices": vertices,
415 "edges": edges,
416 "vertex_count": self.vertex_count,
417 "edge_count": self.edge_count
418 });
419
420 serde_json::to_string_pretty(&json_obj)
421 }
422
423 pub fn jsonload(json_data: &str) -> Result<Self, serde_json::Error> {
425 let json_obj: serde_json::Value = serde_json::from_str(json_data)?;
426
427 let mut graph = Graph::new(json_obj["name"].as_str().unwrap_or("my_graph"));
428 graph.guid = json_obj["guid"].as_str().unwrap_or("").to_string();
429 graph.vertex_count = json_obj["vertex_count"].as_i64().unwrap_or(0) as i32;
430 graph.edge_count = json_obj["edge_count"].as_i64().unwrap_or(0) as i32;
431
432 if let Some(vertices_array) = json_obj["vertices"].as_array() {
434 for vertex_data in vertices_array {
435 let vertex: Vertex = serde_json::from_value(vertex_data.clone())?;
436 graph.vertices.insert(vertex.name.clone(), vertex);
437 }
438 }
439
440 if let Some(edges_array) = json_obj["edges"].as_array() {
442 for edge_data in edges_array {
443 let edge: Edge = serde_json::from_value(edge_data.clone())?;
444 let u = &edge.v0;
445 let v = &edge.v1;
446
447 graph
448 .edges
449 .entry(u.clone())
450 .or_default()
451 .insert(v.clone(), edge.clone());
452 graph
453 .edges
454 .entry(v.clone())
455 .or_default()
456 .insert(u.clone(), edge);
457 }
458 }
459
460 Ok(graph)
461 }
462
463 pub fn to_json(&self, filepath: &str) -> Result<(), Box<dyn std::error::Error>> {
465 let json_data = self.jsondump()?;
466 std::fs::write(filepath, json_data)?;
467 Ok(())
468 }
469
470 pub fn from_json(filepath: &str) -> Result<Self, Box<dyn std::error::Error>> {
472 let json_data = std::fs::read_to_string(filepath)?;
473 Self::jsonload(&json_data).map_err(|e| e.into())
474 }
475
476 pub fn edge_attribute(&mut self, u: &str, v: &str, value: Option<&str>) -> Option<String> {
478 if !self.has_edge((u, v)) {
479 return None;
480 }
481 if let Some(val) = value {
482 let new_attr = val.to_string();
483 if let Some(neighbors) = self.edges.get_mut(u) {
484 if let Some(edge) = neighbors.get_mut(v) {
485 edge.attribute = new_attr.clone();
486 }
487 }
488 if let Some(neighbors) = self.edges.get_mut(v) {
489 if let Some(edge) = neighbors.get_mut(u) {
490 edge.attribute = new_attr.clone();
491 }
492 }
493 Some(new_attr)
494 } else {
495 self.edges
496 .get(u)
497 .and_then(|neighbors| neighbors.get(v))
498 .map(|edge| edge.attribute.clone())
499 }
500 }
501}
502
503#[cfg(test)]
504#[path = "graph_test.rs"]
505mod graph_test;