Skip to main content

jstd/graph/
node.rs

1//! Node views and traversal iterators for the graph.
2
3use std::{collections::HashSet, marker::PhantomData};
4
5use crate::graph::{Graph, edge::Edge};
6
7pub trait Node<'graph> {
8    type Graph: Graph;
9
10    fn new(id: <Self::Graph as Graph>::NodeId, graph: &'graph Self::Graph) -> Self;
11
12    /// Returns this node identifier.
13    fn id(&self) -> <Self::Graph as Graph>::NodeId;
14
15    /// Returns the backing graph reference for this node.
16    fn graph(&self) -> &'graph Self::Graph;
17
18    /// Retrieve the ids of all edges incident to this node.
19    fn edge_ids(
20        &self,
21    ) -> &'graph HashSet<<Self::Graph as Graph>::EdgeId, <Self::Graph as Graph>::Hasher>;
22
23    /// Returns the number of incident edges for this node.
24    fn edge_count(&self) -> usize;
25
26    /// Returns `true` if this node has no connected edges.
27    fn is_leaf(&self) -> bool {
28        self.edge_count() == 0
29    }
30
31    /// Iterates over all incident edges.
32    fn edges(&self) -> Iter<'graph, EdgeMode, Self::Graph> {
33        Iter {
34            graph: self.graph(),
35            node: self.id(),
36            iter: self.edge_ids().iter(),
37            _mode: PhantomData,
38        }
39    }
40
41    /// Iterates over child relationships for outgoing edges.
42    fn children(&self) -> Iter<'graph, ChildMode, Self::Graph> {
43        Iter {
44            graph: self.graph(),
45            node: self.id(),
46            iter: self.edge_ids().iter(),
47            _mode: PhantomData,
48        }
49    }
50
51    /// Iterates over parent relationships for incoming edges.
52    fn parents(&self) -> Iter<'graph, ParentMode, Self::Graph> {
53        Iter {
54            graph: self.graph(),
55            node: self.id(),
56            iter: self.edge_ids().iter(),
57            _mode: PhantomData,
58        }
59    }
60}
61
62pub trait NodeMut<'graph> {
63    type Graph: Graph;
64
65    fn new(id: <Self::Graph as Graph>::NodeId, graph: &'graph mut Self::Graph) -> Self;
66
67    /// Returns this node identifier.
68    fn id(&self) -> <Self::Graph as Graph>::NodeId;
69
70    /// Returns the backing graph reference for this node.
71    fn graph(&mut self) -> &mut Self::Graph;
72
73    /// Retrieve the ids of all edges incident to this node.
74    fn edge_ids(&self) -> &HashSet<<Self::Graph as Graph>::EdgeId, <Self::Graph as Graph>::Hasher>;
75
76    /// Returns the number of incident edges for this node.
77    fn edge_count(&self) -> usize;
78
79    /// Registers an edge as incident to this node.
80    fn add_edge_id(&mut self, edge: <Self::Graph as Graph>::EdgeId);
81
82    /// Removes an edge from this node's incident edge set.
83    fn remove_edge_id(&mut self, edge: <Self::Graph as Graph>::EdgeId);
84
85    /// Returns a "weaker" immutable view of this mutable node handle.
86    fn as_ref<'a>(&'a mut self) -> <Self::Graph as Graph>::Node<'a>
87    where
88        'graph: 'a,
89    {
90        <Self::Graph as Graph>::Node::new(self.id(), &*self.graph())
91    }
92}
93
94/// One traversal item containing both edge and opposite-node information.
95pub struct EdgeItem<'graph, G: Graph> {
96    pub(crate) graph: &'graph G,
97    pub(crate) edge: G::EdgeId,
98    pub(crate) node: G::NodeId,
99}
100
101impl<'graph, G: Graph> EdgeItem<'graph, G> {
102    /// Returns the traversed edge identifier.
103    pub fn edge_id(&self) -> G::EdgeId {
104        self.edge
105    }
106
107    /// Returns the opposite-node identifier for this traversal step.
108    pub fn node_id(&self) -> G::NodeId {
109        self.node
110    }
111
112    /// Returns the opposite node handle for this traversal step.
113    pub fn node(&self) -> G::Node<'graph> {
114        <G as Graph>::Node::new(self.node, self.graph)
115    }
116
117    /// Returns the traversed edge handle for this step.
118    pub fn edge(&self) -> G::Edge<'graph> {
119        <G as Graph>::Edge::new(self.edge, self.graph)
120    }
121}
122
123/// Iterator mode selecting outgoing child traversal.
124pub struct ChildMode;
125
126/// Iterator mode selecting incoming parent traversal.
127pub struct ParentMode;
128
129/// Iterator mode selecting all incident edges.
130pub struct EdgeMode;
131
132/// Traversal iterator over node relationships.
133pub struct Iter<'graph, Mode, G: Graph> {
134    graph: &'graph G,
135    node: G::NodeId,
136    iter: std::collections::hash_set::Iter<'graph, G::EdgeId>,
137    _mode: PhantomData<Mode>,
138}
139
140impl<'graph, G: Graph> Iterator for Iter<'graph, ChildMode, G> {
141    type Item = EdgeItem<'graph, G>;
142
143    fn next(&mut self) -> Option<Self::Item> {
144        for &id in self.iter.by_ref() {
145            let edge = <G as Graph>::Edge::new(id, self.graph);
146
147            if self.node == edge.from_id() {
148                return Some(EdgeItem {
149                    graph: self.graph,
150                    edge: id,
151                    node: edge.to_id(),
152                });
153            }
154        }
155
156        None
157    }
158}
159
160impl<'graph, G: Graph> Iterator for Iter<'graph, ParentMode, G> {
161    type Item = EdgeItem<'graph, G>;
162
163    fn next(&mut self) -> Option<Self::Item> {
164        for id in self.iter.by_ref() {
165            let edge = <G as Graph>::Edge::new(*id, self.graph);
166
167            if self.node == edge.to_id() {
168                return Some(EdgeItem {
169                    graph: self.graph,
170                    edge: *id,
171                    node: edge.from_id(),
172                });
173            }
174        }
175
176        None
177    }
178}
179
180impl<'graph, G: Graph> Iterator for Iter<'graph, EdgeMode, G> {
181    type Item = EdgeItem<'graph, G>;
182
183    fn next(&mut self) -> Option<Self::Item> {
184        self.iter.next().map(|&id| {
185            let edge = <G as Graph>::Edge::new(id, self.graph);
186            let other_node = if self.node == edge.from_id() {
187                edge.to_id()
188            } else {
189                edge.from_id()
190            };
191
192            EdgeItem {
193                graph: self.graph,
194                edge: id,
195                node: other_node,
196            }
197        })
198    }
199}