Skip to content

Commit 0773c2c

Browse files
patowenRalith
authored andcommitted
Ensure peer_traverser does not unnecessarily expand the graph
1 parent 0dccd63 commit 0773c2c

1 file changed

Lines changed: 55 additions & 28 deletions

File tree

common/src/peer_traverser.rs

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,16 @@ fn peer_nodes_impl(mut graph: impl GraphRef, base_node: NodeId) -> Vec<PeerNode>
2626
let mut nodes = Vec::new();
2727

2828
// Depth 1 paths
29-
for parent_side in Side::iter() {
30-
let parent_node = graph.neighbor(base_node, parent_side);
31-
if graph.depth(parent_node) >= graph.depth(base_node) {
32-
continue;
33-
}
29+
for (parent_side, parent_node) in graph.parents(base_node) {
3430
for &child_side in &DEPTH1_CHILD_PATHS[parent_side as usize] {
35-
let peer_node = graph.neighbor(parent_node, child_side);
36-
if graph.depth(peer_node) == graph.depth(base_node) {
37-
nodes.push(PeerNode {
38-
node_id: peer_node,
39-
parent_path: ArrayVec::from_iter([parent_side]),
40-
child_path: ArrayVec::from_iter([child_side]),
41-
});
42-
}
31+
let Some(peer_node) = graph.child(parent_node, child_side) else {
32+
continue;
33+
};
34+
nodes.push(PeerNode {
35+
node_id: peer_node,
36+
parent_path: ArrayVec::from_iter([parent_side]),
37+
child_path: ArrayVec::from_iter([child_side]),
38+
});
4339
}
4440
}
4541

@@ -53,15 +49,17 @@ fn peer_nodes_impl(mut graph: impl GraphRef, base_node: NodeId) -> Vec<PeerNode>
5349
continue;
5450
}
5551
for &child_sides in &DEPTH2_CHILD_PATHS[parent_side0 as usize][parent_side1 as usize] {
56-
let peer_node_parent = graph.neighbor(parent_node1, child_sides[0]);
57-
let peer_node = graph.neighbor(peer_node_parent, child_sides[1]);
58-
if graph.depth(peer_node) == graph.depth(base_node) {
59-
nodes.push(PeerNode {
60-
node_id: peer_node,
61-
parent_path: ArrayVec::from_iter([parent_side0, parent_side1]),
62-
child_path: ArrayVec::from_iter(child_sides),
63-
});
64-
}
52+
let Some(peer_node_parent) = graph.child(parent_node1, child_sides[0]) else {
53+
continue;
54+
};
55+
let Some(peer_node) = graph.child(peer_node_parent, child_sides[1]) else {
56+
continue;
57+
};
58+
nodes.push(PeerNode {
59+
node_id: peer_node,
60+
parent_path: ArrayVec::from_iter([parent_side0, parent_side1]),
61+
child_path: ArrayVec::from_iter(child_sides),
62+
});
6563
}
6664
}
6765
}
@@ -168,6 +166,16 @@ trait GraphRef: AsRef<Graph> {
168166
fn depth(&self, node: NodeId) -> u32;
169167
fn neighbor(&mut self, node: NodeId, side: Side) -> NodeId;
170168
fn parents(&self, node: NodeId) -> impl ExactSizeIterator<Item = (Side, NodeId)> + use<Self>;
169+
170+
/// A helper function that returns the node at the particular side if it's a child, or `None` if it's a parent.
171+
fn child(&mut self, node: NodeId, side: Side) -> Option<NodeId> {
172+
let candidate_child = self.neighbor(node, side);
173+
if self.depth(candidate_child) > self.depth(node) {
174+
Some(candidate_child)
175+
} else {
176+
None
177+
}
178+
}
171179
}
172180

173181
/// A `GraphRef` that asserts that all the nodes it needs already exist
@@ -242,11 +250,8 @@ mod tests {
242250
#[test]
243251
fn peer_traverser_example() {
244252
let mut graph = Graph::new(1);
245-
let base_node = node_from_path(
246-
&mut graph,
247-
NodeId::ROOT,
248-
[Side::B, Side::D, Side::C, Side::A],
249-
);
253+
let base_node_path = [Side::B, Side::D, Side::C, Side::A];
254+
let base_node = node_from_path(&mut graph, NodeId::ROOT, base_node_path);
250255

251256
let expected_paths: &[(&[Side], &[Side])] = &[
252257
(&[Side::A], &[Side::B]),
@@ -265,7 +270,7 @@ mod tests {
265270

266271
let peers = ensure_peer_nodes(&mut graph, base_node);
267272
assert_eq!(peers.len(), expected_paths.len());
268-
for (peer, expected_path) in peers.into_iter().zip(expected_paths) {
273+
for (peer, expected_path) in peers.iter().zip(expected_paths) {
269274
assert_eq!(
270275
peer.peer_to_shared().collect::<Vec<_>>(),
271276
expected_path.0.to_vec(),
@@ -275,6 +280,28 @@ mod tests {
275280
expected_path.1.to_vec(),
276281
);
277282
}
283+
284+
// Assert that the graph isn't expanded any more than necessary by generating
285+
// a reference graph with the same base node and peer nodes manually.
286+
let mut reference_graph = Graph::new(1);
287+
assert_eq!(
288+
base_node,
289+
node_from_path(&mut reference_graph, NodeId::ROOT, base_node_path),
290+
"Sanity check for reusing base_node"
291+
);
292+
for peer in &peers {
293+
// Generate the peer node by taking the path from the base node to the peer node via their shared parent.
294+
node_from_path(
295+
&mut reference_graph,
296+
base_node,
297+
peer.parent_path
298+
.iter()
299+
.cloned()
300+
.chain(peer.child_path.iter().cloned()),
301+
);
302+
}
303+
304+
assert_eq!(graph.len(), reference_graph.len());
278305
}
279306

280307
#[test]

0 commit comments

Comments
 (0)