1use std::collections::{BTreeMap, BTreeSet};
2
3use crate::edge::Edge;
4use crate::error::GraphError;
5use crate::node::{Node, NodeId};
6
7#[derive(Debug, Default, Clone, PartialEq, Eq)]
17pub struct Graph {
18 nodes: BTreeMap<NodeId, Node>,
19 edges: BTreeSet<Edge>,
20}
21
22impl Graph {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn add_node(&mut self, node: Node) -> Result<(), GraphError> {
28 let empty = |field| GraphError::EmptyField {
29 id: node.id.clone(),
30 field,
31 };
32 if node.id.as_str().is_empty() {
33 return Err(empty("id"));
34 }
35 if node.name.is_empty() {
36 return Err(empty("name"));
37 }
38 if node.file.is_empty() {
39 return Err(empty("file"));
40 }
41 if node.span.end <= node.span.start {
42 return Err(GraphError::InvalidSpan {
43 id: node.id.clone(),
44 start: node.span.start,
45 end: node.span.end,
46 });
47 }
48 if self.nodes.contains_key(&node.id) {
49 return Err(GraphError::DuplicateNode(node.id));
50 }
51 self.nodes.insert(node.id.clone(), node);
52 Ok(())
53 }
54
55 pub fn add_edge(&mut self, edge: Edge) -> Result<(), GraphError> {
56 if !self.nodes.contains_key(&edge.src) {
57 return Err(GraphError::MissingEndpoint(edge.src));
58 }
59 if !self.nodes.contains_key(&edge.dst) {
60 return Err(GraphError::MissingEndpoint(edge.dst));
61 }
62 self.edges.insert(edge);
63 Ok(())
64 }
65
66 pub fn node(&self, id: &NodeId) -> Option<&Node> {
67 self.nodes.get(id)
68 }
69
70 pub fn nodes(&self) -> impl Iterator<Item = &Node> {
71 self.nodes.values()
72 }
73
74 pub fn edges(&self) -> impl Iterator<Item = &Edge> {
75 self.edges.iter()
76 }
77
78 pub fn edges_from<'a>(&'a self, id: &'a NodeId) -> impl Iterator<Item = &'a Edge> {
81 self.edges.iter().filter(move |e| &e.src == id)
82 }
83
84 pub fn edges_to<'a>(&'a self, id: &'a NodeId) -> impl Iterator<Item = &'a Edge> {
85 self.edges.iter().filter(move |e| &e.dst == id)
86 }
87
88 pub fn node_count(&self) -> usize {
89 self.nodes.len()
90 }
91
92 pub fn edge_count(&self) -> usize {
93 self.edges.len()
94 }
95}