graph_core/
graph.rs

1use crate::{Edge, NodeId};
2
3/// The central graph abstraction that every algorithm in graph-rs operates on.
4///
5/// `N` is the node-data type and `W` is the edge-weight type.
6///
7/// Implementors provide two associated iterator types — `NodeIter<'a>` and
8/// `NeighborIter<'a>` — that borrow from `&self`. These are **Generic
9/// Associated Types** (GATs, stable since Rust 1.65): associated types that
10/// are themselves generic over a lifetime, enabling zero-allocation iterators
11/// that reference graph internals directly.
12///
13/// # Implementing `Graph`
14///
15/// ```ignore
16/// use graph_core::{Graph, NodeId, Edge};
17///
18/// struct MyGraph { /* ... */ }
19///
20/// impl Graph for MyGraph {
21///     type NodeData = String;
22///     type Weight   = f64;
23///     // ... (see AdjacencyList for a complete example)
24/// }
25/// ```
26pub trait Graph {
27    /// Data stored at each node (e.g. `String`, `()`, coordinates).
28    type NodeData;
29
30    /// Edge-weight type (e.g. `f64`, `u32`, `()`).
31    type Weight;
32
33    /// Iterator over all [`NodeId`]s in the graph.
34    type NodeIter<'a>: Iterator<Item = NodeId>
35    where
36        Self: 'a;
37
38    /// Iterator over `(neighbour_id, &weight)` pairs for one node.
39    type NeighborIter<'a>: Iterator<Item = (NodeId, &'a Self::Weight)>
40    where
41        Self: 'a;
42
43    // ── Mutation ──────────────────────────────────────────────────────────────
44
45    /// Adds a node with the given data and returns its [`NodeId`].
46    fn add_node(&mut self, data: Self::NodeData) -> NodeId;
47
48    /// Adds a directed edge from `from` to `to` with `weight`.
49    ///
50    /// # Errors
51    ///
52    /// Returns [`GraphError`](crate::GraphError) if either node does not exist.
53    fn add_edge(
54        &mut self,
55        from: NodeId,
56        to: NodeId,
57        weight: Self::Weight,
58    ) -> Result<(), crate::GraphError>;
59
60    /// Removes the node at `id` and all edges incident to it.
61    ///
62    /// Returns the node data if found, or `None` if the node did not exist.
63    fn remove_node(&mut self, id: NodeId) -> Option<Self::NodeData>;
64
65    // ── Query ─────────────────────────────────────────────────────────────────
66
67    /// Returns the number of nodes.
68    fn node_count(&self) -> usize;
69
70    /// Returns the number of directed edges.
71    fn edge_count(&self) -> usize;
72
73    /// Returns `true` if the graph contains a node with this id.
74    fn contains_node(&self, id: NodeId) -> bool;
75
76    /// Returns `true` if there is a directed edge from `from` to `to`.
77    fn contains_edge(&self, from: NodeId, to: NodeId) -> bool;
78
79    /// Returns the out-degree of node `id` (number of outgoing edges).
80    ///
81    /// # Panics
82    ///
83    /// Panics if `id` does not exist in the graph.
84    fn degree(&self, id: NodeId) -> usize;
85
86    // ── Iteration ─────────────────────────────────────────────────────────────
87
88    /// Returns an iterator over all [`NodeId`]s in the graph.
89    fn nodes(&self) -> Self::NodeIter<'_>;
90
91    /// Returns an iterator over `(neighbour_id, &weight)` for all outgoing
92    /// edges of `id`.
93    ///
94    /// # Panics
95    ///
96    /// Panics if `id` does not exist in the graph.
97    fn neighbors(&self, id: NodeId) -> Self::NeighborIter<'_>;
98
99    // ── Provided helpers ──────────────────────────────────────────────────────
100
101    /// Returns all edges in the graph as [`Edge<W>`] values.
102    ///
103    /// Default implementation iterates over all nodes and their neighbours.
104    /// Implementations may override this for efficiency.
105    fn all_edges(&self) -> Vec<Edge<Self::Weight>>
106    where
107        Self::Weight: Clone,
108    {
109        let mut edges = Vec::new();
110        for u in self.nodes() {
111            for (v, w) in self.neighbors(u) {
112                edges.push(Edge::new(u, v, w.clone()));
113            }
114        }
115        edges
116    }
117
118    /// Returns `true` if the graph has no nodes.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// use graph_core::{AdjacencyList, Graph};
124    ///
125    /// let g: AdjacencyList<()> = AdjacencyList::directed();
126    /// assert!(g.is_empty());
127    /// ```
128    #[inline]
129    fn is_empty(&self) -> bool {
130        self.node_count() == 0
131    }
132}