flow_graph/schematic/iterators/
port.rs1use super::*;
2use crate::node::NodePort;
3use crate::port::PortDirection;
4use crate::{NodeIndex, PortReference};
5
6#[derive(Debug, Clone)]
7#[must_use]
8pub struct Port<'graph, DATA> {
9 schematic: &'graph Schematic<DATA>,
10 pub(super) port: PortReference,
11}
12
13impl<'graph, DATA> Port<'graph, DATA>
14where
15 DATA: Clone,
16{
17 pub const fn new(schematic: &'graph Schematic<DATA>, port: PortReference) -> Self {
18 Self { schematic, port }
19 }
20
21 pub const fn node(&self) -> NodeHop<DATA> {
22 NodeHop::new(self.schematic, self.port.node_index)
23 }
24
25 pub fn connections(&self) -> Connections<DATA> {
26 get_port_connections(self.schematic, &self.port)
27 }
28
29 #[must_use]
30 pub fn name(&self) -> &str {
31 get_port_name(self.schematic, &self.port)
32 }
33
34 pub fn inner(&self) -> &NodePort {
35 get_ports_node(self.schematic, &self.port)
36 }
37
38 pub const fn direction(&self) -> PortDirection {
39 self.port.direction
40 }
41}
42
43impl<'graph, DATA> AsRef<PortReference> for Port<'graph, DATA> {
44 fn as_ref(&self) -> &PortReference {
45 &self.port
46 }
47}
48
49impl<'graph, DATA> std::fmt::Display for Port<'graph, DATA>
50where
51 DATA: Clone,
52{
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "{}", display(self.schematic, &self.port))
55 }
56}
57
58#[derive(Debug, Clone)]
59#[must_use]
60pub struct Ports<'graph, DATA> {
61 pub(super) direction: Option<PortDirection>,
62 pub(super) ports: Vec<PortReference>,
63 pub(super) cur_index: usize,
64 pub(super) node_index: NodeIndex,
65 schematic: &'graph Schematic<DATA>,
66}
67
68impl<'graph, DATA> Ports<'graph, DATA> {
69 pub(crate) fn new(schematic: &'graph Schematic<DATA>, node_index: NodeIndex, ports: Vec<PortReference>) -> Self {
70 Self {
71 direction: ports.get(0).map(|p| *p.direction()),
72 ports,
73 cur_index: 0,
74 node_index,
75 schematic,
76 }
77 }
78
79 #[must_use]
80 pub fn len(&self) -> usize {
81 self.ports.len()
82 }
83
84 #[must_use]
85 pub fn is_empty(&self) -> bool {
86 self.ports.is_empty()
87 }
88}
89
90impl<'graph, DATA> Iterator for Ports<'graph, DATA>
91where
92 DATA: Clone,
93{
94 type Item = Port<'graph, DATA>;
95
96 fn next(&mut self) -> Option<Port<'graph, DATA>> {
97 let result = self
98 .ports
99 .get(self.cur_index)
100 .map(|index| Port::new(self.schematic, *index));
101 self.cur_index += 1;
102 result
103 }
104}
105
106fn display<DATA>(schematic: &Schematic<DATA>, port: &PortReference) -> String
107where
108 DATA: Clone,
109{
110 let node = &schematic.nodes[port.node_index];
111 let (port, dir) = match port.direction {
112 PortDirection::In => (&node.inputs()[port.port_index], "IN"),
113 PortDirection::Out => (&node.outputs()[port.port_index], "OUT"),
114 };
115 format!("{}.{}.{}", node, dir, port)
116}
117
118impl<'graph, DATA> std::fmt::Display for Ports<'graph, DATA>
119where
120 DATA: Clone,
121{
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 for (index, port) in self.ports.iter().enumerate() {
124 let comma = if index < (self.ports.len() - 1) { ", " } else { "" };
125 if index == self.cur_index {
126 write!(f, ">>>{}<<<{}", display(self.schematic, port), comma)?;
127 } else {
128 write!(f, "{}{}", display(self.schematic, port), comma)?;
129 }
130 }
131 if self.cur_index >= self.ports.len() {
132 write!(f, ", >>>DONE<<<")?;
133 }
134 Ok(())
135 }
136}