1use crate::coord::{Point, Trans};
8use crate::layer::LayerIndex;
9use smol_str::SmolStr;
10
11#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
12pub struct PortKindId(pub u32);
13
14impl PortKindId {
15 pub const ANY: Self = Self(0);
16}
17
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
19#[repr(u8)]
20pub enum Angle90 {
21 E = 0,
22 N = 1,
23 W = 2,
24 S = 3,
25}
26
27impl Angle90 {
28 pub fn degrees(self) -> i32 {
29 (self as i32) * 90
30 }
31
32 pub fn rotate(self, by: crate::coord::Rot4) -> Angle90 {
33 let s = self as u8;
34 let r = by as u8;
35 match (s + r) % 4 {
36 0 => Angle90::E,
37 1 => Angle90::N,
38 2 => Angle90::W,
39 _ => Angle90::S,
40 }
41 }
42}
43
44#[derive(Clone, Debug, PartialEq, Eq, Hash)]
45pub struct Port {
46 pub name: SmolStr,
47 pub kind: PortKindId,
48 pub center: Point,
49 pub angle: Angle90,
50 pub width: i64,
51 pub layer: LayerIndex,
52}
53
54impl Port {
55 pub fn new(
56 name: impl Into<SmolStr>,
57 layer: LayerIndex,
58 center: Point,
59 angle: Angle90,
60 width: i64,
61 ) -> Self {
62 Self {
63 name: name.into(),
64 kind: PortKindId::ANY,
65 center,
66 angle,
67 width,
68 layer,
69 }
70 }
71
72 pub fn with_kind(mut self, kind: PortKindId) -> Self {
73 self.kind = kind;
74 self
75 }
76
77 pub fn transform(&self, t: Trans) -> Port {
78 Port {
79 name: self.name.clone(),
80 kind: self.kind,
81 center: t.apply(self.center),
82 angle: if t.mirror {
83 let after_mirror = match self.angle {
85 Angle90::E => Angle90::E,
86 Angle90::N => Angle90::S,
87 Angle90::W => Angle90::W,
88 Angle90::S => Angle90::N,
89 };
90 after_mirror.rotate(t.rot)
91 } else {
92 self.angle.rotate(t.rot)
93 },
94 width: self.width,
95 layer: self.layer,
96 }
97 }
98}