refactor(layout): separate RecordingLayout as mutable borrowing wrapper

This commit is contained in:
Alain Emilia Anna Zscheile 2025-01-03 03:30:57 +01:00
parent 3b47c4a30e
commit b8cc0e0963
6 changed files with 219 additions and 248 deletions

View File

@ -86,7 +86,8 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn undo_pointroute(&mut self, band: BandTermsegIndex) -> Result<(), AutorouterError> {
self.board
.layout_mut()
.remove_band(&mut LayoutEdit::new(), band)
.recording(&mut LayoutEdit::new())
.remove_band(band)
.map_err(|_| AutorouterError::CouldNotRemoveBand(band))
}
@ -124,7 +125,8 @@ impl<M: AccessMesadata> Autorouter<M> {
.unwrap();
self.board
.layout_mut()
.remove_band(&mut LayoutEdit::new(), band)
.recording(&mut LayoutEdit::new())
.remove_band(band)
.map_err(|_| AutorouterError::CouldNotRemoveBand(band))?;
}

View File

@ -44,7 +44,8 @@ impl PlaceViaExecutionStepper {
autorouter
.board
.layout_mut()
.add_via(&mut edit, self.weight)?;
.recording(&mut edit)
.add_via(self.weight)?;
Ok(Some(edit))
} else {
Ok(None)

View File

@ -42,7 +42,11 @@ impl RemoveBandsExecutionStepper {
let mut edit = LayoutEdit::new();
for selector in self.selection.selectors() {
let band = autorouter.board.bandname_band(&selector.band).unwrap().0;
autorouter.board.layout_mut().remove_band(&mut edit, band);
autorouter
.board
.layout_mut()
.recording(&mut edit)
.remove_band(band);
}
Ok(Some(edit))
} else {

View File

@ -91,7 +91,10 @@ impl<M: AccessMesadata> Board<M> {
weight: FixedDotWeight,
maybe_pin: Option<String>,
) -> FixedDotIndex {
let dot = self.layout.add_fixed_dot_infringably(recorder, weight);
let dot = self
.layout
.recording(recorder)
.add_fixed_dot_infringably(weight);
if let Some(pin) = maybe_pin {
self.node_to_pinname
@ -112,7 +115,8 @@ impl<M: AccessMesadata> Board<M> {
) -> FixedDotIndex {
let dot = self
.layout
.add_poly_fixed_dot_infringably(recorder, weight, poly);
.recording(recorder)
.add_poly_fixed_dot_infringably(weight, poly);
if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) {
self.node_to_pinname
@ -135,7 +139,8 @@ impl<M: AccessMesadata> Board<M> {
) -> FixedSegIndex {
let seg = self
.layout
.add_fixed_seg_infringably(recorder, from, to, weight);
.recording(recorder)
.add_fixed_seg_infringably(from, to, weight);
if let Some(pin) = maybe_pin {
self.node_to_pinname
@ -158,7 +163,8 @@ impl<M: AccessMesadata> Board<M> {
) -> FixedSegIndex {
let seg = self
.layout
.add_poly_fixed_seg_infringably(recorder, from, to, weight, poly);
.recording(recorder)
.add_poly_fixed_seg_infringably(from, to, weight, poly);
if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) {
self.node_to_pinname
@ -177,7 +183,7 @@ impl<M: AccessMesadata> Board<M> {
weight: PolyWeight,
maybe_pin: Option<String>,
) -> GenericIndex<PolyWeight> {
let poly = self.layout.add_poly(recorder, weight);
let poly = self.layout.recording(recorder).add_poly(weight);
if let Some(pin) = maybe_pin {
self.node_to_pinname

View File

@ -22,7 +22,7 @@ use crate::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
},
Drawing, DrawingEdit, DrawingException, Infringement,
Drawing, DrawingEdit, DrawingException, Infringement, RecordingDrawing,
},
geometry::{edit::ApplyGeometryEdit, shape::Shape, GenericNode},
graph::{GenericIndex, GetPetgraphIndex},
@ -52,245 +52,27 @@ pub struct Layout<R> {
drawing: Drawing<CompoundWeight, R>,
}
pub struct RecordingLayout<'a, R> {
pub layout: &'a mut Layout<R>,
pub recorder: &'a mut LayoutEdit,
}
impl<R> Layout<R> {
#[inline(always)]
pub fn new(drawing: Drawing<CompoundWeight, R>) -> Self {
Self { drawing }
}
#[inline(always)]
pub fn recording<'a>(&'a mut self, recorder: &'a mut LayoutEdit) -> RecordingLayout<'a, R> {
RecordingLayout {
layout: self,
recorder,
}
}
}
impl<R: AccessRules> Layout<R> {
/// Insert [`Cane`] object into the [`Layout`]
pub fn insert_cane(
&mut self,
recorder: &mut LayoutEdit,
from: DotIndex,
around: GearIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Cane, DrawingException> {
self.drawing.recording(recorder).insert_cane(
from,
around,
dot_weight,
seg_weight,
bend_weight,
cw,
)
}
/// Remove [`Cane`] object from the [`Layout`]
pub fn remove_cane(&mut self, recorder: &mut LayoutEdit, cane: &Cane, face: LooseDotIndex) {
self.drawing.recording(recorder).remove_cane(cane, face)
}
#[debug_ensures(ret.is_ok() -> self.drawing.node_count() == old(self.drawing.node_count()) + weight.to_layer - weight.from_layer + 2)]
#[debug_ensures(ret.is_err() -> self.drawing.node_count() == old(self.drawing.node_count()))]
/// Insert [`Via`] into the [`Layout`]
pub fn add_via(
&mut self,
recorder: &mut LayoutEdit,
weight: ViaWeight,
) -> Result<GenericIndex<ViaWeight>, Infringement> {
let compound = self.drawing.recording(recorder).add_compound(weight.into());
let mut dots = vec![];
for layer in weight.from_layer..=weight.to_layer {
match self
.drawing
.recording(recorder)
.add_fixed_dot(FixedDotWeight {
circle: weight.circle,
layer,
maybe_net: weight.maybe_net,
}) {
Ok(dot) => {
self.drawing
.recording(recorder)
.add_to_compound(dot, compound);
dots.push(dot);
}
Err(err) => {
// Remove inserted dots.
self.drawing.recording(recorder).remove_compound(compound);
for dot in dots.iter().rev() {
self.drawing.recording(recorder).remove_fixed_dot(*dot);
}
return Err(err);
}
}
}
Ok(GenericIndex::<ViaWeight>::new(compound.petgraph_index()))
}
pub fn add_fixed_dot(
&mut self,
recorder: &mut LayoutEdit,
weight: FixedDotWeight,
) -> Result<FixedDotIndex, Infringement> {
self.drawing.recording(recorder).add_fixed_dot(weight)
}
pub fn add_fixed_dot_infringably(
&mut self,
recorder: &mut LayoutEdit,
weight: FixedDotWeight,
) -> FixedDotIndex {
self.drawing
.recording(recorder)
.add_fixed_dot_infringably(weight)
}
pub fn add_poly_fixed_dot(
&mut self,
recorder: &mut LayoutEdit,
weight: FixedDotWeight,
poly: GenericIndex<PolyWeight>,
) -> Result<FixedDotIndex, Infringement> {
let maybe_dot = self.drawing.recording(recorder).add_fixed_dot(weight);
if let Ok(dot) = maybe_dot {
self.drawing
.recording(recorder)
.add_to_compound(dot, poly.into());
}
maybe_dot
}
pub fn add_poly_fixed_dot_infringably(
&mut self,
recorder: &mut LayoutEdit,
weight: FixedDotWeight,
poly: GenericIndex<PolyWeight>,
) -> FixedDotIndex {
let dot = self
.drawing
.recording(recorder)
.add_fixed_dot_infringably(weight);
self.drawing
.recording(recorder)
.add_to_compound(dot, poly.into());
dot
}
pub fn add_fixed_seg(
&mut self,
recorder: &mut LayoutEdit,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> Result<FixedSegIndex, Infringement> {
self.drawing
.recording(recorder)
.add_fixed_seg(from, to, weight)
}
pub fn add_fixed_seg_infringably(
&mut self,
recorder: &mut LayoutEdit,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> FixedSegIndex {
self.drawing
.recording(recorder)
.add_fixed_seg_infringably(from, to, weight)
}
pub fn add_poly_fixed_seg(
&mut self,
recorder: &mut LayoutEdit,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
poly: GenericIndex<PolyWeight>,
) -> Result<FixedSegIndex, Infringement> {
let maybe_seg = self.add_fixed_seg(recorder, from, to, weight);
if let Ok(seg) = maybe_seg {
self.drawing
.recording(recorder)
.add_to_compound(seg, poly.into());
}
maybe_seg
}
pub fn add_poly_fixed_seg_infringably(
&mut self,
recorder: &mut LayoutEdit,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
poly: GenericIndex<PolyWeight>,
) -> FixedSegIndex {
let seg = self.add_fixed_seg_infringably(recorder, from, to, weight);
self.drawing
.recording(recorder)
.add_to_compound(seg, poly.into());
seg
}
pub fn add_lone_loose_seg(
&mut self,
recorder: &mut LayoutEdit,
from: FixedDotIndex,
to: FixedDotIndex,
weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> {
self.drawing
.recording(recorder)
.add_lone_loose_seg(from, to, weight)
}
pub fn add_seq_loose_seg(
&mut self,
recorder: &mut LayoutEdit,
from: DotIndex,
to: LooseDotIndex,
weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> {
self.drawing
.recording(recorder)
.add_seq_loose_seg(from, to, weight)
}
pub fn move_dot(
&mut self,
recorder: &mut LayoutEdit,
dot: DotIndex,
to: Point,
) -> Result<(), Infringement> {
self.drawing.recording(recorder).move_dot(dot, to)
}
pub fn add_poly(
&mut self,
recorder: &mut LayoutEdit,
weight: PolyWeight,
) -> GenericIndex<PolyWeight> {
GenericIndex::<PolyWeight>::new(
self.drawing
.recording(recorder)
.add_compound(CompoundWeight::Poly(weight))
.petgraph_index(),
)
}
pub fn remove_band(
&mut self,
recorder: &mut LayoutEdit,
band: BandTermsegIndex,
) -> Result<(), DrawingException> {
self.drawing.recording(recorder).remove_band(band)
}
pub fn polys<W: 'static>(
&self,
node: GenericIndex<W>,
@ -418,6 +200,179 @@ impl<R: AccessRules> Layout<R> {
}
}
impl<R: AccessRules> RecordingLayout<'_, R> {
fn recording_drawing(&mut self) -> RecordingDrawing<'_, CompoundWeight, R> {
self.layout.drawing.recording(self.recorder)
}
/// Insert [`Cane`] object into the [`Layout`]
pub fn insert_cane(
&mut self,
from: DotIndex,
around: GearIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Cane, DrawingException> {
self.recording_drawing()
.insert_cane(from, around, dot_weight, seg_weight, bend_weight, cw)
}
/// Remove [`Cane`] object from the [`Layout`]
pub fn remove_cane(&mut self, cane: &Cane, face: LooseDotIndex) {
self.recording_drawing().remove_cane(cane, face)
}
#[debug_ensures(ret.is_ok() -> self.drawing.node_count() == old(self.drawing.node_count()) + weight.to_layer - weight.from_layer + 2)]
#[debug_ensures(ret.is_err() -> self.drawing.node_count() == old(self.drawing.node_count()))]
/// Insert [`Via`] into the [`Layout`]
pub fn add_via(&mut self, weight: ViaWeight) -> Result<GenericIndex<ViaWeight>, Infringement> {
let compound = self.recording_drawing().add_compound(weight.into());
let mut dots = vec![];
for layer in weight.from_layer..=weight.to_layer {
match self.recording_drawing().add_fixed_dot(FixedDotWeight {
circle: weight.circle,
layer,
maybe_net: weight.maybe_net,
}) {
Ok(dot) => {
self.recording_drawing().add_to_compound(dot, compound);
dots.push(dot);
}
Err(err) => {
// Remove inserted dots.
self.recording_drawing().remove_compound(compound);
for dot in dots.iter().rev() {
self.recording_drawing().remove_fixed_dot(*dot);
}
return Err(err);
}
}
}
Ok(GenericIndex::<ViaWeight>::new(compound.petgraph_index()))
}
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
self.recording_drawing().add_fixed_dot(weight)
}
pub fn add_fixed_dot_infringably(&mut self, weight: FixedDotWeight) -> FixedDotIndex {
self.recording_drawing().add_fixed_dot_infringably(weight)
}
pub fn add_poly_fixed_dot(
&mut self,
weight: FixedDotWeight,
poly: GenericIndex<PolyWeight>,
) -> Result<FixedDotIndex, Infringement> {
let maybe_dot = self.recording_drawing().add_fixed_dot(weight);
if let Ok(dot) = maybe_dot {
self.recording_drawing().add_to_compound(dot, poly.into());
}
maybe_dot
}
pub fn add_poly_fixed_dot_infringably(
&mut self,
weight: FixedDotWeight,
poly: GenericIndex<PolyWeight>,
) -> FixedDotIndex {
let dot = self.recording_drawing().add_fixed_dot_infringably(weight);
self.recording_drawing().add_to_compound(dot, poly.into());
dot
}
pub fn add_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> Result<FixedSegIndex, Infringement> {
self.recording_drawing().add_fixed_seg(from, to, weight)
}
pub fn add_fixed_seg_infringably(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> FixedSegIndex {
self.recording_drawing()
.add_fixed_seg_infringably(from, to, weight)
}
pub fn add_poly_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
poly: GenericIndex<PolyWeight>,
) -> Result<FixedSegIndex, Infringement> {
let maybe_seg = self.add_fixed_seg(from, to, weight);
if let Ok(seg) = maybe_seg {
self.recording_drawing().add_to_compound(seg, poly.into());
}
maybe_seg
}
pub fn add_poly_fixed_seg_infringably(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
poly: GenericIndex<PolyWeight>,
) -> FixedSegIndex {
let seg = self.add_fixed_seg_infringably(from, to, weight);
self.recording_drawing().add_to_compound(seg, poly.into());
seg
}
pub fn add_lone_loose_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> {
self.recording_drawing()
.add_lone_loose_seg(from, to, weight)
}
pub fn add_seq_loose_seg(
&mut self,
from: DotIndex,
to: LooseDotIndex,
weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> {
self.recording_drawing().add_seq_loose_seg(from, to, weight)
}
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
self.recording_drawing().move_dot(dot, to)
}
pub fn add_poly(&mut self, weight: PolyWeight) -> GenericIndex<PolyWeight> {
GenericIndex::<PolyWeight>::new(
self.recording_drawing()
.add_compound(CompoundWeight::Poly(weight))
.petgraph_index(),
)
}
pub fn remove_band(&mut self, band: BandTermsegIndex) -> Result<(), DrawingException> {
self.recording_drawing().remove_band(band)
}
}
impl<R: AccessRules>
ApplyGeometryEdit<
PrimitiveWeight,

View File

@ -73,8 +73,8 @@ impl<'a, R: AccessRules> Draw<'a, R> {
Ok(match head.face() {
DotIndex::Fixed(dot) => BandTermsegIndex::Straight(
self.layout
.recording(recorder)
.add_lone_loose_seg(
recorder,
dot,
into,
LoneLooseSegWeight {
@ -87,8 +87,8 @@ impl<'a, R: AccessRules> Draw<'a, R> {
),
DotIndex::Loose(dot) => BandTermsegIndex::Bended(
self.layout
.recording(recorder)
.add_seq_loose_seg(
recorder,
into.into(),
dot,
SeqLooseSegWeight {
@ -184,7 +184,9 @@ impl<'a, R: AccessRules> Draw<'a, R> {
to: Point,
) -> Result<Head, Infringement> {
if let Head::Cane(head) = head {
self.layout.move_dot(recorder, head.face.into(), to)?;
self.layout
.recording(recorder)
.move_dot(head.face.into(), to)?;
Ok(Head::Cane(head))
} else {
Ok(head)
@ -205,8 +207,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
) -> Result<CaneHead, DrawingException> {
let layer = head.face().primitive(self.layout.drawing()).layer();
let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net();
let cane = self.layout.insert_cane(
recorder,
let cane = self.layout.recording(recorder).insert_cane(
head.face(),
around,
LooseDotWeight {
@ -249,7 +250,9 @@ impl<'a, R: AccessRules> Draw<'a, R> {
.primitive(head.cane.seg)
.other_joint(head.cane.dot.into());
self.layout.remove_cane(recorder, &head.cane, head.face);
self.layout
.recording(recorder)
.remove_cane(&head.cane, head.face);
Some(self.guide().head(prev_dot))
}