1use std::fmt::Debug;
4use std::hash::Hash;
5
6use derive_more::{From, Into};
7use derive_where::derive_where;
8use serde::{Deserialize, Serialize};
9
10use crate::{port_diff::Owned, Graph};
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13pub enum EdgeEnd {
14 Left,
15 Right,
16}
17
18impl EdgeEnd {
19 pub fn opposite(&self) -> Self {
20 match self {
21 Self::Left => Self::Right,
22 Self::Right => Self::Left,
23 }
24 }
25}
26
27#[derive(
32 Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
33)]
34pub struct Site<N, P> {
35 pub node: N,
37 pub port: P,
39}
40
41impl<N, P> Site<N, P> {
42 pub fn map_node(self, f: impl FnOnce(N) -> N) -> Site<N, P> {
43 Site {
44 node: f(self.node),
45 port: self.port,
46 }
47 }
48
49 pub fn filter_map_node(self, f: impl FnOnce(N) -> Option<N>) -> Option<Site<N, P>> {
50 Some(Site {
51 node: f(self.node)?,
52 port: self.port,
53 })
54 }
55}
56
57#[derive(
59 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, From, Into, Serialize, Deserialize,
60)]
61pub struct BoundaryIndex(usize);
62
63#[derive(Debug, From, Serialize, Deserialize)]
67#[serde(bound(
68 serialize = "G::Edge: Serialize",
69 deserialize = "G::Edge: Deserialize<'de>"
70))]
71#[derive_where(PartialEq; G: Graph)]
72#[derive_where(Eq; G: Graph)]
73#[derive_where(PartialOrd; G: Graph)]
74#[derive_where(Ord; G: Graph)]
75pub enum Port<G: Graph> {
76 Boundary(BoundaryIndex),
78 Bound(BoundPort<G::Edge>),
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
87pub struct BoundPort<E> {
88 pub edge: E,
90 pub end: EdgeEnd,
92}
93
94impl<G: Graph> Clone for Port<G> {
95 fn clone(&self) -> Self {
96 match self {
97 Self::Boundary(i) => Self::Boundary(*i),
98 Self::Bound(port) => Self::Bound(port.clone()),
99 }
100 }
101}
102
103impl<G: Graph> Copy for Port<G> where G::Edge: Copy {}
104
105impl<G: Graph> Owned<Port<G>, G> {
106 pub fn site(&self) -> Option<Site<G::Node, G::PortLabel>> {
107 match self.data {
108 Port::Boundary(boundary) => self.owner.boundary_site(boundary).clone().try_into().ok(),
109 Port::Bound(port) => Some(self.owner.graph().get_port_site(port)),
110 }
111 }
112}
113
114impl<E: Copy> BoundPort<E> {
127 pub fn opposite(&self) -> Self {
128 Self {
129 edge: self.edge,
130 end: self.end.opposite(),
131 }
132 }
133}
134
135impl<G: Graph> TryFrom<BoundarySite<G>> for Site<G::Node, G::PortLabel> {
146 type Error = BoundarySite<G>;
147
148 fn try_from(value: BoundarySite<G>) -> Result<Self, Self::Error> {
149 value.try_into_site()
150 }
151}
152
153#[derive(Serialize, Deserialize, From)]
160#[derive_where(PartialEq, Eq, PartialOrd, Ord, Clone; G: Graph)]
161#[derive_where(Debug; G: Graph, G::Node: Debug, G::PortLabel: Debug)]
162#[derive_where(Hash; G: Graph, G::Node: Hash, G::PortLabel: Hash)]
163#[serde(bound(
164 serialize = "G::Node: Serialize, G::PortLabel: Serialize",
165 deserialize = "G::Node: Deserialize<'de>, G::PortLabel: Deserialize<'de>"
166))]
167pub enum BoundarySite<G: Graph> {
168 Site(Site<G::Node, G::PortLabel>),
169 Wire { id: usize, end: EdgeEnd },
170}
171
172impl<G: Graph> BoundarySite<G> {
173 pub fn try_as_site_ref(&self) -> Option<&Site<G::Node, G::PortLabel>> {
174 match self {
175 Self::Site(site) => Some(site),
176 Self::Wire { .. } => None,
177 }
178 }
179
180 pub fn try_into_site(self) -> Result<Site<G::Node, G::PortLabel>, Self> {
181 match self {
182 Self::Site(site) => Ok(site),
183 Self::Wire { .. } => Err(self),
184 }
185 }
186
187 pub fn unwrap_site(self) -> Site<G::Node, G::PortLabel> {
188 self.try_into_site().ok().unwrap()
189 }
190}