god_gragh/graph/
traits.rs1use crate::edge::{EdgeIndex, EdgeRef};
6use crate::node::{NodeIndex, NodeRef};
7use crate::errors::{GraphError, GraphResult};
8
9pub trait GraphBase {
13 type NodeData;
15 type EdgeData;
17
18 fn node_count(&self) -> usize;
20
21 fn edge_count(&self) -> usize;
23
24 fn is_empty(&self) -> bool {
26 self.node_count() == 0
27 }
28
29 fn contains_node(&self, index: NodeIndex) -> bool;
31
32 fn contains_edge(&self, index: EdgeIndex) -> bool;
34}
35
36pub trait GraphQuery: GraphBase {
40 fn get_node(&self, index: NodeIndex) -> GraphResult<&Self::NodeData>;
42
43 fn get_edge(&self, index: EdgeIndex) -> GraphResult<&Self::EdgeData>;
45
46 fn edge_endpoints(&self, index: EdgeIndex) -> GraphResult<(NodeIndex, NodeIndex)>;
48
49 fn neighbors(&self, node: NodeIndex) -> impl Iterator<Item = NodeIndex>;
51
52 fn incident_edges(&self, node: NodeIndex) -> impl Iterator<Item = EdgeIndex>;
54
55 fn has_edge(&self, from: NodeIndex, to: NodeIndex) -> bool;
57
58 fn out_degree(&self, node: NodeIndex) -> GraphResult<usize>;
60
61 fn in_degree(&self, node: NodeIndex) -> GraphResult<usize> {
63 self.out_degree(node)
64 }
65
66 fn degree(&self, node: NodeIndex) -> GraphResult<usize> {
68 self.out_degree(node)
69 }
70
71 fn nodes(&self) -> impl Iterator<Item = NodeRef<'_, Self::NodeData>>;
73
74 fn edges(&self) -> impl Iterator<Item = EdgeRef<'_, Self::EdgeData>>;
76}
77
78pub trait GraphOps: GraphBase {
82 fn add_node(&mut self, data: Self::NodeData) -> GraphResult<NodeIndex>;
84
85 fn remove_node(&mut self, index: NodeIndex) -> GraphResult<Self::NodeData>;
87
88 fn add_edge(
90 &mut self,
91 from: NodeIndex,
92 to: NodeIndex,
93 data: Self::EdgeData,
94 ) -> GraphResult<EdgeIndex>;
95
96 fn remove_edge(&mut self, index: EdgeIndex) -> GraphResult<Self::EdgeData>;
98
99 fn update_node(
101 &mut self,
102 index: NodeIndex,
103 data: Self::NodeData,
104 ) -> GraphResult<Self::NodeData>;
105
106 fn update_edge(
108 &mut self,
109 index: EdgeIndex,
110 data: Self::EdgeData,
111 ) -> GraphResult<Self::EdgeData>;
112
113 fn clear(&mut self);
115
116 fn reserve(&mut self, additional_nodes: usize, additional_edges: usize);
118}
119
120#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
122pub enum Direction {
123 Outgoing,
125 Incoming,
127}
128
129impl Direction {
130 #[inline]
132 pub fn opposite(self) -> Self {
133 match self {
134 Direction::Outgoing => Direction::Incoming,
135 Direction::Incoming => Direction::Outgoing,
136 }
137 }
138
139 #[inline]
141 pub fn is_outgoing(self) -> bool {
142 matches!(self, Direction::Outgoing)
143 }
144
145 #[inline]
147 pub fn is_incoming(self) -> bool {
148 matches!(self, Direction::Incoming)
149 }
150}
151
152#[inline]
156pub fn validate_node_index(provided: NodeIndex, current_generation: u32) -> GraphResult<()> {
157 if provided.generation() == current_generation {
158 Ok(())
159 } else {
160 Err(GraphError::NodeDeleted {
161 index: provided.index(),
162 provided: provided.generation(),
163 current: current_generation,
164 })
165 }
166}
167
168#[inline]
172pub fn validate_edge_index(provided: EdgeIndex, current_generation: u32) -> GraphResult<()> {
173 if provided.generation() == current_generation {
174 Ok(())
175 } else {
176 Err(GraphError::EdgeDeleted {
177 index: provided.index(),
178 provided: provided.generation(),
179 current: current_generation,
180 })
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_direction() {
190 assert_eq!(Direction::Outgoing.opposite(), Direction::Incoming);
191 assert_eq!(Direction::Incoming.opposite(), Direction::Outgoing);
192 assert!(Direction::Outgoing.is_outgoing());
193 assert!(Direction::Incoming.is_incoming());
194 }
195}