From 64d8b2117d8040ef5adf8f067233f45f7a30a052 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Sat, 23 May 2026 23:18:22 +0300 Subject: [PATCH] refactor(entities): macro-ize EntityTypeOps dispatch Each of the five dispatch functions in `entities/traits.rs` was a hand-written `match self { EntityType::Line(e) => ..., EntityType::Arc(e) => ..., ... }` block listing ~35 variants. Adding a new entity meant adding five match arms across the file. Replace with a `dispatch!` macro that takes `(self, |e| body, [variant list], _ => default)`. Each dispatch function keeps its own variant list (the supported sets differ per trait), but the per-arm boilerplate is gone. File shrinks from 386 to 145 lines. Adding a new entity now means adding one identifier to one (or more) of the variant lists. Co-Authored-By: Claude Opus 4.7 --- src/entities/traits.rs | 408 +++++++++-------------------------------- 1 file changed, 87 insertions(+), 321 deletions(-) diff --git a/src/entities/traits.rs b/src/entities/traits.rs index 5cfdcf454..bcce509ac 100644 --- a/src/entities/traits.rs +++ b/src/entities/traits.rs @@ -40,346 +40,112 @@ pub trait EntityTypeOps { fn apply_transform(&mut self, t: &EntityTransform); } +/// Per-dispatch-function entity-variant lists. Adding a new entity that +/// participates in a dispatch = adding one identifier to one list here +/// (instead of one full match arm to each of five `match self` blocks). +/// +/// `dispatch!` expands `EntityType::$Variant(e) => $body` for each name. +macro_rules! dispatch { + ($self:expr, |$e:ident| $body:expr, [$($variant:ident),* $(,)?], _ => $default:expr $(,)?) => { + match $self { + $(EntityType::$variant($e) => $body,)* + _ => $default, + } + }; +} + impl EntityTypeOps for EntityType { fn to_truck_entity(&self, document: &CadDocument) -> Option { - match self { - EntityType::Point(pt) => TruckConvertible::to_truck(pt, document), - EntityType::Line(line) => TruckConvertible::to_truck(line, document), - EntityType::Circle(circle) => TruckConvertible::to_truck(circle, document), - EntityType::Arc(arc) => TruckConvertible::to_truck(arc, document), - EntityType::Ellipse(ellipse) => TruckConvertible::to_truck(ellipse, document), - EntityType::Spline(spline) => TruckConvertible::to_truck(spline, document), - EntityType::LwPolyline(pline) => TruckConvertible::to_truck(pline, document), - EntityType::Polyline(pl) => TruckConvertible::to_truck(pl, document), - EntityType::Polyline2D(pl) => TruckConvertible::to_truck(pl, document), - EntityType::Polyline3D(pl) => TruckConvertible::to_truck(pl, document), - EntityType::Ray(ray) => TruckConvertible::to_truck(ray, document), - EntityType::XLine(xl) => TruckConvertible::to_truck(xl, document), - EntityType::RasterImage(img) => TruckConvertible::to_truck(img, document), - EntityType::Wipeout(wo) => TruckConvertible::to_truck(wo, document), - EntityType::AttributeDefinition(a) => TruckConvertible::to_truck(a, document), - EntityType::AttributeEntity(a) => TruckConvertible::to_truck(a, document), - EntityType::MLine(ml) => TruckConvertible::to_truck(ml, document), - EntityType::Tolerance(tol) => TruckConvertible::to_truck(tol, document), - EntityType::Solid(solid) => TruckConvertible::to_truck(solid, document), - EntityType::Face3D(f) => TruckConvertible::to_truck(f, document), - EntityType::PolygonMesh(pm) => TruckConvertible::to_truck(pm, document), - EntityType::PolyfaceMesh(pfm) => TruckConvertible::to_truck(pfm, document), - EntityType::Mesh(m) => TruckConvertible::to_truck(m, document), - EntityType::Table(tbl) => TruckConvertible::to_truck(tbl, document), - EntityType::Text(text) => TruckConvertible::to_truck(text, document), - EntityType::MText(text) => TruckConvertible::to_truck(text, document), - EntityType::Leader(leader) => TruckConvertible::to_truck(leader, document), - EntityType::MultiLeader(ml) => TruckConvertible::to_truck(ml, document), - EntityType::Underlay(ul) => TruckConvertible::to_truck(ul, document), - EntityType::Shape(shp) => TruckConvertible::to_truck(shp, document), - EntityType::Ole2Frame(ole) => TruckConvertible::to_truck(ole, document), + dispatch!(self, + |e| TruckConvertible::to_truck(e, document), + [ + Point, Line, Circle, Arc, Ellipse, Spline, LwPolyline, + Polyline, Polyline2D, Polyline3D, Ray, XLine, RasterImage, + Wipeout, AttributeDefinition, AttributeEntity, MLine, + Tolerance, Solid, Face3D, PolygonMesh, PolyfaceMesh, Mesh, + Table, Text, MText, Leader, MultiLeader, Underlay, Shape, + Ole2Frame, + ], _ => None, - } + ) } fn grips(&self) -> Vec { - match self { - EntityType::Line(line) => Grippable::grips(line), - EntityType::Circle(circle) => Grippable::grips(circle), - EntityType::Arc(arc) => Grippable::grips(arc), - EntityType::Ellipse(ellipse) => Grippable::grips(ellipse), - EntityType::LwPolyline(pline) => Grippable::grips(pline), - EntityType::Polyline(pl) => Grippable::grips(pl), - EntityType::Polyline2D(pl) => Grippable::grips(pl), - EntityType::Polyline3D(pl) => Grippable::grips(pl), - EntityType::Ray(ray) => Grippable::grips(ray), - EntityType::XLine(xl) => Grippable::grips(xl), - EntityType::RasterImage(img) => Grippable::grips(img), - EntityType::Wipeout(wo) => Grippable::grips(wo), - EntityType::AttributeDefinition(a) => Grippable::grips(a), - EntityType::AttributeEntity(a) => Grippable::grips(a), - EntityType::MLine(ml) => Grippable::grips(ml), - EntityType::Tolerance(tol) => Grippable::grips(tol), - EntityType::Solid(solid) => Grippable::grips(solid), - EntityType::Solid3D(s) => Grippable::grips(s), - EntityType::Region(r) => Grippable::grips(r), - EntityType::Body(b) => Grippable::grips(b), - EntityType::Face3D(f) => Grippable::grips(f), - EntityType::PolygonMesh(pm) => Grippable::grips(pm), - EntityType::PolyfaceMesh(pfm) => Grippable::grips(pfm), - EntityType::Mesh(m) => Grippable::grips(m), - EntityType::Table(tbl) => Grippable::grips(tbl), - EntityType::Point(pt) => Grippable::grips(pt), - EntityType::Spline(spline) => Grippable::grips(spline), - EntityType::Text(text) => Grippable::grips(text), - EntityType::MText(text) => Grippable::grips(text), - EntityType::Viewport(vp) => Grippable::grips(vp), - EntityType::Insert(ins) => Grippable::grips(ins), - EntityType::Leader(leader) => Grippable::grips(leader), - EntityType::MultiLeader(ml) => Grippable::grips(ml), - EntityType::Dimension(dim) => Grippable::grips(dim), - EntityType::Hatch(hatch) => Grippable::grips(hatch), - EntityType::Underlay(ul) => Grippable::grips(ul), - EntityType::Shape(shp) => Grippable::grips(shp), - EntityType::Ole2Frame(ole) => Grippable::grips(ole), + dispatch!(self, + |e| Grippable::grips(e), + [ + Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D, + Polyline3D, Ray, XLine, RasterImage, Wipeout, + AttributeDefinition, AttributeEntity, MLine, Tolerance, + Solid, Solid3D, Region, Body, Face3D, PolygonMesh, + PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText, + Viewport, Insert, Leader, MultiLeader, Dimension, Hatch, + Underlay, Shape, Ole2Frame, + ], _ => vec![], - } + ) } fn geometry_properties(&self, text_style_names: &[String]) -> Option { - match self { - EntityType::Line(line) => Some(PropertyEditable::geometry_properties( - line, - text_style_names, - )), - EntityType::Circle(circle) => Some(PropertyEditable::geometry_properties( - circle, - text_style_names, - )), - EntityType::Arc(arc) => { - Some(PropertyEditable::geometry_properties(arc, text_style_names)) - } - EntityType::Ellipse(ellipse) => Some(PropertyEditable::geometry_properties( - ellipse, - text_style_names, - )), - EntityType::LwPolyline(pline) => Some(PropertyEditable::geometry_properties( - pline, - text_style_names, - )), - EntityType::Polyline(pl) => { - Some(PropertyEditable::geometry_properties(pl, text_style_names)) - } - EntityType::Polyline2D(pl) => { - Some(PropertyEditable::geometry_properties(pl, text_style_names)) - } - EntityType::Polyline3D(pl) => { - Some(PropertyEditable::geometry_properties(pl, text_style_names)) - } - EntityType::Ray(ray) => { - Some(PropertyEditable::geometry_properties(ray, text_style_names)) - } - EntityType::XLine(xl) => { - Some(PropertyEditable::geometry_properties(xl, text_style_names)) - } - EntityType::RasterImage(img) => { - Some(PropertyEditable::geometry_properties(img, text_style_names)) - } - EntityType::Wipeout(wo) => { - Some(PropertyEditable::geometry_properties(wo, text_style_names)) - } - EntityType::AttributeDefinition(a) => { - Some(PropertyEditable::geometry_properties(a, text_style_names)) - } - EntityType::AttributeEntity(a) => { - Some(PropertyEditable::geometry_properties(a, text_style_names)) - } - EntityType::MLine(ml) => { - Some(PropertyEditable::geometry_properties(ml, text_style_names)) - } - EntityType::Tolerance(tol) => { - Some(PropertyEditable::geometry_properties(tol, text_style_names)) - } - EntityType::Solid(solid) => Some(PropertyEditable::geometry_properties( - solid, - text_style_names, - )), - EntityType::Solid3D(s) => { - Some(PropertyEditable::geometry_properties(s, text_style_names)) - } - EntityType::Region(r) => { - Some(PropertyEditable::geometry_properties(r, text_style_names)) - } - EntityType::Body(b) => Some(PropertyEditable::geometry_properties(b, text_style_names)), - EntityType::Face3D(f) => { - Some(PropertyEditable::geometry_properties(f, text_style_names)) - } - EntityType::PolygonMesh(pm) => { - Some(PropertyEditable::geometry_properties(pm, text_style_names)) - } - EntityType::PolyfaceMesh(pfm) => { - Some(PropertyEditable::geometry_properties(pfm, text_style_names)) - } - EntityType::Mesh(m) => { - Some(PropertyEditable::geometry_properties(m, text_style_names)) - } - EntityType::Table(tbl) => { - Some(PropertyEditable::geometry_properties(tbl, text_style_names)) - } - EntityType::Hatch(hatch) => Some(PropertyEditable::geometry_properties( - hatch, - text_style_names, - )), - EntityType::Point(pt) => { - Some(PropertyEditable::geometry_properties(pt, text_style_names)) - } - EntityType::Spline(spline) => Some(PropertyEditable::geometry_properties( - spline, - text_style_names, - )), - EntityType::Text(text) => Some(PropertyEditable::geometry_properties( - text, - text_style_names, - )), - EntityType::MText(text) => Some(PropertyEditable::geometry_properties( - text, - text_style_names, - )), - EntityType::Viewport(vp) => { - Some(PropertyEditable::geometry_properties(vp, text_style_names)) - } - EntityType::Insert(ins) => { - Some(PropertyEditable::geometry_properties(ins, text_style_names)) - } - EntityType::Dimension(dim) => { - Some(PropertyEditable::geometry_properties(dim, text_style_names)) - } - EntityType::Leader(leader) => Some(PropertyEditable::geometry_properties( - leader, - text_style_names, - )), - EntityType::MultiLeader(ml) => { - Some(PropertyEditable::geometry_properties(ml, text_style_names)) - } - EntityType::Underlay(ul) => { - Some(PropertyEditable::geometry_properties(ul, text_style_names)) - } - EntityType::Shape(shp) => { - Some(PropertyEditable::geometry_properties(shp, text_style_names)) - } - EntityType::Ole2Frame(ole) => { - Some(PropertyEditable::geometry_properties(ole, text_style_names)) - } + dispatch!(self, + |e| Some(PropertyEditable::geometry_properties(e, text_style_names)), + [ + Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D, + Polyline3D, Ray, XLine, RasterImage, Wipeout, + AttributeDefinition, AttributeEntity, MLine, Tolerance, + Solid, Solid3D, Region, Body, Face3D, PolygonMesh, + PolyfaceMesh, Mesh, Table, Hatch, Point, Spline, Text, MText, + Viewport, Insert, Dimension, Leader, MultiLeader, Underlay, + Shape, Ole2Frame, + ], _ => None, - } + ) } fn apply_geom_prop(&mut self, field: &str, value: &str) { - match self { - EntityType::Line(line) => PropertyEditable::apply_geom_prop(line, field, value), - EntityType::Circle(circle) => PropertyEditable::apply_geom_prop(circle, field, value), - EntityType::Arc(arc) => PropertyEditable::apply_geom_prop(arc, field, value), - EntityType::Ellipse(ellipse) => { - PropertyEditable::apply_geom_prop(ellipse, field, value) - } - EntityType::LwPolyline(pline) => PropertyEditable::apply_geom_prop(pline, field, value), - EntityType::Polyline(pl) => PropertyEditable::apply_geom_prop(pl, field, value), - EntityType::Polyline2D(pl) => PropertyEditable::apply_geom_prop(pl, field, value), - EntityType::Polyline3D(pl) => PropertyEditable::apply_geom_prop(pl, field, value), - EntityType::Ray(ray) => PropertyEditable::apply_geom_prop(ray, field, value), - EntityType::XLine(xl) => PropertyEditable::apply_geom_prop(xl, field, value), - EntityType::RasterImage(img) => PropertyEditable::apply_geom_prop(img, field, value), - EntityType::Wipeout(wo) => PropertyEditable::apply_geom_prop(wo, field, value), - EntityType::AttributeDefinition(a) => { - PropertyEditable::apply_geom_prop(a, field, value) - } - EntityType::AttributeEntity(a) => PropertyEditable::apply_geom_prop(a, field, value), - EntityType::MLine(ml) => PropertyEditable::apply_geom_prop(ml, field, value), - EntityType::Tolerance(tol) => PropertyEditable::apply_geom_prop(tol, field, value), - EntityType::Solid(solid) => PropertyEditable::apply_geom_prop(solid, field, value), - EntityType::Solid3D(s) => PropertyEditable::apply_geom_prop(s, field, value), - EntityType::Region(r) => PropertyEditable::apply_geom_prop(r, field, value), - EntityType::Body(b) => PropertyEditable::apply_geom_prop(b, field, value), - EntityType::Face3D(f) => PropertyEditable::apply_geom_prop(f, field, value), - EntityType::PolygonMesh(pm) => PropertyEditable::apply_geom_prop(pm, field, value), - EntityType::PolyfaceMesh(pfm) => PropertyEditable::apply_geom_prop(pfm, field, value), - EntityType::Mesh(m) => PropertyEditable::apply_geom_prop(m, field, value), - EntityType::Table(tbl) => PropertyEditable::apply_geom_prop(tbl, field, value), - EntityType::Hatch(hatch) => PropertyEditable::apply_geom_prop(hatch, field, value), - EntityType::Point(pt) => PropertyEditable::apply_geom_prop(pt, field, value), - EntityType::Spline(spline) => PropertyEditable::apply_geom_prop(spline, field, value), - EntityType::Text(text) => PropertyEditable::apply_geom_prop(text, field, value), - EntityType::MText(text) => PropertyEditable::apply_geom_prop(text, field, value), - EntityType::Viewport(vp) => PropertyEditable::apply_geom_prop(vp, field, value), - EntityType::Insert(ins) => PropertyEditable::apply_geom_prop(ins, field, value), - EntityType::Dimension(dim) => PropertyEditable::apply_geom_prop(dim, field, value), - EntityType::Leader(leader) => PropertyEditable::apply_geom_prop(leader, field, value), - EntityType::MultiLeader(ml) => PropertyEditable::apply_geom_prop(ml, field, value), - EntityType::Underlay(ul) => PropertyEditable::apply_geom_prop(ul, field, value), - EntityType::Shape(shp) => PropertyEditable::apply_geom_prop(shp, field, value), - EntityType::Ole2Frame(ole) => PropertyEditable::apply_geom_prop(ole, field, value), - _ => {} - } + dispatch!(self, + |e| PropertyEditable::apply_geom_prop(e, field, value), + [ + Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D, + Polyline3D, Ray, XLine, RasterImage, Wipeout, + AttributeDefinition, AttributeEntity, MLine, Tolerance, + Solid, Solid3D, Region, Body, Face3D, PolygonMesh, + PolyfaceMesh, Mesh, Table, Hatch, Point, Spline, Text, MText, + Viewport, Insert, Dimension, Leader, MultiLeader, Underlay, + Shape, Ole2Frame, + ], + _ => {}, + ) } fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { - match self { - EntityType::Line(line) => Grippable::apply_grip(line, grip_id, apply), - EntityType::Circle(circle) => Grippable::apply_grip(circle, grip_id, apply), - EntityType::Arc(arc) => Grippable::apply_grip(arc, grip_id, apply), - EntityType::Ellipse(ellipse) => Grippable::apply_grip(ellipse, grip_id, apply), - EntityType::LwPolyline(pline) => Grippable::apply_grip(pline, grip_id, apply), - EntityType::Polyline(pl) => Grippable::apply_grip(pl, grip_id, apply), - EntityType::Polyline2D(pl) => Grippable::apply_grip(pl, grip_id, apply), - EntityType::Polyline3D(pl) => Grippable::apply_grip(pl, grip_id, apply), - EntityType::Ray(ray) => Grippable::apply_grip(ray, grip_id, apply), - EntityType::XLine(xl) => Grippable::apply_grip(xl, grip_id, apply), - EntityType::RasterImage(img) => Grippable::apply_grip(img, grip_id, apply), - EntityType::Wipeout(wo) => Grippable::apply_grip(wo, grip_id, apply), - EntityType::AttributeDefinition(a) => Grippable::apply_grip(a, grip_id, apply), - EntityType::AttributeEntity(a) => Grippable::apply_grip(a, grip_id, apply), - EntityType::MLine(ml) => Grippable::apply_grip(ml, grip_id, apply), - EntityType::Tolerance(tol) => Grippable::apply_grip(tol, grip_id, apply), - EntityType::Solid(solid) => Grippable::apply_grip(solid, grip_id, apply), - EntityType::Solid3D(s) => Grippable::apply_grip(s, grip_id, apply), - EntityType::Region(r) => Grippable::apply_grip(r, grip_id, apply), - EntityType::Body(b) => Grippable::apply_grip(b, grip_id, apply), - EntityType::Face3D(f) => Grippable::apply_grip(f, grip_id, apply), - EntityType::PolygonMesh(pm) => Grippable::apply_grip(pm, grip_id, apply), - EntityType::PolyfaceMesh(pfm) => Grippable::apply_grip(pfm, grip_id, apply), - EntityType::Mesh(m) => Grippable::apply_grip(m, grip_id, apply), - EntityType::Table(tbl) => Grippable::apply_grip(tbl, grip_id, apply), - EntityType::Point(pt) => Grippable::apply_grip(pt, grip_id, apply), - EntityType::Spline(spline) => Grippable::apply_grip(spline, grip_id, apply), - EntityType::Text(text) => Grippable::apply_grip(text, grip_id, apply), - EntityType::MText(text) => Grippable::apply_grip(text, grip_id, apply), - EntityType::Viewport(vp) => Grippable::apply_grip(vp, grip_id, apply), - EntityType::Insert(ins) => Grippable::apply_grip(ins, grip_id, apply), - EntityType::Leader(leader) => Grippable::apply_grip(leader, grip_id, apply), - EntityType::MultiLeader(ml) => Grippable::apply_grip(ml, grip_id, apply), - EntityType::Dimension(dim) => Grippable::apply_grip(dim, grip_id, apply), - EntityType::Hatch(hatch) => Grippable::apply_grip(hatch, grip_id, apply), - EntityType::Underlay(ul) => Grippable::apply_grip(ul, grip_id, apply), - EntityType::Shape(shp) => Grippable::apply_grip(shp, grip_id, apply), - EntityType::Ole2Frame(ole) => Grippable::apply_grip(ole, grip_id, apply), - _ => {} - } + dispatch!(self, + |e| Grippable::apply_grip(e, grip_id, apply), + [ + Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D, + Polyline3D, Ray, XLine, RasterImage, Wipeout, + AttributeDefinition, AttributeEntity, MLine, Tolerance, + Solid, Solid3D, Region, Body, Face3D, PolygonMesh, + PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText, + Viewport, Insert, Leader, MultiLeader, Dimension, Hatch, + Underlay, Shape, Ole2Frame, + ], + _ => {}, + ) } fn apply_transform(&mut self, t: &EntityTransform) { - match self { - EntityType::Arc(arc) => Transformable::apply_transform(arc, t), - EntityType::Circle(circle) => Transformable::apply_transform(circle, t), - EntityType::Ellipse(ellipse) => Transformable::apply_transform(ellipse, t), - EntityType::Hatch(hatch) => Transformable::apply_transform(hatch, t), - EntityType::Insert(ins) => Transformable::apply_transform(ins, t), - EntityType::Line(line) => Transformable::apply_transform(line, t), - EntityType::LwPolyline(pline) => Transformable::apply_transform(pline, t), - EntityType::Polyline(pl) => Transformable::apply_transform(pl, t), - EntityType::Polyline2D(pl) => Transformable::apply_transform(pl, t), - EntityType::Polyline3D(pl) => Transformable::apply_transform(pl, t), - EntityType::Ray(ray) => Transformable::apply_transform(ray, t), - EntityType::XLine(xl) => Transformable::apply_transform(xl, t), - EntityType::RasterImage(img) => Transformable::apply_transform(img, t), - EntityType::Wipeout(wo) => Transformable::apply_transform(wo, t), - EntityType::AttributeDefinition(a) => Transformable::apply_transform(a, t), - EntityType::AttributeEntity(a) => Transformable::apply_transform(a, t), - EntityType::MLine(ml) => Transformable::apply_transform(ml, t), - EntityType::Tolerance(tol) => Transformable::apply_transform(tol, t), - EntityType::Solid(solid) => Transformable::apply_transform(solid, t), - EntityType::Face3D(f) => Transformable::apply_transform(f, t), - EntityType::PolygonMesh(pm) => Transformable::apply_transform(pm, t), - EntityType::PolyfaceMesh(pfm) => Transformable::apply_transform(pfm, t), - EntityType::Mesh(m) => Transformable::apply_transform(m, t), - EntityType::Table(tbl) => Transformable::apply_transform(tbl, t), - EntityType::MText(text) => Transformable::apply_transform(text, t), - EntityType::Point(pt) => Transformable::apply_transform(pt, t), - EntityType::Spline(spline) => Transformable::apply_transform(spline, t), - EntityType::Text(text) => Transformable::apply_transform(text, t), - EntityType::Viewport(vp) => Transformable::apply_transform(vp, t), - EntityType::Dimension(dim) => Transformable::apply_transform(dim, t), - EntityType::Leader(leader) => Transformable::apply_transform(leader, t), - EntityType::MultiLeader(ml) => Transformable::apply_transform(ml, t), - EntityType::Underlay(ul) => Transformable::apply_transform(ul, t), - EntityType::Shape(shp) => Transformable::apply_transform(shp, t), - EntityType::Ole2Frame(ole) => Transformable::apply_transform(ole, t), - _ => {} - } + dispatch!(self, + |e| Transformable::apply_transform(e, t), + [ + Arc, Circle, Ellipse, Hatch, Insert, Line, LwPolyline, + Polyline, Polyline2D, Polyline3D, Ray, XLine, RasterImage, + Wipeout, AttributeDefinition, AttributeEntity, MLine, + Tolerance, Solid, Face3D, PolygonMesh, PolyfaceMesh, Mesh, + Table, MText, Point, Spline, Text, Viewport, Dimension, + Leader, MultiLeader, Underlay, Shape, Ole2Frame, + ], + _ => {}, + ) } }