1use std::collections::HashMap;
2
3use serde::{Serialize, Deserialize};
4
5use crate::component::Id;
6use crate::ports::PortId;
7use crate::error::{FlowError, Result};
8
9
10#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
16pub struct Connection {
17 pub from: Id,
18 pub out_port: PortId,
19 pub to: Id,
20 pub in_port: PortId,
21}
22
23
24#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
40pub struct Point {
41 id: Id,
42 port: PortId,
43}
44impl Point {
45 #[inline]
47 pub const fn new(id: Id, port: PortId) -> Self {
48 Self { id, port }
49 }
50
51 #[inline]
53 pub fn id(&self) -> Id {
54 self.id
55 }
56
57 #[inline]
59 pub fn port(&self) -> PortId {
60 self.port
61 }
62}
63
64
65impl From<(Id, PortId)> for Point {
66 #[inline]
67 fn from((id, port): (Id, PortId)) -> Self {
68 Point { id, port }
69 }
70}
71
72impl Connection {
73 #[inline]
75 pub const fn new(from: Id, out_port: PortId, to: Id, in_port: PortId) -> Self {
76 Self {
77 from,
78 out_port,
79 to,
80 in_port,
81 }
82 }
83
84 #[inline]
86 pub const fn by(from: Point, to: Point) -> Self {
87 Self {
88 from: from.id,
89 out_port: from.port,
90 to: to.id,
91 in_port: to.port
92 }
93 }
94
95 #[inline]
97 pub fn from(&self) -> Point {
98 Point::new(self.from, self.out_port)
99 }
100
101 #[inline]
103 pub fn to(&self) -> Point {
104 Point::new(self.to, self.in_port)
105 }
106}
107
108
109#[derive(Debug, Clone)]
119pub(crate) struct Connections {
120 parents: HashMap<Id, Vec<Id>>,
121 connections: HashMap<Point, Vec<Point>>
122}
123
124
125impl Default for Connections {
127 fn default() -> Connections {
128 Connections {
129 parents: Default::default(),
130 connections: Default::default()
131 }
132 }
133}
134
135impl Connections {
136 pub fn new() -> Self {
138 Self::default()
139 }
140
141 pub fn add(&mut self, connection: Connection) -> Result<()> {
143 if self.ancestral_of(connection.from, connection.to) {
144 return Err(FlowError::LoopCreated { connection }.into())
145 }
146
147 let entry = self.connections.entry(connection.from());
148 let to = connection.to();
149 let to_ports = entry.or_default();
150
151 if to_ports.contains(&to) {
152 return Err(FlowError::ConnectionAlreadyExist { connection }.into())
153 }
154
155 to_ports.push(to);
156
157 let parents = self.parents.entry(connection.to).or_default();
158 if !parents.contains(&connection.from) {
159 parents.push(connection.from);
160 }
161
162 Ok(())
163 }
164
165
166 pub fn ancestral_of(&self, ancestral: Id, id: Id) -> bool {
167 if ancestral == id { return true;
169 }
170 if let Some(parents) = self.parents.get(&id) {
171 for parent in parents {
172 if *parent == ancestral || self.ancestral_of(ancestral, *parent) {
173 return true;
174 }
175 }
176 }
177
178 false
179 }
180
181 pub fn any_ancestral_of(&self, ancestrals: &[Id], id: Id) -> bool {
182 if ancestrals.contains(&id) { return true;
184 }
185
186 if let Some(parents) = self.parents.get(&id) {
187 for parent in parents {
188 if self.any_ancestral_of(ancestrals, *parent) {
189 return true;
190 }
191 }
192 }
193
194 false
195 }
196
197 pub fn from(&self, from: Point) -> Option<&Vec<Point>> {
198 self.connections.get(&from)
199 }
200}