diff --git a/Cargo.toml b/Cargo.toml index c7468ab..fe03555 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,6 @@ proptest = { version = "1.1.0", optional = true } rand = { version = "0.8.5", optional = true } petgraph = { version = "0.6.3", optional = true } delegate = "0.13.0" -context-iterators = "0.2.0" itertools = "0.13.0" [features] diff --git a/benches/benchmarks/portgraph.rs b/benches/benchmarks/portgraph.rs index c2404e0..0b4183f 100644 --- a/benches/benchmarks/portgraph.rs +++ b/benches/benchmarks/portgraph.rs @@ -27,7 +27,8 @@ fn remove_all_unordered(graph: &mut PortGraph) { } // Remove all remaining nodes while graph.node_count() > 0 { - graph.remove_node(graph.nodes_iter().next().unwrap()); + let next = graph.nodes_iter().next().unwrap(); + graph.remove_node(next); } } diff --git a/src/algorithms/post_order.rs b/src/algorithms/post_order.rs index ba2ab0a..4b2d65f 100644 --- a/src/algorithms/post_order.rs +++ b/src/algorithms/post_order.rs @@ -213,7 +213,7 @@ impl<'graph> Iterator for PostOrder<'graph> { if !self.visited.replace(next.index(), true) { // The node is visited for the first time. We leave the node on the stack and push // all of its neighbours in the traversal direction. - for port in self.graph.ports(next, self.direction).rev() { + for port in self.graph._ports(next, self.direction).rev() { if self.ignore_port(next, port) { continue; } diff --git a/src/multiportgraph.rs b/src/multiportgraph.rs index 17e7c67..0e160b4 100644 --- a/src/multiportgraph.rs +++ b/src/multiportgraph.rs @@ -5,12 +5,13 @@ mod iter; pub use self::iter::{ Neighbours, NodeConnections, NodeLinks, NodeSubports, Nodes, PortLinks, Ports, }; -use crate::portgraph::{NodePortOffsets, NodePorts, PortOperation}; +use crate::portgraph::PortOperation; use crate::view::{LinkMut, MultiMut, MultiView, PortMut}; use crate::{ Direction, LinkError, LinkView, NodeIndex, PortGraph, PortIndex, PortOffset, PortView, SecondaryMap, }; +use delegate::delegate; use bitvec::vec::BitVec; @@ -97,77 +98,6 @@ impl MultiPortGraph { } impl PortView for MultiPortGraph { - type Nodes<'a> = Nodes<'a> - where - Self: 'a; - - type Ports<'a> = Ports<'a> - where - Self: 'a; - - type NodePorts<'a> = NodePorts - where - Self: 'a; - - type NodePortOffsets<'a> = NodePortOffsets - where - Self: 'a; - - #[inline] - fn port_direction(&self, port: impl Into) -> Option { - self.graph.port_direction(port.into()) - } - - #[inline] - fn port_node(&self, port: impl Into) -> Option { - self.graph.port_node(port.into()) - } - - #[inline] - fn port_offset(&self, port: impl Into) -> Option { - self.graph.port_offset(port.into()) - } - - #[inline] - fn port_index(&self, node: NodeIndex, offset: PortOffset) -> Option { - self.graph.port_index(node, offset) - } - - #[inline] - fn ports(&self, node: NodeIndex, direction: Direction) -> Self::NodePorts<'_> { - self.graph.ports(node, direction) - } - - #[inline] - fn all_ports(&self, node: NodeIndex) -> Self::NodePorts<'_> { - self.graph.all_ports(node) - } - - #[inline] - fn input(&self, node: NodeIndex, offset: usize) -> Option { - self.graph.input(node, offset) - } - - #[inline] - fn output(&self, node: NodeIndex, offset: usize) -> Option { - self.graph.output(node, offset) - } - - #[inline] - fn num_ports(&self, node: NodeIndex, direction: Direction) -> usize { - self.graph.num_ports(node, direction) - } - - #[inline] - fn port_offsets(&self, node: NodeIndex, direction: Direction) -> Self::NodePortOffsets<'_> { - self.graph.port_offsets(node, direction) - } - - #[inline] - fn all_port_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_> { - self.graph.all_port_offsets(node) - } - #[inline] fn contains_node(&self, node: NodeIndex) -> bool { self.graph.contains_node(node) && !self.copy_node.get(node) @@ -197,18 +127,19 @@ impl PortView for MultiPortGraph { // addition to all the subports. self.graph.port_count() - self.subport_count - self.copy_node_count } + #[inline] - fn nodes_iter(&self) -> Self::Nodes<'_> { + fn nodes_iter(&self) -> impl Iterator + Clone { self::iter::Nodes { multigraph: self, - iter: self.graph.nodes_iter(), + iter: self.graph._nodes_iter(), len: self.node_count(), } } #[inline] - fn ports_iter(&self) -> Self::Ports<'_> { - Ports::new(self, self.graph.ports_iter()) + fn ports_iter(&self) -> impl Iterator + Clone { + Ports::new(self, self.graph._ports_iter()) } #[inline] @@ -222,9 +153,21 @@ impl PortView for MultiPortGraph { self.graph.port_capacity() - self.subport_count - self.copy_node_count } - #[inline] - fn node_port_capacity(&self, node: NodeIndex) -> usize { - self.graph.node_port_capacity(node) + delegate! { + to (self.graph) { + fn port_direction(&self, port: impl Into) -> Option; + fn port_node(&self, port: impl Into) -> Option; + fn port_offset(&self, port: impl Into) -> Option; + fn port_index(&self, node: NodeIndex, offset: PortOffset) -> Option; + fn ports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_ports(&self, node: NodeIndex) -> impl Iterator + Clone; + fn input(&self, node: NodeIndex, offset: usize) -> Option; + fn output(&self, node: NodeIndex, offset: usize) -> Option; + fn num_ports(&self, node: NodeIndex, direction: Direction) -> usize; + fn port_offsets(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_port_offsets(&self, node: NodeIndex) -> impl Iterator + Clone; + fn node_port_capacity(&self, node: NodeIndex) -> usize; + } } } @@ -236,7 +179,7 @@ impl PortMut for MultiPortGraph { fn remove_node(&mut self, node: NodeIndex) { debug_assert!(!self.copy_node.get(node)); - for port in self.graph.all_ports(node) { + for port in self.graph._all_ports(node) { if *self.multiport.get(port) { self.unlink_port(port); } @@ -316,58 +259,28 @@ impl PortMut for MultiPortGraph { impl LinkView for MultiPortGraph { type LinkEndpoint = SubportIndex; - type Neighbours<'a> = Neighbours<'a> - where - Self: 'a; - - type NodeConnections<'a> = NodeConnections<'a> - where - Self: 'a; - - type NodeLinks<'a> = NodeLinks<'a> - where - Self: 'a; - - type PortLinks<'a> = PortLinks<'a> - where - Self: 'a; - - #[inline] - fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> Self::NodeConnections<'_> { - NodeConnections::new(self, to, self.output_links(from)) - } - - #[inline] - fn port_links(&self, port: PortIndex) -> Self::PortLinks<'_> { - PortLinks::new(self, port) - } - - #[inline] - fn links(&self, node: NodeIndex, direction: Direction) -> Self::NodeLinks<'_> { - NodeLinks::new(self, self.ports(node, direction), 0..0) - } - - #[inline] - fn all_links(&self, node: NodeIndex) -> Self::NodeLinks<'_> { - let output_ports = self.graph.node_outgoing_ports(node); - NodeLinks::new(self, self.all_ports(node), output_ports) - } - - #[inline] - fn neighbours(&self, node: NodeIndex, direction: Direction) -> Self::Neighbours<'_> { - Neighbours::new(self, self.subports(node, direction), node, false) - } - - #[inline] - fn all_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_> { - Neighbours::new(self, self.all_subports(node), node, true) - } - #[inline] fn link_count(&self) -> usize { // Do not count the links between copy nodes and their main nodes. self.graph.link_count() - self.copy_node_count } + + delegate! { + to self { + #[call(_get_connections)] + fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> impl Iterator + Clone; + #[call(_port_links)] + fn port_links(&self, port: PortIndex) -> impl Iterator + Clone; + #[call(_links)] + fn links(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_links)] + fn all_links(&self, node: NodeIndex) -> impl Iterator + Clone; + #[call(_neighbours)] + fn neighbours(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_neighbours)] + fn all_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone; + } + } } impl LinkMut for MultiPortGraph { @@ -396,24 +309,19 @@ impl LinkMut for MultiPortGraph { } impl MultiView for MultiPortGraph { - type NodeSubports<'a> = NodeSubports<'a> - where - Self: 'a; - fn subport_link(&self, subport: SubportIndex) -> Option { let subport_index = self.get_subport_index(subport)?; let link = self.graph.port_link(subport_index)?; self.get_subport_from_index(link) } - #[inline] - fn subports(&self, node: NodeIndex, direction: Direction) -> Self::NodeSubports<'_> { - NodeSubports::new(self, self.graph.ports(node, direction)) - } - - #[inline] - fn all_subports(&self, node: NodeIndex) -> Self::NodeSubports<'_> { - NodeSubports::new(self, self.graph.all_ports(node)) + delegate! { + to self { + #[call(_subports)] + fn subports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_subports)] + fn all_subports(&self, node: NodeIndex) -> impl Iterator + Clone; + } } } @@ -459,7 +367,7 @@ impl MultiPortGraph { let link = self.graph.links(copy_node, dir).next(); let link = link.map(|(_, tgt)| self.get_subport_from_index(tgt).unwrap()); - let mut subports = self.graph.ports(copy_node, dir.reverse()); + let mut subports = self.graph._ports(copy_node, dir.reverse()); self.multiport.set(copy_port, false); self.multiport.set(main_node_port, false); self.copy_node.set(copy_node, false); @@ -583,8 +491,8 @@ impl MultiPortGraph { /// Returns the PortIndex from the main node that connects to this copy node. fn copy_node_main_port(&self, copy_node: NodeIndex) -> Option { debug_assert!(self.copy_node.get(copy_node)); - let mut incoming = self.graph.inputs(copy_node); - let mut outgoing = self.graph.outputs(copy_node); + let mut incoming = self.graph._inputs(copy_node); + let mut outgoing = self.graph._outputs(copy_node); let internal_copy_port = match (incoming.len(), outgoing.len()) { (1, 1) => { diff --git a/src/multiportgraph/iter.rs b/src/multiportgraph/iter.rs index 5ec5212..9e7a4a4 100644 --- a/src/multiportgraph/iter.rs +++ b/src/multiportgraph/iter.rs @@ -8,6 +8,71 @@ use super::{MultiPortGraph, SubportIndex}; use crate::portgraph::{self, NodePorts}; use crate::{Direction, LinkView, NodeIndex, PortIndex, PortOffset, PortView}; +/// Iterator methods for [`MultiPortGraph`] with concrete return types. +/// +/// Used internally by other iterator implementations to avoid the generic RPITIT return types. +impl MultiPortGraph { + #[inline] + /// Returns an iterator over every pair of matching ports connecting `from` + /// with `to`. + pub(crate) fn _get_connections(&self, from: NodeIndex, to: NodeIndex) -> NodeConnections { + NodeConnections::new(self, to, self._output_links(from)) + } + + /// Returns the port that the given `port` is linked to. + #[inline] + pub(crate) fn _port_links(&self, port: PortIndex) -> PortLinks { + PortLinks::new(self, port) + } + + /// Iterates over the connected links of the `node` in the given + /// `direction`. + #[inline] + pub(crate) fn _links(&self, node: NodeIndex, direction: Direction) -> NodeLinks { + NodeLinks::new(self, self.graph._ports(node, direction), 0..0) + } + + /// Iterates over the connected input and output links of the `node` in sequence. + #[inline] + pub(crate) fn _all_links(&self, node: NodeIndex) -> NodeLinks { + let output_ports = self.graph.node_outgoing_ports(node); + NodeLinks::new(self, self.graph._all_ports(node), output_ports) + } + + /// Iterates over the connected output links of the `node`. Shorthand for + /// [`LinkView::links`]. + #[must_use] + #[inline] + pub(crate) fn _output_links(&self, node: NodeIndex) -> NodeLinks { + self._links(node, Direction::Outgoing) + } + + /// Iterates over neighbour nodes in the given `direction`. + /// May contain duplicates if the graph has multiple links between nodes. + #[inline] + pub(crate) fn _neighbours(&self, node: NodeIndex, direction: Direction) -> Neighbours { + Neighbours::new(self, self._subports(node, direction), node, false) + } + + /// Iterates over the input and output neighbours of the `node` in sequence. + #[inline] + pub(crate) fn _all_neighbours(&self, node: NodeIndex) -> Neighbours { + Neighbours::new(self, self._all_subports(node), node, true) + } + + /// Iterates over all the subports of the `node` in the given `direction`. + #[inline] + pub(crate) fn _subports(&self, node: NodeIndex, direction: Direction) -> NodeSubports { + NodeSubports::new(self, self.graph._ports(node, direction)) + } + + /// Iterates over the input and output subports of the `node` in sequence. + #[inline] + pub(crate) fn _all_subports(&self, node: NodeIndex) -> NodeSubports { + NodeSubports::new(self, self.graph._all_ports(node)) + } +} + /// Iterator over the nodes of a graph. #[derive(Clone)] pub struct Nodes<'a> { @@ -105,7 +170,7 @@ impl<'a> Iterator for NodeSubports<'a> { self.current_subports = self .multigraph .graph - .port_offsets(copy_node, dir) + ._port_offsets(copy_node, dir) .as_range(dir); } else { // The port is not a multiport, return the single subport. @@ -316,7 +381,7 @@ impl<'a> PortLinks<'a> { if multigraph.is_multiport(port) { let copy_node = multigraph.get_copy_node(port).unwrap(); let dir = multigraph.graph.port_direction(port).unwrap(); - let subports = multigraph.graph.ports(copy_node, dir).enumerate(); + let subports = multigraph.graph._ports(copy_node, dir).enumerate(); Self::Multiport { multigraph, port, diff --git a/src/portgraph.rs b/src/portgraph.rs index 6836747..a01ae7e 100644 --- a/src/portgraph.rs +++ b/src/portgraph.rs @@ -12,6 +12,7 @@ mod iter; +use delegate::delegate; use std::mem::{replace, take}; use std::num::{NonZeroU16, NonZeroU32}; use std::ops::Range; @@ -255,9 +256,9 @@ impl PortGraph { // Disconnect any port to be removed. for port in self - .inputs(node) + ._inputs(node) .skip(incoming) - .chain(self.outputs(node).skip(outgoing)) + .chain(self._outputs(node).skip(outgoing)) { let old_link = self.unlink_port(port); rekey(port, PortOperation::Removed { old_link }); @@ -315,22 +316,6 @@ impl PortGraph { } impl PortView for PortGraph { - type Nodes<'a> = Nodes<'a> - where - Self: 'a; - - type Ports<'a> = Ports<'a> - where - Self: 'a; - - type NodePorts<'a> = NodePorts - where - Self: 'a; - - type NodePortOffsets<'a> = NodePortOffsets - where - Self: 'a; - #[inline] fn port_direction(&self, port: impl Into) -> Option { Some(self.port_meta_valid(port.into())?.direction()) @@ -368,24 +353,6 @@ impl PortView for PortGraph { node_meta.ports(direction).nth(offset).map(PortIndex::new) } - fn ports(&self, node: NodeIndex, direction: Direction) -> Self::NodePorts<'_> { - match self.node_meta_valid(node) { - Some(node_meta) => NodePorts { - indices: node_meta.ports(direction), - }, - None => NodePorts::default(), - } - } - - fn all_ports(&self, node: NodeIndex) -> Self::NodePorts<'_> { - match self.node_meta_valid(node) { - Some(node_meta) => NodePorts { - indices: node_meta.all_ports(), - }, - None => NodePorts::default(), - } - } - #[inline] fn input(&self, node: NodeIndex, offset: usize) -> Option { self.port_index(node, PortOffset::new_incoming(offset)) @@ -407,27 +374,6 @@ impl PortView for PortGraph { } } - fn port_offsets(&self, node: NodeIndex, direction: Direction) -> Self::NodePortOffsets<'_> { - match direction { - Direction::Incoming => NodePortOffsets { - incoming: 0..self.num_inputs(node) as u16, - outgoing: 0..0, - }, - Direction::Outgoing => NodePortOffsets { - incoming: 0..0, - outgoing: 0..self.num_outputs(node) as u32, - }, - } - } - - #[inline] - fn all_port_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_> { - NodePortOffsets { - incoming: 0..self.num_inputs(node) as u16, - outgoing: 0..self.num_outputs(node) as u32, - } - } - #[inline] fn contains_node(&self, node: NodeIndex) -> bool { self.node_meta_valid(node).is_some() @@ -453,22 +399,6 @@ impl PortView for PortGraph { self.port_count } - #[inline] - fn nodes_iter(&self) -> Self::Nodes<'_> { - Nodes { - iter: self.node_meta.iter().enumerate(), - len: self.node_count, - } - } - - #[inline] - fn ports_iter(&self) -> Self::Ports<'_> { - Ports { - iter: self.port_meta.iter().enumerate(), - len: self.port_count, - } - } - #[inline] fn node_capacity(&self) -> usize { self.node_meta.capacity() @@ -484,6 +414,22 @@ impl PortView for PortGraph { self.node_meta_valid(node) .map_or(0, |node_meta| node_meta.capacity()) } + delegate! { + to self { + #[call(_ports)] + fn ports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_ports)] + fn all_ports(&self, node: NodeIndex) -> impl Iterator + Clone; + #[call(_port_offsets)] + fn port_offsets(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_port_offsets)] + fn all_port_offsets(&self, node: NodeIndex) -> impl Iterator + Clone; + #[call(_nodes_iter)] + fn nodes_iter(&self) -> impl Iterator + Clone; + #[call(_ports_iter)] + fn ports_iter(&self) -> impl Iterator + Clone; + } + } } impl PortMut for PortGraph { @@ -588,9 +534,9 @@ impl PortMut for PortGraph { // Disconnect any port to be removed. for port in self - .inputs(node) + ._inputs(node) .skip(incoming) - .chain(self.outputs(node).skip(outgoing)) + .chain(self._outputs(node).skip(outgoing)) { let old_link = self.unlink_port(port); rekey(port, PortOperation::Removed { old_link }); @@ -764,28 +710,7 @@ impl PortMut for PortGraph { impl LinkView for PortGraph { type LinkEndpoint = PortIndex; - type Neighbours<'a> = Neighbours<'a> - where - Self: 'a; - - type NodeConnections<'a> = NodeConnections<'a> - where - Self: 'a; - - type NodeLinks<'a> = NodeLinks<'a> - where - Self: 'a; - - type PortLinks<'a> = std::iter::Once<(PortIndex, PortIndex)> - where - Self: 'a; - - #[inline] - fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> Self::NodeConnections<'_> { - NodeConnections::new(self, to, self.output_links(from)) - } - - fn port_links(&self, port: PortIndex) -> Self::PortLinks<'_> { + fn port_links(&self, port: PortIndex) -> impl Iterator + Clone { self.port_meta_valid(port).unwrap(); match self.port_link[port.index()] { Some(link) => std::iter::once((port, link)), @@ -797,42 +722,25 @@ impl LinkView for PortGraph { } } - fn links(&self, node: NodeIndex, direction: Direction) -> Self::NodeLinks<'_> { - let Some(node_meta) = self.node_meta_valid(node) else { - return NodeLinks::new(self.ports(node, direction), &[], 0..0); - }; - let indices = node_meta.ports(direction); - NodeLinks::new(self.ports(node, direction), &self.port_link[indices], 0..0) - } - - fn all_links(&self, node: NodeIndex) -> Self::NodeLinks<'_> { - let Some(node_meta) = self.node_meta_valid(node) else { - return NodeLinks::new(self.all_ports(node), &[], 0..0); - }; - let indices = node_meta.all_ports(); - // Ignore links where the target is one of the node's output ports. - // This way we only count self-links once. - NodeLinks::new( - self.all_ports(node), - &self.port_link[indices], - node_meta.outgoing_ports(), - ) - } - - #[inline] - fn neighbours(&self, node: NodeIndex, direction: Direction) -> Self::Neighbours<'_> { - Neighbours::from_node_links(self, self.links(node, direction)) - } - - #[inline] - fn all_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_> { - Neighbours::from_node_links(self, self.all_links(node)) - } - #[inline] fn link_count(&self) -> usize { self.link_count } + + delegate! { + to self { + #[call(_get_connections)] + fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> impl Iterator + Clone; + #[call(_links)] + fn links(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_links)] + fn all_links(&self, node: NodeIndex) -> impl Iterator + Clone; + #[call(_neighbours)] + fn neighbours(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + #[call(_all_neighbours)] + fn all_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone; + } + } } impl LinkMut for PortGraph { @@ -1091,8 +999,8 @@ mod debug { impl<'a> std::fmt::Debug for NodeDebug<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let inputs = PortRangeDebug(self.0.inputs(self.1).as_range()); - let outputs = PortRangeDebug(self.0.outputs(self.1).as_range()); + let inputs = PortRangeDebug(self.0._inputs(self.1).as_range()); + let outputs = PortRangeDebug(self.0._outputs(self.1).as_range()); f.debug_struct("Node") .field("inputs", &inputs) @@ -1386,7 +1294,7 @@ pub mod test { vec![(node1_output, node0_input), (node1_output2, node0_input2)] ); assert_eq!( - g.get_connections(node1, node0).rev().collect::>(), + g._get_connections(node1, node0).rev().collect::>(), vec![(node1_output2, node0_input2), (node1_output, node0_input)] ); } diff --git a/src/portgraph/iter.rs b/src/portgraph/iter.rs index 663e780..33345f5 100644 --- a/src/portgraph/iter.rs +++ b/src/portgraph/iter.rs @@ -11,6 +11,135 @@ use crate::{ }; use crate::{NodeIndex, PortIndex, PortOffset}; +/// Iterator methods for [`PortGraph`] with concrete return types. +/// +/// Used internally by other iterator implementations to avoid the generic RPITIT return types. +impl PortGraph { + /// Iterates over all the ports of the `node` in the given `direction`. + pub(crate) fn _ports(&self, node: NodeIndex, direction: Direction) -> NodePorts { + match self.node_meta_valid(node) { + Some(node_meta) => NodePorts { + indices: node_meta.ports(direction), + }, + None => NodePorts::default(), + } + } + + /// Iterates over all the input ports of the `node`. + /// + /// Shorthand for [`PortView::ports`]. + #[must_use] + #[inline] + pub(crate) fn _inputs(&self, node: NodeIndex) -> NodePorts { + self._ports(node, Direction::Incoming) + } + + /// Iterates over all the output ports of the `node`. + /// + /// Shorthand for [`PortView::ports`]. + #[must_use] + #[inline] + pub(crate) fn _outputs(&self, node: NodeIndex) -> NodePorts { + self._ports(node, Direction::Outgoing) + } + + /// Iterates over the input and output ports of the `node` in sequence. + pub(crate) fn _all_ports(&self, node: NodeIndex) -> NodePorts { + match self.node_meta_valid(node) { + Some(node_meta) => NodePorts { + indices: node_meta.all_ports(), + }, + None => NodePorts::default(), + } + } + + /// Iterates over all the port offsets of the `node` in the given `direction`. + pub(crate) fn _port_offsets(&self, node: NodeIndex, direction: Direction) -> NodePortOffsets { + match direction { + Direction::Incoming => NodePortOffsets { + incoming: 0..self.num_inputs(node) as u16, + outgoing: 0..0, + }, + Direction::Outgoing => NodePortOffsets { + incoming: 0..0, + outgoing: 0..self.num_outputs(node) as u32, + }, + } + } + + /// Iterates over the input and output port offsets of the `node` in sequence. + #[inline] + pub(crate) fn _all_port_offsets(&self, node: NodeIndex) -> NodePortOffsets { + NodePortOffsets { + incoming: 0..self.num_inputs(node) as u16, + outgoing: 0..self.num_outputs(node) as u32, + } + } + + /// Iterates over the nodes in the port graph. + #[inline] + pub(crate) fn _nodes_iter(&self) -> Nodes { + Nodes { + iter: self.node_meta.iter().enumerate(), + len: self.node_count, + } + } + + /// Iterates over the ports in the port graph. + #[inline] + pub(crate) fn _ports_iter(&self) -> Ports { + Ports { + iter: self.port_meta.iter().enumerate(), + len: self.port_count, + } + } + + /// Returns an iterator over every pair of matching ports connecting `from` + /// with `to`. + #[inline] + pub(crate) fn _get_connections(&self, from: NodeIndex, to: NodeIndex) -> NodeConnections { + NodeConnections::new(self, to, self._links(from, Direction::Outgoing)) + } + + /// Iterates over the connected links of the `node` in the given + /// `direction`. + pub(crate) fn _links(&self, node: NodeIndex, direction: Direction) -> NodeLinks { + let Some(node_meta) = self.node_meta_valid(node) else { + return NodeLinks::new(self._ports(node, direction), &[], 0..0); + }; + let indices = node_meta.ports(direction); + NodeLinks::new(self._ports(node, direction), &self.port_link[indices], 0..0) + } + + /// Iterates over the connected input and output links of the `node` in sequence. + pub(crate) fn _all_links(&self, node: NodeIndex) -> NodeLinks { + let Some(node_meta) = self.node_meta_valid(node) else { + return NodeLinks::new(self._all_ports(node), &[], 0..0); + }; + let indices = node_meta.all_ports(); + // Ignore links where the target is one of the node's output ports. + // This way we only count self-links once. + NodeLinks::new( + self._all_ports(node), + &self.port_link[indices], + node_meta.outgoing_ports(), + ) + } + + /// Iterates over neighbour nodes in the given `direction`. + /// May contain duplicates if the graph has multiple links between nodes. + #[inline] + pub(crate) fn _neighbours(&self, node: NodeIndex, direction: Direction) -> Neighbours { + Neighbours::from_node_links(self, self._links(node, direction)) + } + + /// Iterates over the input and output neighbours of the `node` in sequence. + #[inline] + pub(crate) fn _all_neighbours(&self, node: NodeIndex) -> Neighbours { + Neighbours::from_node_links(self, self._all_links(node)) + } +} + /// Iterator over the ports of a node. /// See [`PortGraph::inputs`], [`PortGraph::outputs`], and [`PortGraph::all_ports`]. #[derive(Debug, Clone, Default)] diff --git a/src/view.rs b/src/view.rs index d0f2cad..7e9ffae 100644 --- a/src/view.rs +++ b/src/view.rs @@ -18,26 +18,6 @@ pub use subgraph::Subgraph; /// Core capabilities for querying a graph containing nodes and ports. pub trait PortView { - /// Iterator over the nodes of the graph. - type Nodes<'a>: Iterator - where - Self: 'a; - - /// Iterator over the ports of the graph. - type Ports<'a>: Iterator - where - Self: 'a; - - /// Iterator over the ports of a node. - type NodePorts<'a>: Iterator - where - Self: 'a; - - /// Iterator over the port offsets in a node. - type NodePortOffsets<'a>: Iterator - where - Self: 'a; - /// Returns the direction of the `port`. #[must_use] fn port_direction(&self, port: impl Into) -> Option; @@ -56,18 +36,22 @@ pub trait PortView { /// Iterates over all the ports of the `node` in the given `direction`. #[must_use] - fn ports(&self, node: NodeIndex, direction: Direction) -> Self::NodePorts<'_>; + fn ports( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone; /// Iterates over the input and output ports of the `node` in sequence. #[must_use] - fn all_ports(&self, node: NodeIndex) -> Self::NodePorts<'_>; + fn all_ports(&self, node: NodeIndex) -> impl Iterator + Clone; /// Iterates over all the input ports of the `node`. /// /// Shorthand for [`PortView::ports`]. #[must_use] #[inline] - fn inputs(&self, node: NodeIndex) -> Self::NodePorts<'_> { + fn inputs(&self, node: NodeIndex) -> impl Iterator + Clone { self.ports(node, Direction::Incoming) } @@ -76,7 +60,7 @@ pub trait PortView { /// Shorthand for [`PortView::ports`]. #[must_use] #[inline] - fn outputs(&self, node: NodeIndex) -> Self::NodePorts<'_> { + fn outputs(&self, node: NodeIndex) -> impl Iterator + Clone { self.ports(node, Direction::Outgoing) } @@ -127,18 +111,22 @@ pub trait PortView { /// assert!(graph.port_offsets(node, Direction::Outgoing).eq([PortOffset::new_outgoing(0), PortOffset::new_outgoing(1)])); /// ``` #[must_use] - fn port_offsets(&self, node: NodeIndex, direction: Direction) -> Self::NodePortOffsets<'_>; + fn port_offsets( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone; /// Iterates over the input and output port offsets of the `node` in sequence. #[must_use] - fn all_port_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_>; + fn all_port_offsets(&self, node: NodeIndex) -> impl Iterator + Clone; /// Iterates over all the input port offsets of the `node`. /// /// Shorthand for [`PortView::port_offsets`]. #[must_use] #[inline] - fn input_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_> { + fn input_offsets(&self, node: NodeIndex) -> impl Iterator + Clone { self.port_offsets(node, Direction::Incoming) } @@ -147,7 +135,7 @@ pub trait PortView { /// Shorthand for [`PortView::port_offsets`]. #[must_use] #[inline] - fn output_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_> { + fn output_offsets(&self, node: NodeIndex) -> impl Iterator + Clone { self.port_offsets(node, Direction::Outgoing) } @@ -173,11 +161,11 @@ pub trait PortView { /// Iterates over the nodes in the port graph. #[must_use] - fn nodes_iter(&self) -> Self::Nodes<'_>; + fn nodes_iter(&self) -> impl Iterator + Clone; /// Iterates over the ports in the port graph. #[must_use] - fn ports_iter(&self) -> Self::Ports<'_>; + fn ports_iter(&self) -> impl Iterator + Clone; /// Returns the capacity of the underlying buffer for nodes. #[must_use] @@ -225,8 +213,12 @@ pub trait PortMut: PortView { /// let mut g = PortGraph::new(); /// let node0 = g.add_node(1, 1); /// let node1 = g.add_node(1, 1); - /// g.link_ports(g.outputs(node0).nth(0).unwrap(), g.inputs(node1).nth(0).unwrap()); - /// g.link_ports(g.outputs(node1).nth(0).unwrap(), g.inputs(node0).nth(0).unwrap()); + /// let out0 = g.outputs(node0).nth(0).unwrap(); + /// let out1 = g.outputs(node1).nth(0).unwrap(); + /// let in0 = g.inputs(node0).nth(0).unwrap(); + /// let in1 = g.inputs(node1).nth(0).unwrap(); + /// g.link_ports(out0, in1); + /// g.link_ports(out1, in0); /// g.remove_node(node0); /// assert!(!g.contains_node(node0)); /// assert!(g.port_link(g.outputs(node1).nth(0).unwrap()).is_none()); @@ -287,28 +279,6 @@ pub trait LinkView: PortView { /// The identifier for the endpoints of a link. type LinkEndpoint: Into + Copy; - /// Iterator over the neighbours of a node. - type Neighbours<'a>: Iterator - where - Self: 'a; - - /// Iterator over the connections between two nodes. - type NodeConnections<'a>: Iterator - where - Self: 'a; - - /// Iterator over the links of a node. Returns pairs of source subport in - /// the given node and target subport in the linked node. - type NodeLinks<'a>: Iterator - where - Self: 'a; - - /// Iterator over the links of a port. Returns pairs of source subport in - /// the given ports and target subport in the linked port. - type PortLinks<'a>: Iterator - where - Self: 'a; - /// Returns an iterator over every pair of matching ports connecting `from` /// with `to`. /// @@ -328,7 +298,11 @@ pub trait LinkView: PortView { /// assert_eq!(connections.next(), None); /// ``` #[must_use] - fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> Self::NodeConnections<'_>; + fn get_connections( + &self, + from: NodeIndex, + to: NodeIndex, + ) -> impl Iterator + Clone; /// Checks whether there is a directed link between the two nodes and /// returns the first matching pair of ports. @@ -375,7 +349,10 @@ pub trait LinkView: PortView { /// Returns the port that the given `port` is linked to. #[must_use] - fn port_links(&self, port: PortIndex) -> Self::PortLinks<'_>; + fn port_links( + &self, + port: PortIndex, + ) -> impl Iterator + Clone; /// Return the link to the provided port, if not connected return None. /// If this port has multiple connected subports, an arbitrary one is returned. @@ -407,17 +384,27 @@ pub trait LinkView: PortView { /// assert!(graph.links(node_b, Direction::Incoming).eq([(port_b, port_a)])); /// ``` #[must_use] - fn links(&self, node: NodeIndex, direction: Direction) -> Self::NodeLinks<'_>; + fn links( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone; /// Iterates over the connected input and output links of the `node` in sequence. #[must_use] - fn all_links(&self, node: NodeIndex) -> Self::NodeLinks<'_>; + fn all_links( + &self, + node: NodeIndex, + ) -> impl Iterator + Clone; /// Iterates over the connected input links of the `node`. Shorthand for /// [`LinkView::links`]. #[must_use] #[inline] - fn input_links(&self, node: NodeIndex) -> Self::NodeLinks<'_> { + fn input_links( + &self, + node: NodeIndex, + ) -> impl Iterator + Clone { self.links(node, Direction::Incoming) } @@ -425,7 +412,10 @@ pub trait LinkView: PortView { /// [`LinkView::links`]. #[must_use] #[inline] - fn output_links(&self, node: NodeIndex) -> Self::NodeLinks<'_> { + fn output_links( + &self, + node: NodeIndex, + ) -> impl Iterator + Clone { self.links(node, Direction::Outgoing) } @@ -449,23 +439,27 @@ pub trait LinkView: PortView { /// assert!(graph.neighbours(b, Direction::Incoming).eq([a,b])); /// ``` #[must_use] - fn neighbours(&self, node: NodeIndex, direction: Direction) -> Self::Neighbours<'_>; + fn neighbours( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone; /// Iterates over the input and output neighbours of the `node` in sequence. #[must_use] - fn all_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_>; + fn all_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone; /// Iterates over the input neighbours of the `node`. Shorthand for [`LinkView::neighbours`]. #[must_use] #[inline] - fn input_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_> { + fn input_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone { self.neighbours(node, Direction::Incoming) } /// Iterates over the output neighbours of the `node`. Shorthand for [`LinkView::neighbours`]. #[must_use] #[inline] - fn output_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_> { + fn output_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone { self.neighbours(node, Direction::Outgoing) } @@ -585,11 +579,6 @@ pub trait LinkMut: LinkView + PortMut { /// Abstraction over a portgraph that may have multiple connections per node. pub trait MultiView: LinkView { - /// Iterator over all the subports of a node. - type NodeSubports<'a>: Iterator - where - Self: 'a; - /// Return the subport linked to the given `port`. If the port is not /// connected, return None. #[must_use] @@ -597,18 +586,22 @@ pub trait MultiView: LinkView { /// Iterates over all the subports of the `node` in the given `direction`. #[must_use] - fn subports(&self, node: NodeIndex, direction: Direction) -> Self::NodeSubports<'_>; + fn subports( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone; /// Iterates over the input and output subports of the `node` in sequence. #[must_use] - fn all_subports(&self, node: NodeIndex) -> Self::NodeSubports<'_>; + fn all_subports(&self, node: NodeIndex) -> impl Iterator + Clone; /// Iterates over all the input subports of the `node`. /// /// Shorthand for [`MultiView::subports`]. #[must_use] #[inline] - fn subport_inputs(&self, node: NodeIndex) -> Self::NodeSubports<'_> { + fn subport_inputs(&self, node: NodeIndex) -> impl Iterator + Clone { self.subports(node, Direction::Incoming) } @@ -617,7 +610,7 @@ pub trait MultiView: LinkView { /// Shorthand for [`MultiView::subports`]. #[must_use] #[inline] - fn subport_outputs(&self, node: NodeIndex) -> Self::NodeSubports<'_> { + fn subport_outputs(&self, node: NodeIndex) -> impl Iterator + Clone { self.subports(node, Direction::Outgoing) } } diff --git a/src/view/filter.rs b/src/view/filter.rs index c39043e..038d4d1 100644 --- a/src/view/filter.rs +++ b/src/view/filter.rs @@ -1,8 +1,7 @@ //! Wrappers around portgraphs to filter out nodes and ports. -use crate::{Direction, LinkView, MultiView, NodeIndex, PortIndex, PortView}; +use crate::{Direction, LinkView, MultiView, NodeIndex, PortIndex, PortOffset, PortView}; -use context_iterators::{ContextIterator, FilterWithCtx, IntoContextIterator, MapWithCtx}; use delegate::delegate; /// Node filter used by [`FilteredGraph`]. @@ -75,108 +74,43 @@ where G: Clone, { /// Node filter used for the iterators - fn node_filter(node: &NodeIndex, ctx: &FilteredGraphCtx) -> bool + fn node_filter(&self, node: &NodeIndex) -> bool where G: PortView, { - (ctx.node_filter)(*node, ctx.context) + (self.node_filter)(*node, &self.context) } /// Port filter used for the iterators /// /// A port exists iff its node exists (don't use `link_filter`!) - fn port_filter(&port: &(impl Into + Copy), ctx: &FilteredGraphCtx) -> bool + fn port_filter(&self, &port: &(impl Into + Copy)) -> bool where G: PortView, { - let node = ctx.graph.port_node(port).unwrap(); - FilteredGraph::node_filter(&node, ctx) + let node = self.graph.port_node(port).unwrap(); + self.node_filter(&node) } /// Link filter used for the iterators /// /// A link exists if both its ports exist and satisfy `link_filter`. - fn link_filter( - link: &(G::LinkEndpoint, G::LinkEndpoint), - ctx: &FilteredGraphCtx, - ) -> bool + fn link_filter(&self, link: &(G::LinkEndpoint, G::LinkEndpoint)) -> bool where G: LinkView, { let &(from, to) = link; - FilteredGraph::port_filter(&from, ctx) - && FilteredGraph::port_filter(&to, ctx) - && (ctx.link_filter)(from.into(), ctx.context) - && (ctx.link_filter)(to.into(), ctx.context) - } - - /// The full context used for the iterators - fn as_context(&self) -> FilteredGraphCtx<'_, G, Ctx> - where - G: PortView, - { - FilteredGraphCtx::new( - self.graph.clone(), - self.node_filter, - self.link_filter, - &self.context, - ) - } -} - -/// Context used internally for the [`FilteredGraph`] iterators. -/// -/// This is a named struct to make the iterator signatures more readable. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct FilteredGraphCtx<'a, G, Ctx> { - pub(self) graph: G, - pub(self) node_filter: NodeFilter, - pub(self) link_filter: LinkFilter, - pub(self) context: &'a Ctx, -} - -impl<'a, G, Ctx> FilteredGraphCtx<'a, G, Ctx> { - /// Create a new context. - pub(self) fn new( - graph: G, - node_filter: NodeFilter, - link_filter: LinkFilter, - context: &'a Ctx, - ) -> Self { - Self { - graph, - node_filter, - link_filter, - context, - } + self.port_filter(&from) + && self.port_filter(&to) + && (self.link_filter)(from.into(), &self.context) + && (self.link_filter)(to.into(), &self.context) } } -/// Filtered iterator wrapper used by [`FilteredGraph`]. -pub type FilteredGraphIter<'a, G, Ctx, I> = FilterWithCtx>; -/// Filtered + mapped iterator wrapper used by [`FilteredGraph`]. -pub type MapFilteredGraphIter<'a, G, Ctx, I, O> = MapWithCtx, O>; - impl PortView for FilteredGraph, LinkFilter, Ctx> where G: PortView + Clone, { - type Nodes<'a> = FilteredGraphIter<'a, G, Ctx, ::Nodes<'a>> - where - Self: 'a; - - type Ports<'a> = FilteredGraphIter<'a, G, Ctx, ::Ports<'a>> - where - Self: 'a; - - type NodePorts<'a> = G::NodePorts<'a> - where - Self: 'a; - - type NodePortOffsets<'a> = G::NodePortOffsets<'a> - where - Self: 'a; - #[inline] fn contains_node(&'_ self, node: NodeIndex) -> bool { self.graph.contains_node(node) && (self.node_filter)(node, &self.context) @@ -208,19 +142,13 @@ where } #[inline] - fn nodes_iter(&self) -> Self::Nodes<'_> { - self.graph - .nodes_iter() - .with_context(self.as_context()) - .filter_with_context(Self::node_filter) + fn nodes_iter(&self) -> impl Iterator + Clone { + self.graph.nodes_iter().filter(|n| self.node_filter(n)) } #[inline] - fn ports_iter(&self) -> Self::Ports<'_> { - self.graph - .ports_iter() - .with_context(self.as_context()) - .filter_with_context(Self::port_filter) + fn ports_iter(&self) -> impl Iterator + Clone { + self.graph.ports_iter().filter(|p| self.port_filter(p)) } delegate! { @@ -229,13 +157,13 @@ where fn port_node(&self, port: impl Into) -> Option; fn port_offset(&self, port: impl Into) -> Option; fn port_index(&self, node: NodeIndex, offset: crate::PortOffset) -> Option; - fn ports(&self, node: NodeIndex, direction: Direction) -> Self::NodePorts<'_>; - fn all_ports(&self, node: NodeIndex) -> Self::NodePorts<'_>; + fn ports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_ports(&self, node: NodeIndex) -> impl Iterator + Clone; fn input(&self, node: NodeIndex, offset: usize) -> Option; fn output(&self, node: NodeIndex, offset: usize) -> Option; fn num_ports(&self, node: NodeIndex, direction: Direction) -> usize; - fn port_offsets(&self, node: NodeIndex, direction: Direction) -> Self::NodePortOffsets<'_>; - fn all_port_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_>; + fn port_offsets(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_port_offsets(&self, node: NodeIndex) -> impl Iterator + Clone; fn node_capacity(&self) -> usize; fn port_capacity(&self) -> usize; fn node_port_capacity(&self, node: NodeIndex) -> usize; @@ -249,60 +177,52 @@ where { type LinkEndpoint = G::LinkEndpoint; - type Neighbours<'a> = MapFilteredGraphIter<'a, G, Ctx, Self::NodeLinks<'a>, NodeIndex> - where - Self: 'a; - - type NodeConnections<'a> = FilteredGraphIter<'a, G, Ctx, ::NodeConnections<'a>> - where - Self: 'a; - - type NodeLinks<'a> = FilteredGraphIter<'a, G, Ctx, ::NodeLinks<'a>> - where - Self: 'a; - - type PortLinks<'a> = FilteredGraphIter<'a, G, Ctx, ::PortLinks<'a>> - where - Self: 'a; - - fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> Self::NodeConnections<'_> { + fn get_connections( + &self, + from: NodeIndex, + to: NodeIndex, + ) -> impl Iterator + Clone { self.graph .get_connections(from, to) - .with_context(self.as_context()) - .filter_with_context(Self::link_filter) + .filter(|l| self.link_filter(l)) } - fn port_links(&self, port: PortIndex) -> Self::PortLinks<'_> { - self.graph - .port_links(port) - .with_context(self.as_context()) - .filter_with_context(Self::link_filter) + fn port_links( + &self, + port: PortIndex, + ) -> impl Iterator + Clone { + self.graph.port_links(port).filter(|l| self.link_filter(l)) } - fn links(&self, node: NodeIndex, direction: Direction) -> Self::NodeLinks<'_> { + fn links( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone { self.graph .links(node, direction) - .with_context(self.as_context()) - .filter_with_context(Self::link_filter) + .filter(|l| self.link_filter(l)) } - fn all_links(&self, node: NodeIndex) -> Self::NodeLinks<'_> { - self.graph - .all_links(node) - .with_context(self.as_context()) - .filter_with_context(Self::link_filter) + fn all_links( + &self, + node: NodeIndex, + ) -> impl Iterator + Clone { + self.graph.all_links(node).filter(|l| self.link_filter(l)) } - fn neighbours(&self, node: NodeIndex, direction: Direction) -> Self::Neighbours<'_> { + fn neighbours( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone { self.links(node, direction) - .with_context(self.as_context()) - .map_with_context(|(_, p), ctx| ctx.graph.port_node(p).unwrap()) + .map(|(_, p)| self.graph.port_node(p).unwrap()) } - fn all_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_> { + fn all_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone { self.all_links(node) - .with_context(self.as_context()) - .map_with_context(|(_, p), ctx| ctx.graph.port_node(p).unwrap()) + .map(|(_, p)| self.graph.port_node(p).unwrap()) } fn link_count(&self) -> usize { @@ -316,22 +236,20 @@ impl MultiView for FilteredGraph, LinkFilter, Ct where G: MultiView + Clone, { - type NodeSubports<'a> = FilteredGraphIter<'a, G, Ctx, ::NodeSubports<'a>> - where - Self: 'a; - - fn subports(&self, node: NodeIndex, direction: Direction) -> Self::NodeSubports<'_> { + fn subports( + &self, + node: NodeIndex, + direction: Direction, + ) -> impl Iterator + Clone { self.graph .subports(node, direction) - .with_context(self.as_context()) - .filter_with_context(Self::port_filter) + .filter(|p| self.port_filter(p)) } - fn all_subports(&self, node: NodeIndex) -> Self::NodeSubports<'_> { + fn all_subports(&self, node: NodeIndex) -> impl Iterator + Clone { self.graph .all_subports(node) - .with_context(self.as_context()) - .filter_with_context(Self::port_filter) + .filter(|p| self.port_filter(p)) } fn subport_link(&self, subport: Self::LinkEndpoint) -> Option { diff --git a/src/view/petgraph.rs b/src/view/petgraph.rs index 6086b96..46bb80f 100644 --- a/src/view/petgraph.rs +++ b/src/view/petgraph.rs @@ -6,7 +6,7 @@ use bitvec::vec::BitVec; use crate::multiportgraph::MultiPortGraph; use crate::view::filter::{NodeFilter, NodeFiltered}; -use crate::{LinkView, NodeIndex, PortGraph, PortView, SecondaryMap}; +use crate::{LinkView, NodeIndex, PortGraph, PortIndex, PortView, SecondaryMap}; impl From for crate::Direction { fn from(d: petgraph::Direction) -> Self { @@ -95,39 +95,39 @@ macro_rules! impl_petgraph_traits { } impl<'g, $($args)*> petgraph::visit::IntoNodeIdentifiers for &'g $graph where $($where)* { - type NodeIdentifiers = <$graph as PortView>::Nodes<'g>; + type NodeIdentifiers = Box + 'g>; fn node_identifiers(self) -> Self::NodeIdentifiers { - self.nodes_iter() + Box::new(self.nodes_iter()) } } impl<'g, $($args)*> petgraph::visit::IntoNodeReferences for &'g $graph where $($where)* { type NodeRef = NodeIndex; - type NodeReferences = <$graph as PortView>::Nodes<'g>; + type NodeReferences = Box + 'g>; fn node_references(self) -> Self::NodeReferences { - self.nodes_iter() + Box::new(self.nodes_iter()) } } impl<'g, $($args)*> petgraph::visit::IntoNeighbors for &'g $graph where $($where)* { - type Neighbors = <$graph as LinkView>::Neighbours<'g>; + type Neighbors = Box + 'g>; fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { - self.output_neighbours(n) + Box::new(self.output_neighbours(n)) } } impl<'g, $($args)*> petgraph::visit::IntoNeighborsDirected for &'g $graph where $($where)* { - type NeighborsDirected = <$graph as LinkView>::Neighbours<'g>; + type NeighborsDirected = Box + 'g>; fn neighbors_directed( self, n: Self::NodeId, d: petgraph::Direction, ) -> Self::NeighborsDirected { - self.neighbours(n, d.into()) + Box::new(self.neighbours(n, d.into())) } } @@ -325,8 +325,9 @@ where /// Used for compatibility with petgraph. pub struct EdgeRefs<'g, G: LinkView> { graph: &'g G, - ports: G::Ports<'g>, - links: Option>, + ports: Box + 'g>, + #[allow(clippy::type_complexity)] + links: Option + 'g>>, count: usize, } @@ -338,7 +339,7 @@ where pub fn new(graph: &'g G) -> Self { Self { graph, - ports: graph.ports_iter(), + ports: Box::new(graph.ports_iter()), links: None, count: graph.link_count(), } @@ -362,7 +363,7 @@ where } let port = self.ports.next()?; - self.links = Some(self.graph.port_links(port)); + self.links = Some(Box::new(self.graph.port_links(port))); } } @@ -394,7 +395,7 @@ impl FusedIterator for EdgeRefs<'_, G> {} /// Used for compatibility with petgraph. pub struct NodeEdgeRefs<'g, G: LinkView> { graph: &'g G, - links: G::NodeLinks<'g>, + links: Box + 'g>, } impl<'g, G> NodeEdgeRefs<'g, G> @@ -405,7 +406,7 @@ where pub fn new(graph: &'g G, node: NodeIndex) -> Self { Self { graph, - links: graph.all_links(node), + links: Box::new(graph.all_links(node)), } } @@ -413,7 +414,7 @@ where pub fn new_directed(graph: &'g G, node: NodeIndex, dir: crate::Direction) -> Self { Self { graph, - links: graph.links(node, dir), + links: Box::new(graph.links(node, dir)), } } } @@ -446,15 +447,3 @@ where self.links.size_hint() } } - -impl<'g, G: LinkView> ExactSizeIterator for NodeEdgeRefs<'g, G> -where - G::NodeLinks<'g>: ExactSizeIterator, -{ - #[inline] - fn len(&self) -> usize { - self.links.len() - } -} - -impl<'g, G: LinkView> FusedIterator for NodeEdgeRefs<'g, G> where G::NodeLinks<'g>: FusedIterator {} diff --git a/src/view/refs.rs b/src/view/refs.rs index beb8fba..52a33e8 100644 --- a/src/view/refs.rs +++ b/src/view/refs.rs @@ -7,45 +7,29 @@ use crate::{Direction, NodeIndex, PortIndex, PortOffset}; use delegate::delegate; -use super::{LinkView, PortView}; +use super::{LinkView, MultiView, PortView}; impl<'g, G: PortView> PortView for &'g G { - type Nodes<'a> = G::Nodes<'a> - where - Self: 'a; - - type Ports<'a> = G::Ports<'a> - where - Self: 'a; - - type NodePorts<'a> = G::NodePorts<'a> - where - Self: 'a; - - type NodePortOffsets<'a> = G::NodePortOffsets<'a> - where - Self: 'a; - delegate! { to (*self) { fn port_direction(&self, port: impl Into) -> Option; fn port_node(&self, port: impl Into) -> Option; fn port_offset(&self, port: impl Into) -> Option; fn port_index(&self, node: NodeIndex, offset: PortOffset) -> Option; - fn ports(&self, node: NodeIndex, direction: Direction) -> Self::NodePorts<'_>; - fn all_ports(&self, node: NodeIndex) -> Self::NodePorts<'_>; + fn ports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_ports(&self, node: NodeIndex) -> impl Iterator + Clone; fn input(&self, node: NodeIndex, offset: usize) -> Option; fn output(&self, node: NodeIndex, offset: usize) -> Option; fn num_ports(&self, node: NodeIndex, direction: Direction) -> usize; - fn port_offsets(&self, node: NodeIndex, direction: Direction) -> Self::NodePortOffsets<'_>; - fn all_port_offsets(&self, node: NodeIndex) -> Self::NodePortOffsets<'_>; + fn port_offsets(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_port_offsets(&self, node: NodeIndex) -> impl Iterator + Clone; fn contains_node(&self, node: NodeIndex) -> bool; fn contains_port(&self, port: PortIndex) -> bool; fn is_empty(&self) -> bool; fn node_count(&self) -> usize; fn port_count(&self) -> usize; - fn nodes_iter(&self) -> Self::Nodes<'_>; - fn ports_iter(&self) -> Self::Ports<'_>; + fn nodes_iter(&self) -> impl Iterator + Clone; + fn ports_iter(&self) -> impl Iterator + Clone; fn node_capacity(&self) -> usize; fn port_capacity(&self) -> usize; fn node_port_capacity(&self, node: NodeIndex) -> usize; @@ -56,33 +40,27 @@ impl<'g, G: PortView> PortView for &'g G { impl<'g, G: LinkView> LinkView for &'g G { type LinkEndpoint = G::LinkEndpoint; - type Neighbours<'a> = G::Neighbours<'a> - where - Self: 'a; - - type NodeConnections<'a> = G::NodeConnections<'a> - where - Self: 'a; - - type NodeLinks<'a> = G::NodeLinks<'a> - where - Self: 'a; - - type PortLinks<'a> = G::PortLinks<'a> - where - Self: 'a; - delegate! { to (*self) { - fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> Self::NodeConnections<'_>; - fn port_links(&self, port: PortIndex) -> Self::PortLinks<'_>; - fn links(&self, node: NodeIndex, direction: Direction) -> Self::NodeLinks<'_>; - fn all_links(&self, node: NodeIndex) -> Self::NodeLinks<'_>; - fn neighbours(&self, node: NodeIndex, direction: Direction) -> Self::Neighbours<'_>; - fn all_neighbours(&self, node: NodeIndex) -> Self::Neighbours<'_>; + fn get_connections(&self, from: NodeIndex, to: NodeIndex) -> impl Iterator + Clone; + fn port_links(&self, port: PortIndex) -> impl Iterator + Clone; + fn links(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_links(&self, node: NodeIndex) -> impl Iterator + Clone; + fn neighbours(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_neighbours(&self, node: NodeIndex) -> impl Iterator + Clone; fn link_count(&self) -> usize; } } } -// TODO: PortMut, LinkMut, MultiView, MultiMut +impl<'g, G: MultiView> MultiView for &'g G { + delegate! { + to (*self) { + fn subports(&self, node: NodeIndex, direction: Direction) -> impl Iterator + Clone; + fn all_subports(&self, node: NodeIndex) -> impl Iterator + Clone; + fn subport_link(&self, subport: Self::LinkEndpoint) -> Option; + } + } +} + +// TODO: PortMut, LinkMut, MultiMut