use enum_dispatch::enum_dispatch; use petgraph::stable_graph::NodeIndex; use std::{ hash::{Hash, Hasher}, marker::PhantomData, }; use crate::{ layout::Layout, math::Circle, primitive::{GenericPrimitive, Primitive}, }; pub trait Interior { fn interior(&self) -> Vec; } pub trait GetEnds { fn ends(&self) -> (F, T); } #[enum_dispatch] pub trait Retag { fn retag(&self, index: NodeIndex) -> Index; } #[enum_dispatch] pub trait GetNet { fn net(&self) -> i64; } pub trait GetNetMut { fn net_mut(&mut self) -> &mut i64; } pub trait GetBand { fn band(&self) -> usize; } #[enum_dispatch] pub trait GetWidth { fn width(&self) -> f64; } pub trait GetOffset { fn offset(&self) -> f64; } macro_rules! impl_weight { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { impl Retag for $weight_struct { fn retag(&self, index: NodeIndex) -> Index { Index::$weight_variant($index_struct { node_index: index, marker: PhantomData, }) } } pub type $index_struct = GenericIndex<$weight_struct>; impl MakePrimitive for $index_struct { fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a> { Primitive::$weight_variant(GenericPrimitive::new(*self, layout)) } } }; } macro_rules! impl_fixed_weight { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { impl_weight!($weight_struct, $weight_variant, $index_struct); impl GetNet for $weight_struct { fn net(&self) -> i64 { self.net } } impl GetNetMut for $weight_struct { fn net_mut(&mut self) -> &mut i64 { &mut self.net } } }; } macro_rules! impl_loose_weight { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { impl_weight!($weight_struct, $weight_variant, $index_struct); impl GetBand for $weight_struct { fn band(&self) -> usize { self.band } } }; } #[enum_dispatch(Retag)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum Weight { FixedDot(FixedDotWeight), LooseDot(LooseDotWeight), FixedSeg(FixedSegWeight), LooseSeg(LooseSegWeight), FixedBend(FixedBendWeight), LooseBend(LooseBendWeight), } #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum Index { FixedDot(FixedDotIndex), LooseDot(LooseDotIndex), FixedSeg(FixedSegIndex), LooseSeg(LooseSegIndex), FixedBend(FixedBendIndex), LooseBend(LooseBendIndex), } #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum DotIndex { Fixed(FixedDotIndex), Loose(LooseDotIndex), } impl From for Index { fn from(dot: DotIndex) -> Self { match dot { DotIndex::Fixed(fixed) => Index::FixedDot(fixed), DotIndex::Loose(loose) => Index::LooseDot(loose), } } } #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum SegIndex { Fixed(FixedSegIndex), Loose(LooseSegIndex), } impl From for Index { fn from(seg: SegIndex) -> Self { match seg { SegIndex::Fixed(seg) => Index::FixedSeg(seg), SegIndex::Loose(seg) => Index::LooseSeg(seg), } } } #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum BendIndex { Fixed(FixedBendIndex), Loose(LooseBendIndex), } impl From for Index { fn from(bend: BendIndex) -> Self { match bend { BendIndex::Fixed(bend) => Index::FixedBend(bend), BendIndex::Loose(bend) => Index::LooseBend(bend), } } } pub trait DotWeight: GetWidth + Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedDotWeight { pub net: i64, pub circle: Circle, } impl_fixed_weight!(FixedDotWeight, FixedDot, FixedDotIndex); impl DotWeight for FixedDotWeight {} impl GetWidth for FixedDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 } } #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseDotWeight { pub band: usize, pub circle: Circle, } impl_loose_weight!(LooseDotWeight, LooseDot, LooseDotIndex); impl DotWeight for LooseDotWeight {} impl GetWidth for LooseDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 } } pub trait SegWeight: Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedSegWeight { pub net: i64, pub width: f64, } impl_fixed_weight!(FixedSegWeight, FixedSeg, FixedSegIndex); impl SegWeight for FixedSegWeight {} impl GetWidth for FixedSegWeight { fn width(&self) -> f64 { self.width } } #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseSegWeight { pub band: usize, } impl_loose_weight!(LooseSegWeight, LooseSeg, LooseSegIndex); impl SegWeight for LooseSegWeight {} pub trait BendWeight: Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedBendWeight { pub net: i64, pub width: f64, pub cw: bool, } impl_fixed_weight!(FixedBendWeight, FixedBend, FixedBendIndex); impl BendWeight for FixedBendWeight {} impl GetWidth for FixedBendWeight { fn width(&self) -> f64 { self.width } } #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseBendWeight { pub band: usize, pub offset: f64, pub cw: bool, } impl GetOffset for LooseBendWeight { fn offset(&self) -> f64 { self.offset } } impl_loose_weight!(LooseBendWeight, LooseBend, LooseBendIndex); impl BendWeight for LooseBendWeight {} #[derive(Debug, Clone, Copy, PartialEq)] pub enum Label { Adjacent, Outer, Core, } #[enum_dispatch] pub trait GetNodeIndex { fn node_index(&self) -> NodeIndex; } #[enum_dispatch] pub trait MakePrimitive { fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>; } #[derive(Debug, Clone, Copy)] pub struct GenericIndex { node_index: NodeIndex, marker: PhantomData, } impl GenericIndex { pub fn new(index: NodeIndex) -> Self { Self { node_index: index, marker: PhantomData, } } } impl Hash for GenericIndex { fn hash(&self, state: &mut H) { self.node_index.hash(state) } } impl PartialEq for GenericIndex { fn eq(&self, other: &Self) -> bool { self.node_index == other.node_index } } impl Eq for GenericIndex {} impl GetNodeIndex for GenericIndex { fn node_index(&self) -> NodeIndex { self.node_index } }