flow_graph/schematic/iterators/
port.rs

1use 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}