// SPDX-FileCopyrightText: 2024 Topola contributors // // SPDX-License-Identifier: MIT use enum_dispatch::enum_dispatch; use petgraph::stable_graph::NodeIndex; use crate::{ geometry::GetLayer, graph::{GenericIndex, GetPetgraphIndex}, }; use super::{ bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, dot::{FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, primitive::Primitive, rules::AccessRules, seg::{ FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight, }, Drawing, }; #[enum_dispatch] pub trait IsInLayer { fn is_in_layer(&self, layer: usize) -> bool; fn is_in_any_layer_of(&self, layers: &[bool]) -> bool; } impl IsInLayer for T { #[inline] fn is_in_layer(&self, layer: usize) -> bool { self.layer() == layer } fn is_in_any_layer_of(&self, layers: &[bool]) -> bool { *layers.get(self.layer()).unwrap_or(&false) } } #[enum_dispatch] pub trait GetMaybeNet { fn maybe_net(&self) -> Option; } #[enum_dispatch] pub trait MakePrimitive { fn primitive<'a, CW: Clone, Cek: Copy, R: AccessRules>( &self, drawing: &'a Drawing, ) -> Primitive<'a, CW, Cek, R>; } macro_rules! impl_weight_forward { ($weight_struct:ty, $weight_variant:ident, $index_struct:ident) => { impl GetLayer for $weight_struct { fn layer(&self) -> usize { self.0.layer() } } impl GetMaybeNet for $weight_struct { fn maybe_net(&self) -> Option { self.0.maybe_net() } } impl GetWidth for $weight_struct { fn width(&self) -> f64 { self.0.width() } } pub type $index_struct = GenericIndex<$weight_struct>; impl MakePrimitive for $index_struct { fn primitive<'a, CW: Clone, Cek: Copy, R: AccessRules>( &self, drawing: &'a crate::drawing::Drawing, ) -> Primitive<'a, CW, Cek, R> { Primitive::$weight_variant(GenericPrimitive::new(*self, drawing)) } } }; } // TODO: This enum shouldn't exist: we shouldn't be carrying the tag around like this. Instead we // should be getting it from the graph when it's needed. #[enum_dispatch(GetPetgraphIndex, MakePrimitive)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum PrimitiveIndex { FixedDot(FixedDotIndex), LooseDot(LooseDotIndex), FixedSeg(FixedSegIndex), LoneLooseSeg(LoneLooseSegIndex), SeqLooseSeg(SeqLooseSegIndex), FixedBend(FixedBendIndex), LooseBend(LooseBendIndex), } #[enum_dispatch(GetWidth, GetLayer)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum PrimitiveWeight { FixedDot(FixedDotWeight), LooseDot(LooseDotWeight), FixedSeg(FixedSegWeight), LoneLooseSeg(LoneLooseSegWeight), SeqLooseSeg(SeqLooseSegWeight), FixedBend(FixedBendWeight), LooseBend(LooseBendWeight), } impl crate::geometry::Retag for PrimitiveWeight { type Index = PrimitiveIndex; fn retag(&self, index: NodeIndex) -> PrimitiveIndex { macro_rules! match_self { ($self:expr, $($kind:ident),*,) => {{ match $self { $(PrimitiveWeight::$kind(_) => PrimitiveIndex::$kind(GenericIndex::new(index))),* } }} } match_self!( self, FixedDot, LooseDot, FixedSeg, LoneLooseSeg, SeqLooseSeg, FixedBend, LooseBend, ) } }