use enum_dispatch::enum_dispatch; use petgraph::stable_graph::NodeIndex; use crate::{ drawing::{ bend::{BendIndex, FixedBendIndex, LooseBendIndex}, dot::FixedDotIndex, graph::{MakePrimitive, PrimitiveIndex}, primitive::{FixedBend, FixedDot, GetFirstGear, GetInnerOuter, LooseBend, Primitive}, rules::AccessRules, Drawing, }, graph::{GetPetgraphIndex, MakeRef}, }; #[enum_dispatch] pub trait GetNextGear: GetPetgraphIndex { fn next_gear(&self) -> Option; } #[enum_dispatch(GetPetgraphIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum GearIndex { FixedDot(FixedDotIndex), FixedBend(FixedBendIndex), LooseBend(LooseBendIndex), } impl<'a, CW: Copy, R: AccessRules> MakeRef<'a, GearRef<'a, CW, R>, Drawing> for GearIndex { fn ref_(&self, drawing: &'a Drawing) -> GearRef<'a, CW, R> { GearRef::new(*self, drawing) } } impl From for PrimitiveIndex { fn from(wraparoundable: GearIndex) -> Self { match wraparoundable { GearIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot), GearIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend), GearIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend), } } } impl From for GearIndex { fn from(bend: BendIndex) -> Self { match bend { BendIndex::Fixed(bend) => GearIndex::FixedBend(bend), BendIndex::Loose(bend) => GearIndex::LooseBend(bend), } } } #[enum_dispatch(GetNextGear, GetDrawing, GetPetgraphIndex)] pub enum GearRef<'a, CW: Copy, R: AccessRules> { FixedDot(FixedDot<'a, CW, R>), FixedBend(FixedBend<'a, CW, R>), LooseBend(LooseBend<'a, CW, R>), } impl<'a, CW: Copy, R: AccessRules> GearRef<'a, CW, R> { pub fn new(index: GearIndex, drawing: &'a Drawing) -> Self { match index { GearIndex::FixedDot(dot) => drawing.primitive(dot).into(), GearIndex::FixedBend(bend) => drawing.primitive(bend).into(), GearIndex::LooseBend(bend) => drawing.primitive(bend).into(), } } } impl<'a, CW: Copy, R: AccessRules> GetNextGear for FixedDot<'a, CW, R> { fn next_gear(&self) -> Option { self.first_gear() } } impl<'a, CW: Copy, R: AccessRules> GetNextGear for LooseBend<'a, CW, R> { fn next_gear(&self) -> Option { self.outer() } } impl<'a, CW: Copy, R: AccessRules> GetNextGear for FixedBend<'a, CW, R> { fn next_gear(&self) -> Option { self.first_gear() } }