use crate::coord::{Point, Trans};
use crate::layer::LayerIndex;
use smol_str::SmolStr;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct PortKindId(pub u32);
impl PortKindId {
pub const ANY: Self = Self(0);
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Angle90 {
E = 0,
N = 1,
W = 2,
S = 3,
}
impl Angle90 {
pub fn degrees(self) -> i32 {
(self as i32) * 90
}
pub fn rotate(self, by: crate::coord::Rot4) -> Angle90 {
let s = self as u8;
let r = by as u8;
match (s + r) % 4 {
0 => Angle90::E,
1 => Angle90::N,
2 => Angle90::W,
_ => Angle90::S,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Port {
pub name: SmolStr,
pub kind: PortKindId,
pub center: Point,
pub angle: Angle90,
pub width: i64,
pub layer: LayerIndex,
}
impl Port {
pub fn new(
name: impl Into<SmolStr>,
layer: LayerIndex,
center: Point,
angle: Angle90,
width: i64,
) -> Self {
Self {
name: name.into(),
kind: PortKindId::ANY,
center,
angle,
width,
layer,
}
}
pub fn with_kind(mut self, kind: PortKindId) -> Self {
self.kind = kind;
self
}
pub fn transform(&self, t: Trans) -> Port {
Port {
name: self.name.clone(),
kind: self.kind,
center: t.apply(self.center),
angle: if t.mirror {
let after_mirror = match self.angle {
Angle90::E => Angle90::E,
Angle90::N => Angle90::S,
Angle90::W => Angle90::W,
Angle90::S => Angle90::N,
};
after_mirror.rotate(t.rot)
} else {
self.angle.rotate(t.rot)
},
width: self.width,
layer: self.layer,
}
}
}