From 19a1d033d815931e946289924a65307efea4a04a Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sat, 16 Dec 2023 21:35:18 -0800 Subject: [PATCH 01/20] Initial implementation of validating HalfEdges only used by one Cycle in Sketch --- crates/fj-core/src/validate/mod.rs | 6 +- crates/fj-core/src/validate/sketch.rs | 105 +++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/crates/fj-core/src/validate/mod.rs b/crates/fj-core/src/validate/mod.rs index 3fac7d5bf..148eef5ed 100644 --- a/crates/fj-core/src/validate/mod.rs +++ b/crates/fj-core/src/validate/mod.rs @@ -86,7 +86,7 @@ mod vertex; pub use self::{ cycle::CycleValidationError, edge::EdgeValidationError, face::FaceValidationError, shell::ShellValidationError, - solid::SolidValidationError, + sketch::SketchValidationError, solid::SolidValidationError, }; use std::{convert::Infallible, fmt}; @@ -190,6 +190,10 @@ pub enum ValidationError { /// `Solid` validation error #[error("`Solid` validation error")] Solid(#[from] SolidValidationError), + + /// `Sketch` validation error + #[error("`Sketch` validation error")] + Sketch(#[from] SketchValidationError), } impl From for ValidationError { diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index d3eefbebe..69db9ecc6 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -1,12 +1,111 @@ -use crate::objects::Sketch; +use crate::{ + objects::{HalfEdge, Sketch}, + storage::Handle, +}; use super::{Validate, ValidationConfig, ValidationError}; impl Validate for Sketch { fn validate_with_config( &self, - _: &ValidationConfig, - _: &mut Vec, + config: &ValidationConfig, + errors: &mut Vec, ) { + SketchValidationError::check_obect_references(self, config, errors); + } +} + +/// [`Sketch`] validation failed +#[derive(Clone, Debug, thiserror::Error)] +pub enum SketchValidationError { + /// [`HalfEdge`] referenced by more than one [`Cycle`] + #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] + HalfEdgeMultipleReferences, + /// [`Cycle`] referenced by more than one [`Region`] + #[error("[`Cycle`] referenced by more than one [`Region`]")] + CycleMultipleReferences, +} + +impl SketchValidationError { + fn check_obect_references( + sketch: &Sketch, + _config: &ValidationConfig, + errors: &mut Vec, + ) { + let mut referenced_edges = + std::collections::HashMap::, i32>::new(); + + // Do we care about how many times each edge is used, or should we just return as soon as + // we find one that is used more than once? + sketch.regions().iter().for_each(|r| { + r.all_cycles().for_each(|c| { + c.half_edges().into_iter().for_each(|e| { + referenced_edges.insert(e.clone(), { + if let Some(count) = referenced_edges.get(e) { + count + 1 + } else { + 1 + } + }); + }) + }) + }); + + referenced_edges.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::HalfEdgeMultipleReferences.into()); + } + }) + } +} + +#[cfg(test)] +mod tests { + use crate::{ + assert_contains_err, + objects::{Cycle, HalfEdge, Region, Sketch}, + operations::build::BuildHalfEdge, + services::Services, + storage::Store, + validate::{SketchValidationError, Validate, ValidationError}, + }; + + #[test] + fn should_find_half_edge_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let mut cycle_store: Store = Store::new(); + let mut region_store: Store = Store::new(); + let mut half_edge_store: Store = Store::new(); + + let half_edge = half_edge_store.reserve(); + half_edge_store.insert( + half_edge.clone(), + HalfEdge::line_segment([[0., 0.], [1., 0.]], None, &mut services), + ); + + let exterior = cycle_store.reserve(); + cycle_store + .insert(exterior.clone(), Cycle::new(vec![half_edge.clone()])); + let interior = cycle_store.reserve(); + cycle_store + .insert(interior.clone(), Cycle::new(vec![half_edge.clone()])); + + let region = region_store.reserve(); + region_store.insert( + region.clone(), + Region::new(exterior, vec![interior], None), + ); + + let sketch = Sketch::new(vec![region]); + + assert_contains_err!( + sketch, + ValidationError::Sketch( + SketchValidationError::HalfEdgeMultipleReferences + ) + ); + + Ok(()) } } From bfde2c7c37dbb35f8ad32bba2a9a8fd03f4e462e Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 00:16:41 -0800 Subject: [PATCH 02/20] Test that validation succeeds for valid sketch as well as fails for invalid sketch --- crates/fj-core/src/validate/sketch.rs | 58 +++++++++++++++------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 69db9ecc6..81bc4eeb6 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -63,49 +63,55 @@ impl SketchValidationError { mod tests { use crate::{ assert_contains_err, - objects::{Cycle, HalfEdge, Region, Sketch}, - operations::build::BuildHalfEdge, + objects::{Cycle, HalfEdge, Region, Sketch, Vertex}, + operations::{build::BuildHalfEdge, insert::Insert}, services::Services, - storage::Store, validate::{SketchValidationError, Validate, ValidationError}, }; #[test] fn should_find_half_edge_multiple_references() -> anyhow::Result<()> { + // Test setup let mut services = Services::new(); - let mut cycle_store: Store = Store::new(); - let mut region_store: Store = Store::new(); - let mut half_edge_store: Store = Store::new(); + let half_edge = + HalfEdge::line_segment([[0., 0.], [1., 0.]], None, &mut services) + .insert(&mut services); + let sibling_edge = HalfEdge::from_sibling( + &half_edge, + Vertex::new().insert(&mut services), + ) + .insert(&mut services); - let half_edge = half_edge_store.reserve(); - half_edge_store.insert( - half_edge.clone(), - HalfEdge::line_segment([[0., 0.], [1., 0.]], None, &mut services), - ); - - let exterior = cycle_store.reserve(); - cycle_store - .insert(exterior.clone(), Cycle::new(vec![half_edge.clone()])); - let interior = cycle_store.reserve(); - cycle_store - .insert(interior.clone(), Cycle::new(vec![half_edge.clone()])); + let exterior = + Cycle::new(vec![half_edge.clone(), sibling_edge.clone()]) + .insert(&mut services); - let region = region_store.reserve(); - region_store.insert( - region.clone(), - Region::new(exterior, vec![interior], None), - ); - - let sketch = Sketch::new(vec![region]); + let interior = + Cycle::new(vec![half_edge.clone(), sibling_edge.clone()]) + .insert(&mut services); + // Test validation fails for invalid setup + let invalid_sketch = Sketch::new(vec![Region::new( + exterior.clone(), + vec![interior], + None, + ) + .insert(&mut services)]); assert_contains_err!( - sketch, + invalid_sketch, ValidationError::Sketch( SketchValidationError::HalfEdgeMultipleReferences ) ); + // Test validation succeeds for valid setup + let valid_sketch = + Sketch::new(vec![ + Region::new(exterior, vec![], None).insert(&mut services) + ]); + valid_sketch.validate_and_return_first_error()?; + Ok(()) } } From bb9703805f0a88f029e89d5f7a8983798e4be332 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 14:42:10 -0800 Subject: [PATCH 03/20] Implement validation of Cycle references within Sketch Regions --- crates/fj-core/src/validate/sketch.rs | 58 +++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 81bc4eeb6..534da7afa 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -1,5 +1,5 @@ use crate::{ - objects::{HalfEdge, Sketch}, + objects::{Cycle, HalfEdge, Sketch}, storage::Handle, }; @@ -32,13 +32,22 @@ impl SketchValidationError { _config: &ValidationConfig, errors: &mut Vec, ) { + // todo: store referencing objects instead of just a reference count so that we can surface + // them in the error message let mut referenced_edges = std::collections::HashMap::, i32>::new(); + let mut referenced_cycles = + std::collections::HashMap::, i32>::new(); - // Do we care about how many times each edge is used, or should we just return as soon as - // we find one that is used more than once? sketch.regions().iter().for_each(|r| { r.all_cycles().for_each(|c| { + referenced_cycles.insert(c.clone(), { + if let Some(count) = referenced_cycles.get(c) { + count + 1 + } else { + 1 + } + }); c.half_edges().into_iter().for_each(|e| { referenced_edges.insert(e.clone(), { if let Some(count) = referenced_edges.get(e) { @@ -51,11 +60,16 @@ impl SketchValidationError { }) }); + referenced_cycles.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::CycleMultipleReferences.into()); + } + }); referenced_edges.iter().for_each(|(_, count)| { if count > &1 { errors.push(Self::HalfEdgeMultipleReferences.into()); } - }) + }); } } @@ -69,9 +83,41 @@ mod tests { validate::{SketchValidationError, Validate, ValidationError}, }; + #[test] + fn should_find_cycle_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let shared_cycle = Cycle::new(vec![]).insert(&mut services); + + let invalid_sketch = Sketch::new(vec![ + Region::new( + Cycle::new(vec![]).insert(&mut services), + vec![shared_cycle.clone()], + None, + ) + .insert(&mut services), + Region::new(shared_cycle, vec![], None).insert(&mut services), + ]); + assert_contains_err!( + invalid_sketch, + ValidationError::Sketch( + SketchValidationError::CycleMultipleReferences + ) + ); + + let valid_sketch = Sketch::new(vec![Region::new( + Cycle::new(vec![]).insert(&mut services), + vec![], + None, + ) + .insert(&mut services)]); + valid_sketch.validate_and_return_first_error()?; + + Ok(()) + } + #[test] fn should_find_half_edge_multiple_references() -> anyhow::Result<()> { - // Test setup let mut services = Services::new(); let half_edge = @@ -91,7 +137,6 @@ mod tests { Cycle::new(vec![half_edge.clone(), sibling_edge.clone()]) .insert(&mut services); - // Test validation fails for invalid setup let invalid_sketch = Sketch::new(vec![Region::new( exterior.clone(), vec![interior], @@ -105,7 +150,6 @@ mod tests { ) ); - // Test validation succeeds for valid setup let valid_sketch = Sketch::new(vec![ Region::new(exterior, vec![], None).insert(&mut services) From 01d976e0861def14c1d5a1834ad2704e3767601a Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 15:04:47 -0800 Subject: [PATCH 04/20] Implement Solid reference count validation --- crates/fj-core/src/validate/solid.rs | 117 ++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 0e830d913..712718ee6 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -1,7 +1,7 @@ use std::iter::repeat; use crate::{ - objects::{Solid, Vertex}, + objects::{Cycle, Face, HalfEdge, Region, Solid, Vertex}, storage::Handle, }; use fj_math::Point; @@ -14,7 +14,8 @@ impl Validate for Solid { config: &ValidationConfig, errors: &mut Vec, ) { - SolidValidationError::check_vertices(self, config, errors) + SolidValidationError::check_vertices(self, config, errors); + SolidValidationError::check_object_references(self, config, errors); } } @@ -60,6 +61,18 @@ pub enum SolidValidationError { /// Position of second vertex position_b: Point<3>, }, + /// [`Region`] referenced by multiple faces + #[error("Region referenced by multiple faces")] + RegionMultipleReferences, + /// [`Face`] referenced by multiple shells + #[error("Face referenced by multiple shells")] + FaceMultipleReferences, + /// [`HalfEdge`] referenced by more than one [`Cycle`] + #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] + HalfEdgeMultipleReferences, + /// [`Cycle`] referenced by more than one [`Region`] + #[error("[`Cycle`] referenced by more than one [`Region`]")] + CycleMultipleReferences, } impl SolidValidationError { @@ -127,4 +140,104 @@ impl SolidValidationError { } } } + + fn check_object_references( + solid: &Solid, + _config: &ValidationConfig, + errors: &mut Vec, + ) { + // todo: store referencing objects instead of just a reference count so that we can surface + // them in the error message + let mut referenced_regions = + std::collections::HashMap::, i32>::new(); + let mut referenced_faces = + std::collections::HashMap::, i32>::new(); + let mut referenced_edges = + std::collections::HashMap::, i32>::new(); + let mut referenced_cycles = + std::collections::HashMap::, i32>::new(); + + referenced_cycles.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::CycleMultipleReferences.into()); + } + }); + referenced_edges.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::HalfEdgeMultipleReferences.into()); + } + }); + + solid.shells().iter().for_each(|s| { + s.faces().into_iter().for_each(|f| { + referenced_faces.insert(f.clone(), { + if let Some(count) = referenced_faces.get(f) { + count + 1 + } else { + 1 + } + }); + + referenced_regions.insert(f.region().clone(), { + if let Some(count) = referenced_regions.get(f.region()) { + count + 1 + } else { + 1 + } + }); + f.region().all_cycles().for_each(|c| { + referenced_cycles.insert(c.clone(), { + if let Some(count) = referenced_cycles.get(c) { + count + 1 + } else { + 1 + } + }); + c.half_edges().into_iter().for_each(|e| { + referenced_edges.insert(e.clone(), { + if let Some(count) = referenced_edges.get(e) { + count + 1 + } else { + 1 + } + }); + }) + }) + }) + }); + + referenced_faces.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::FaceMultipleReferences.into()); + } + }); + referenced_regions.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::RegionMultipleReferences.into()); + } + }); + } +} + +#[cfg(test)] +mod tests { + #[test] + fn should_find_face_multiple_references() { + unimplemented!(); + } + + #[test] + fn should_find_region_multiple_references() { + unimplemented!(); + } + + #[test] + fn should_find_cycle_multiple_references() { + unimplemented!(); + } + + #[test] + fn should_find_half_edge_multiple_references() { + unimplemented!(); + } } From f4d6c924c2fefc104eda972359f193ebb13a9205 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 17:24:37 -0800 Subject: [PATCH 05/20] fix reference checks in wrong place --- crates/fj-core/src/validate/solid.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 712718ee6..874c09a71 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -157,17 +157,6 @@ impl SolidValidationError { let mut referenced_cycles = std::collections::HashMap::, i32>::new(); - referenced_cycles.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::CycleMultipleReferences.into()); - } - }); - referenced_edges.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::HalfEdgeMultipleReferences.into()); - } - }); - solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { referenced_faces.insert(f.clone(), { @@ -216,6 +205,16 @@ impl SolidValidationError { errors.push(Self::RegionMultipleReferences.into()); } }); + referenced_cycles.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::CycleMultipleReferences.into()); + } + }); + referenced_edges.iter().for_each(|(_, count)| { + if count > &1 { + errors.push(Self::HalfEdgeMultipleReferences.into()); + } + }); } } From 0e672fe0583c1a311f3cf3428a626a722129259a Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 21:41:36 -0800 Subject: [PATCH 06/20] Unit test shell object reference validations --- crates/fj-core/src/services/service.rs | 8 +- crates/fj-core/src/validate/solid.rs | 199 ++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 9 deletions(-) diff --git a/crates/fj-core/src/services/service.rs b/crates/fj-core/src/services/service.rs index 4317fa61d..bacacd8b4 100644 --- a/crates/fj-core/src/services/service.rs +++ b/crates/fj-core/src/services/service.rs @@ -1,4 +1,4 @@ -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; /// A service that controls access to some state /// @@ -62,6 +62,12 @@ impl Deref for Service { } } +impl DerefMut for Service { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.state + } +} + impl Default for Service where S: Default, diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 874c09a71..624685b6c 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -220,23 +220,206 @@ impl SolidValidationError { #[cfg(test)] mod tests { + use crate::{ + assert_contains_err, + geometry::{GlobalPath, SurfaceGeometry}, + objects::{Cycle, Face, HalfEdge, Region, Shell, Solid, Surface}, + operations::{ + build::{BuildFace, BuildHalfEdge}, + insert::Insert, + }, + services::Services, + validate::{SolidValidationError, Validate, ValidationError}, + }; + #[test] - fn should_find_face_multiple_references() { - unimplemented!(); + fn should_find_face_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let shared_face = Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 1., 1.].into(), + }) + .insert(&mut services), + Region::new( + Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut services) + .insert(&mut services)]) + .insert(&mut services), + vec![], + None, + ) + .insert(&mut services), + ) + .insert(&mut services); + + let invalid_solid = Solid::new(vec![ + Shell::new(vec![shared_face.clone()]).insert(&mut services), + Shell::new(vec![ + shared_face, + Face::triangle( + [[0., 0., 0.], [1., 0., 0.], [1., 1., 0.]], + &mut services, + ) + .insert(&mut services) + .face, + ]) + .insert(&mut services), + ]) + .insert(&mut services); + + assert_contains_err!( + invalid_solid, + ValidationError::Solid( + SolidValidationError::FaceMultipleReferences + ) + ); + + let valid_solid = Solid::new(vec![]).insert(&mut services); + valid_solid.validate_and_return_first_error()?; + + services.validation.errors.clear(); + + Ok(()) } #[test] - fn should_find_region_multiple_references() { - unimplemented!(); + fn should_find_region_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let shared_region = Region::new( + Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut services) + .insert(&mut services)]) + .insert(&mut services), + vec![], + None, + ) + .insert(&mut services); + + let invalid_solid = Solid::new(vec![Shell::new(vec![ + Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 1., 1.].into(), + }) + .insert(&mut services), + shared_region.clone(), + ) + .insert(&mut services), + Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 0., 1.].into(), + }) + .insert(&mut services), + shared_region.clone(), + ) + .insert(&mut services), + ]) + .insert(&mut services)]) + .insert(&mut services); + + assert_contains_err!( + invalid_solid, + ValidationError::Solid( + SolidValidationError::RegionMultipleReferences + ) + ); + + let valid_solid = Solid::new(vec![]).insert(&mut services); + valid_solid.validate_and_return_first_error()?; + + services.validation.errors.clear(); + + Ok(()) } #[test] - fn should_find_cycle_multiple_references() { - unimplemented!(); + fn should_find_cycle_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let shared_cycle = + Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut services) + .insert(&mut services)]) + .insert(&mut services); + + let invalid_solid = Solid::new(vec![Shell::new(vec![ + Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 1., 1.].into(), + }) + .insert(&mut services), + Region::new(shared_cycle.clone(), vec![], None) + .insert(&mut services), + ) + .insert(&mut services), + Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 0., 1.].into(), + }) + .insert(&mut services), + Region::new(shared_cycle, vec![], None).insert(&mut services), + ) + .insert(&mut services), + ]) + .insert(&mut services)]) + .insert(&mut services); + + assert_contains_err!( + invalid_solid, + ValidationError::Solid( + SolidValidationError::CycleMultipleReferences + ) + ); + + let valid_solid = Solid::new(vec![]).insert(&mut services); + valid_solid.validate_and_return_first_error()?; + + services.validation.errors.clear(); + + Ok(()) } #[test] - fn should_find_half_edge_multiple_references() { - unimplemented!(); + fn should_find_half_edge_multiple_references() -> anyhow::Result<()> { + let mut services = Services::new(); + + let shared_edge = + HalfEdge::circle([0., 0.], 1., &mut services).insert(&mut services); + + let invalid_solid = Solid::new(vec![Shell::new(vec![Face::new( + Surface::new(SurfaceGeometry { + u: GlobalPath::circle_from_radius(1.), + v: [0., 0., 1.].into(), + }) + .insert(&mut services), + Region::new( + Cycle::new(vec![shared_edge.clone()]).insert(&mut services), + vec![ + Cycle::new(vec![shared_edge.clone()]).insert(&mut services) + ], + None, + ) + .insert(&mut services), + ) + .insert(&mut services)]) + .insert(&mut services)]) + .insert(&mut services); + + assert_contains_err!( + invalid_solid, + ValidationError::Solid( + SolidValidationError::HalfEdgeMultipleReferences + ) + ); + + let valid_solid = Solid::new(vec![]).insert(&mut services); + valid_solid.validate_and_return_first_error()?; + + services.validation.errors.clear(); + + Ok(()) } } From 224f8925ffca4ab31925c9ee5077822b801664a8 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 21:46:58 -0800 Subject: [PATCH 07/20] Fix doc refence --- crates/fj-core/src/validate/sketch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 534da7afa..c4fd63316 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -21,7 +21,7 @@ pub enum SketchValidationError { /// [`HalfEdge`] referenced by more than one [`Cycle`] #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] HalfEdgeMultipleReferences, - /// [`Cycle`] referenced by more than one [`Region`] + /// [`Cycle`] referenced by more than one [`crate::objects::Region`] #[error("[`Cycle`] referenced by more than one [`Region`]")] CycleMultipleReferences, } From cf761c20cf97753131e083d1cf60004c972aa11b Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sun, 17 Dec 2023 23:34:15 -0800 Subject: [PATCH 08/20] Align error messages --- crates/fj-core/src/validate/solid.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 624685b6c..72b190459 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -61,11 +61,11 @@ pub enum SolidValidationError { /// Position of second vertex position_b: Point<3>, }, - /// [`Region`] referenced by multiple faces - #[error("Region referenced by multiple faces")] + /// [`Region`] referenced by more than one [`Face`] + #[error("[`Region`] referenced by more than one [`Face`]")] RegionMultipleReferences, - /// [`Face`] referenced by multiple shells - #[error("Face referenced by multiple shells")] + /// [`Face`] referenced by more than one [`crate::objects::Shell`] + #[error("[`Face`] referenced by more than one [`crate::objects::Shell`]")] FaceMultipleReferences, /// [`HalfEdge`] referenced by more than one [`Cycle`] #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] From a8e612a5d3b029051c5b412ab1e32cce9ffdbb34 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Thu, 28 Dec 2023 22:20:09 -0800 Subject: [PATCH 09/20] use hashmap entry api --- crates/fj-core/src/validate/sketch.rs | 22 +++++-------- crates/fj-core/src/validate/solid.rs | 46 ++++++++++----------------- 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index c4fd63316..b9ac400ef 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -41,21 +41,15 @@ impl SketchValidationError { sketch.regions().iter().for_each(|r| { r.all_cycles().for_each(|c| { - referenced_cycles.insert(c.clone(), { - if let Some(count) = referenced_cycles.get(c) { - count + 1 - } else { - 1 - } - }); + referenced_cycles + .entry(c.clone()) + .and_modify(|count| *count += 1) + .or_insert(1); c.half_edges().into_iter().for_each(|e| { - referenced_edges.insert(e.clone(), { - if let Some(count) = referenced_edges.get(e) { - count + 1 - } else { - 1 - } - }); + referenced_edges + .entry(e.clone()) + .and_modify(|count| *count += 1) + .or_insert(1); }) }) }); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 72b190459..e6f81118b 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -159,37 +159,25 @@ impl SolidValidationError { solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { - referenced_faces.insert(f.clone(), { - if let Some(count) = referenced_faces.get(f) { - count + 1 - } else { - 1 - } - }); - - referenced_regions.insert(f.region().clone(), { - if let Some(count) = referenced_regions.get(f.region()) { - count + 1 - } else { - 1 - } - }); + referenced_faces + .entry(f.clone()) + .and_modify(|count| *count += 1) + .or_insert(1); + + referenced_regions + .entry(f.region().clone()) + .and_modify(|count| *count += 1) + .or_insert(1); f.region().all_cycles().for_each(|c| { - referenced_cycles.insert(c.clone(), { - if let Some(count) = referenced_cycles.get(c) { - count + 1 - } else { - 1 - } - }); + referenced_cycles + .entry(c.clone()) + .and_modify(|count| *count += 1) + .or_insert(1); c.half_edges().into_iter().for_each(|e| { - referenced_edges.insert(e.clone(), { - if let Some(count) = referenced_edges.get(e) { - count + 1 - } else { - 1 - } - }); + referenced_edges + .entry(e.clone()) + .and_modify(|count| *count += 1) + .or_insert(1); }) }) }) From 56b387f276c0641726cb7025ca5a0e0b72a006ba Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Thu, 28 Dec 2023 22:38:40 -0800 Subject: [PATCH 10/20] create reference counter utility struct --- crates/fj-core/src/validate/mod.rs | 1 + crates/fj-core/src/validate/references.rs | 24 ++++++++ crates/fj-core/src/validate/sketch.rs | 41 +++++-------- crates/fj-core/src/validate/solid.rs | 72 ++++++++--------------- 4 files changed, 64 insertions(+), 74 deletions(-) create mode 100644 crates/fj-core/src/validate/references.rs diff --git a/crates/fj-core/src/validate/mod.rs b/crates/fj-core/src/validate/mod.rs index 148eef5ed..271d00a0c 100644 --- a/crates/fj-core/src/validate/mod.rs +++ b/crates/fj-core/src/validate/mod.rs @@ -76,6 +76,7 @@ mod curve; mod cycle; mod edge; mod face; +mod references; mod region; mod shell; mod sketch; diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs new file mode 100644 index 000000000..450f3f343 --- /dev/null +++ b/crates/fj-core/src/validate/references.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; +use std::hash::Hash; + +use crate::storage::Handle; + +#[derive(Default)] +pub struct ReferenceCounter(HashMap, i32>); + +impl ReferenceCounter { + pub fn new() -> Self { + Self(HashMap::new()) + } + + pub fn add_count(&mut self, object: Handle) { + self.0 + .entry(object) + .and_modify(|count| *count += 1) + .or_insert(1); + } + + pub fn has_multiple(&self) -> bool { + self.0.iter().any(|(_, count)| *count > 1) + } +} diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index b9ac400ef..1b4ce3029 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -1,9 +1,8 @@ -use crate::{ - objects::{Cycle, HalfEdge, Sketch}, - storage::Handle, -}; +use crate::objects::Sketch; -use super::{Validate, ValidationConfig, ValidationError}; +use super::{ + references::ReferenceCounter, Validate, ValidationConfig, ValidationError, +}; impl Validate for Sketch { fn validate_with_config( @@ -34,36 +33,24 @@ impl SketchValidationError { ) { // todo: store referencing objects instead of just a reference count so that we can surface // them in the error message - let mut referenced_edges = - std::collections::HashMap::, i32>::new(); - let mut referenced_cycles = - std::collections::HashMap::, i32>::new(); + let mut referenced_edges = ReferenceCounter::new(); + let mut referenced_cycles = ReferenceCounter::new(); sketch.regions().iter().for_each(|r| { r.all_cycles().for_each(|c| { - referenced_cycles - .entry(c.clone()) - .and_modify(|count| *count += 1) - .or_insert(1); + referenced_cycles.add_count(c.clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges - .entry(e.clone()) - .and_modify(|count| *count += 1) - .or_insert(1); + referenced_edges.add_count(e.clone()); }) }) }); - referenced_cycles.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::CycleMultipleReferences.into()); - } - }); - referenced_edges.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::HalfEdgeMultipleReferences.into()); - } - }); + if referenced_cycles.has_multiple() { + errors.push(Self::CycleMultipleReferences.into()); + }; + if referenced_edges.has_multiple() { + errors.push(Self::HalfEdgeMultipleReferences.into()); + }; } } diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index e6f81118b..3828ceba7 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -1,12 +1,14 @@ use std::iter::repeat; use crate::{ - objects::{Cycle, Face, HalfEdge, Region, Solid, Vertex}, + objects::{Solid, Vertex}, storage::Handle, }; use fj_math::Point; -use super::{Validate, ValidationConfig, ValidationError}; +use super::{ + references::ReferenceCounter, Validate, ValidationConfig, ValidationError, +}; impl Validate for Solid { fn validate_with_config( @@ -148,61 +150,37 @@ impl SolidValidationError { ) { // todo: store referencing objects instead of just a reference count so that we can surface // them in the error message - let mut referenced_regions = - std::collections::HashMap::, i32>::new(); - let mut referenced_faces = - std::collections::HashMap::, i32>::new(); - let mut referenced_edges = - std::collections::HashMap::, i32>::new(); - let mut referenced_cycles = - std::collections::HashMap::, i32>::new(); + let mut referenced_regions = ReferenceCounter::new(); + let mut referenced_faces = ReferenceCounter::new(); + let mut referenced_edges = ReferenceCounter::new(); + let mut referenced_cycles = ReferenceCounter::new(); solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { - referenced_faces - .entry(f.clone()) - .and_modify(|count| *count += 1) - .or_insert(1); - - referenced_regions - .entry(f.region().clone()) - .and_modify(|count| *count += 1) - .or_insert(1); + referenced_faces.add_count(f.clone()); + + referenced_regions.add_count(f.region().clone()); f.region().all_cycles().for_each(|c| { - referenced_cycles - .entry(c.clone()) - .and_modify(|count| *count += 1) - .or_insert(1); + referenced_cycles.add_count(c.clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges - .entry(e.clone()) - .and_modify(|count| *count += 1) - .or_insert(1); + referenced_edges.add_count(e.clone()); }) }) }) }); - referenced_faces.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::FaceMultipleReferences.into()); - } - }); - referenced_regions.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::RegionMultipleReferences.into()); - } - }); - referenced_cycles.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::CycleMultipleReferences.into()); - } - }); - referenced_edges.iter().for_each(|(_, count)| { - if count > &1 { - errors.push(Self::HalfEdgeMultipleReferences.into()); - } - }); + if referenced_faces.has_multiple() { + errors.push(Self::FaceMultipleReferences.into()); + } + if referenced_regions.has_multiple() { + errors.push(Self::RegionMultipleReferences.into()); + }; + if referenced_cycles.has_multiple() { + errors.push(Self::CycleMultipleReferences.into()); + }; + if referenced_edges.has_multiple() { + errors.push(Self::HalfEdgeMultipleReferences.into()); + }; } } From 5224cc17ebab6aa8e40d306cb122053c58d1e4f3 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Thu, 28 Dec 2023 23:25:25 -0800 Subject: [PATCH 11/20] write abstraction for validating reference counts --- crates/fj-core/src/validate/mod.rs | 5 +++ crates/fj-core/src/validate/references.rs | 46 ++++++++++++++++++-- crates/fj-core/src/validate/sketch.rs | 23 ++++------ crates/fj-core/src/validate/solid.rs | 52 ++++++----------------- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/crates/fj-core/src/validate/mod.rs b/crates/fj-core/src/validate/mod.rs index 271d00a0c..ddf0567d7 100644 --- a/crates/fj-core/src/validate/mod.rs +++ b/crates/fj-core/src/validate/mod.rs @@ -84,6 +84,7 @@ mod solid; mod surface; mod vertex; +use self::references::ReferenceCountError; pub use self::{ cycle::CycleValidationError, edge::EdgeValidationError, face::FaceValidationError, shell::ShellValidationError, @@ -195,6 +196,10 @@ pub enum ValidationError { /// `Sketch` validation error #[error("`Sketch` validation error")] Sketch(#[from] SketchValidationError), + + /// Reference validation error + #[error("`Reference` validation error")] + ReferenceCount(#[from] ReferenceCountError), } impl From for ValidationError { diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index 450f3f343..c8ea6a08a 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -1,8 +1,11 @@ use std::collections::HashMap; use std::hash::Hash; +use crate::objects::{Cycle, Face, HalfEdge, Region}; use crate::storage::Handle; +use super::ValidationError; + #[derive(Default)] pub struct ReferenceCounter(HashMap, i32>); @@ -17,8 +20,45 @@ impl ReferenceCounter { .and_modify(|count| *count += 1) .or_insert(1); } +} - pub fn has_multiple(&self) -> bool { - self.0.iter().any(|(_, count)| *count > 1) - } +pub trait ValidateReferences { + fn validate(&self, errors: &mut Vec); +} + +macro_rules! impl_validate { + ($($ty:ty, $err:path;)*) => { + $( + impl ValidateReferences for ReferenceCounter<$ty> { + fn validate(&self, errors: &mut Vec) { + if self.0.iter().any(|(_, count)| *count > 1) { + errors.push($err.into()); + } + } + } + )* + }; +} + +impl_validate!( + Region, ReferenceCountError::Region; + Face, ReferenceCountError::Face; + HalfEdge, ReferenceCountError::HalfEdge; + Cycle, ReferenceCountError::Cycle; +); + +#[derive(Clone, Debug, thiserror::Error)] +pub enum ReferenceCountError { + /// [`Region`] referenced by more than one [`Face`] + #[error("[`Region`] referenced by more than one [`Face`]")] + Region, + /// [`Face`] referenced by more than one [`crate::objects::Shell`] + #[error("[`Face`] referenced by more than one [`crate::objects::Shell`]")] + Face, + /// [`HalfEdge`] referenced by more than one [`Cycle`] + #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] + HalfEdge, + /// [`Cycle`] referenced by more than one [`Region`] + #[error("[`Cycle`] referenced by more than one [`Region`]")] + Cycle, } diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 1b4ce3029..155198ad0 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -1,7 +1,8 @@ use crate::objects::Sketch; use super::{ - references::ReferenceCounter, Validate, ValidationConfig, ValidationError, + references::{ReferenceCounter, ValidateReferences}, + Validate, ValidationConfig, ValidationError, }; impl Validate for Sketch { @@ -45,12 +46,8 @@ impl SketchValidationError { }) }); - if referenced_cycles.has_multiple() { - errors.push(Self::CycleMultipleReferences.into()); - }; - if referenced_edges.has_multiple() { - errors.push(Self::HalfEdgeMultipleReferences.into()); - }; + referenced_cycles.validate(errors); + referenced_edges.validate(errors); } } @@ -61,7 +58,9 @@ mod tests { objects::{Cycle, HalfEdge, Region, Sketch, Vertex}, operations::{build::BuildHalfEdge, insert::Insert}, services::Services, - validate::{SketchValidationError, Validate, ValidationError}, + validate::{ + references::ReferenceCountError, Validate, ValidationError, + }, }; #[test] @@ -81,9 +80,7 @@ mod tests { ]); assert_contains_err!( invalid_sketch, - ValidationError::Sketch( - SketchValidationError::CycleMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::Cycle) ); let valid_sketch = Sketch::new(vec![Region::new( @@ -126,9 +123,7 @@ mod tests { .insert(&mut services)]); assert_contains_err!( invalid_sketch, - ValidationError::Sketch( - SketchValidationError::HalfEdgeMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::HalfEdge) ); let valid_sketch = diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 3828ceba7..0c59a413b 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -7,7 +7,8 @@ use crate::{ use fj_math::Point; use super::{ - references::ReferenceCounter, Validate, ValidationConfig, ValidationError, + references::{ReferenceCounter, ValidateReferences}, + Validate, ValidationConfig, ValidationError, }; impl Validate for Solid { @@ -63,18 +64,6 @@ pub enum SolidValidationError { /// Position of second vertex position_b: Point<3>, }, - /// [`Region`] referenced by more than one [`Face`] - #[error("[`Region`] referenced by more than one [`Face`]")] - RegionMultipleReferences, - /// [`Face`] referenced by more than one [`crate::objects::Shell`] - #[error("[`Face`] referenced by more than one [`crate::objects::Shell`]")] - FaceMultipleReferences, - /// [`HalfEdge`] referenced by more than one [`Cycle`] - #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] - HalfEdgeMultipleReferences, - /// [`Cycle`] referenced by more than one [`Region`] - #[error("[`Cycle`] referenced by more than one [`Region`]")] - CycleMultipleReferences, } impl SolidValidationError { @@ -158,7 +147,6 @@ impl SolidValidationError { solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { referenced_faces.add_count(f.clone()); - referenced_regions.add_count(f.region().clone()); f.region().all_cycles().for_each(|c| { referenced_cycles.add_count(c.clone()); @@ -169,18 +157,10 @@ impl SolidValidationError { }) }); - if referenced_faces.has_multiple() { - errors.push(Self::FaceMultipleReferences.into()); - } - if referenced_regions.has_multiple() { - errors.push(Self::RegionMultipleReferences.into()); - }; - if referenced_cycles.has_multiple() { - errors.push(Self::CycleMultipleReferences.into()); - }; - if referenced_edges.has_multiple() { - errors.push(Self::HalfEdgeMultipleReferences.into()); - }; + referenced_faces.validate(errors); + referenced_regions.validate(errors); + referenced_cycles.validate(errors); + referenced_edges.validate(errors); } } @@ -195,7 +175,9 @@ mod tests { insert::Insert, }, services::Services, - validate::{SolidValidationError, Validate, ValidationError}, + validate::{ + references::ReferenceCountError, Validate, ValidationError, + }, }; #[test] @@ -236,9 +218,7 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::Solid( - SolidValidationError::FaceMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::Face) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -287,9 +267,7 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::Solid( - SolidValidationError::RegionMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::Region) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -335,9 +313,7 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::Solid( - SolidValidationError::CycleMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::Cycle) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -376,9 +352,7 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::Solid( - SolidValidationError::HalfEdgeMultipleReferences - ) + ValidationError::ReferenceCount(ReferenceCountError::HalfEdge) ); let valid_solid = Solid::new(vec![]).insert(&mut services); From 5a51f7d86cfef9a0320ebfc9ecb9e55108d53bd9 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 11:48:46 -0800 Subject: [PATCH 12/20] make reference count error be contained within the object's error type --- crates/fj-core/src/validate/mod.rs | 5 --- crates/fj-core/src/validate/references.rs | 28 +++++++---------- crates/fj-core/src/validate/sketch.rs | 25 ++++++++++----- crates/fj-core/src/validate/solid.rs | 37 +++++++++++++++++------ 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/crates/fj-core/src/validate/mod.rs b/crates/fj-core/src/validate/mod.rs index ddf0567d7..271d00a0c 100644 --- a/crates/fj-core/src/validate/mod.rs +++ b/crates/fj-core/src/validate/mod.rs @@ -84,7 +84,6 @@ mod solid; mod surface; mod vertex; -use self::references::ReferenceCountError; pub use self::{ cycle::CycleValidationError, edge::EdgeValidationError, face::FaceValidationError, shell::ShellValidationError, @@ -196,10 +195,6 @@ pub enum ValidationError { /// `Sketch` validation error #[error("`Sketch` validation error")] Sketch(#[from] SketchValidationError), - - /// Reference validation error - #[error("`Reference` validation error")] - ReferenceCount(#[from] ReferenceCountError), } impl From for ValidationError { diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index c8ea6a08a..76f529e0c 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::hash::Hash; -use crate::objects::{Cycle, Face, HalfEdge, Region}; use crate::storage::Handle; use super::ValidationError; @@ -20,33 +19,28 @@ impl ReferenceCounter { .and_modify(|count| *count += 1) .or_insert(1); } + + pub fn has_multiple(&self) -> bool { + self.0.iter().any(|(_, count)| *count > 1) + } } -pub trait ValidateReferences { +pub trait ValidateReferences { fn validate(&self, errors: &mut Vec); } -macro_rules! impl_validate { - ($($ty:ty, $err:path;)*) => { +/// Find errors and convert to [`ValidationError`] +#[macro_export] +macro_rules! validate_references { + ($errors:ident, $error_ty:ty;$($counter:ident, $err:expr;)*) => { $( - impl ValidateReferences for ReferenceCounter<$ty> { - fn validate(&self, errors: &mut Vec) { - if self.0.iter().any(|(_, count)| *count > 1) { - errors.push($err.into()); - } - } + if $counter.has_multiple() { + $errors.push(Into::<$error_ty>::into($err).into()); } )* }; } -impl_validate!( - Region, ReferenceCountError::Region; - Face, ReferenceCountError::Face; - HalfEdge, ReferenceCountError::HalfEdge; - Cycle, ReferenceCountError::Cycle; -); - #[derive(Clone, Debug, thiserror::Error)] pub enum ReferenceCountError { /// [`Region`] referenced by more than one [`Face`] diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 155198ad0..7c88b35ca 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -1,7 +1,7 @@ -use crate::objects::Sketch; +use crate::{objects::Sketch, validate_references}; use super::{ - references::{ReferenceCounter, ValidateReferences}, + references::{ReferenceCountError, ReferenceCounter}, Validate, ValidationConfig, ValidationError, }; @@ -24,6 +24,9 @@ pub enum SketchValidationError { /// [`Cycle`] referenced by more than one [`crate::objects::Region`] #[error("[`Cycle`] referenced by more than one [`Region`]")] CycleMultipleReferences, + /// Object within sketch referenced by more than one other object + #[error("Object referenced by more than one other Objects")] + MultipleReferences(#[from] ReferenceCountError), } impl SketchValidationError { @@ -46,8 +49,11 @@ impl SketchValidationError { }) }); - referenced_cycles.validate(errors); - referenced_edges.validate(errors); + validate_references!( + errors, SketchValidationError; + referenced_edges, ReferenceCountError::HalfEdge; + referenced_cycles, ReferenceCountError::Cycle; + ); } } @@ -59,7 +65,8 @@ mod tests { operations::{build::BuildHalfEdge, insert::Insert}, services::Services, validate::{ - references::ReferenceCountError, Validate, ValidationError, + references::ReferenceCountError, SketchValidationError, Validate, + ValidationError, }, }; @@ -80,7 +87,9 @@ mod tests { ]); assert_contains_err!( invalid_sketch, - ValidationError::ReferenceCount(ReferenceCountError::Cycle) + ValidationError::Sketch(SketchValidationError::MultipleReferences( + ReferenceCountError::Cycle + )) ); let valid_sketch = Sketch::new(vec![Region::new( @@ -123,7 +132,9 @@ mod tests { .insert(&mut services)]); assert_contains_err!( invalid_sketch, - ValidationError::ReferenceCount(ReferenceCountError::HalfEdge) + ValidationError::Sketch(SketchValidationError::MultipleReferences( + ReferenceCountError::HalfEdge + )) ); let valid_sketch = diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 0c59a413b..5c9497743 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -3,11 +3,12 @@ use std::iter::repeat; use crate::{ objects::{Solid, Vertex}, storage::Handle, + validate_references, }; use fj_math::Point; use super::{ - references::{ReferenceCounter, ValidateReferences}, + references::{ReferenceCountError, ReferenceCounter}, Validate, ValidationConfig, ValidationError, }; @@ -64,6 +65,10 @@ pub enum SolidValidationError { /// Position of second vertex position_b: Point<3>, }, + + /// Object within sketch referenced by more than one other object + #[error("Object referenced by more than one other Objects")] + MultipleReferences(#[from] ReferenceCountError), } impl SolidValidationError { @@ -157,10 +162,13 @@ impl SolidValidationError { }) }); - referenced_faces.validate(errors); - referenced_regions.validate(errors); - referenced_cycles.validate(errors); - referenced_edges.validate(errors); + validate_references!( + errors, SolidValidationError; + referenced_regions, ReferenceCountError::Region; + referenced_faces, ReferenceCountError::Face; + referenced_edges, ReferenceCountError::HalfEdge; + referenced_cycles, ReferenceCountError::Cycle; + ); } } @@ -176,7 +184,8 @@ mod tests { }, services::Services, validate::{ - references::ReferenceCountError, Validate, ValidationError, + references::ReferenceCountError, SolidValidationError, Validate, + ValidationError, }, }; @@ -218,7 +227,9 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::ReferenceCount(ReferenceCountError::Face) + ValidationError::Solid(SolidValidationError::MultipleReferences( + ReferenceCountError::Face + )) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -267,7 +278,9 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::ReferenceCount(ReferenceCountError::Region) + ValidationError::Solid(SolidValidationError::MultipleReferences( + ReferenceCountError::Region + )) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -313,7 +326,9 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::ReferenceCount(ReferenceCountError::Cycle) + ValidationError::Solid(SolidValidationError::MultipleReferences( + ReferenceCountError::Cycle + )) ); let valid_solid = Solid::new(vec![]).insert(&mut services); @@ -352,7 +367,9 @@ mod tests { assert_contains_err!( invalid_solid, - ValidationError::ReferenceCount(ReferenceCountError::HalfEdge) + ValidationError::Solid(SolidValidationError::MultipleReferences( + ReferenceCountError::HalfEdge + )) ); let valid_solid = Solid::new(vec![]).insert(&mut services); From 81e1c8e5398c30e01bda24a640ff26d95f69db71 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 14:53:19 -0800 Subject: [PATCH 13/20] cleanup docs --- crates/fj-core/src/validate/references.rs | 12 +++++++----- crates/fj-core/src/validate/sketch.rs | 2 +- crates/fj-core/src/validate/solid.rs | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index 76f529e0c..d39ab786a 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -41,18 +41,20 @@ macro_rules! validate_references { }; } +/// Validation errors for when an object is referenced by multiple other objects. Each object +/// should only be referenced by a single other object #[derive(Clone, Debug, thiserror::Error)] pub enum ReferenceCountError { - /// [`Region`] referenced by more than one [`Face`] + /// [`crate::objects::Region`] referenced by more than one [`crate::objects::Face`] #[error("[`Region`] referenced by more than one [`Face`]")] Region, - /// [`Face`] referenced by more than one [`crate::objects::Shell`] - #[error("[`Face`] referenced by more than one [`crate::objects::Shell`]")] + /// [`crate::objects::Face`] referenced by more than one [`crate::objects::Shell`] + #[error("[`Face`] referenced by more than one [`Shell`]")] Face, - /// [`HalfEdge`] referenced by more than one [`Cycle`] + /// [`crate::objects::HalfEdge`] referenced by more than one [`crate::objects::Cycle`] #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] HalfEdge, - /// [`Cycle`] referenced by more than one [`Region`] + /// [`crate::objects::Cycle`] referenced by more than one [`crate::objects::Region`] #[error("[`Cycle`] referenced by more than one [`Region`]")] Cycle, } diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 7c88b35ca..7c9be34ae 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -25,7 +25,7 @@ pub enum SketchValidationError { #[error("[`Cycle`] referenced by more than one [`Region`]")] CycleMultipleReferences, /// Object within sketch referenced by more than one other object - #[error("Object referenced by more than one other Objects")] + #[error("Object within sketch referenced by more than one other Object")] MultipleReferences(#[from] ReferenceCountError), } diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 5c9497743..170c6f8c7 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -66,8 +66,8 @@ pub enum SolidValidationError { position_b: Point<3>, }, - /// Object within sketch referenced by more than one other object - #[error("Object referenced by more than one other Objects")] + /// Object within solid referenced by more than one other object + #[error("Object within solid referenced by more than one other Object")] MultipleReferences(#[from] ReferenceCountError), } From 2f2d723e36be68e1ffa59c1de5ffb5a1c172df1f Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 15:23:46 -0800 Subject: [PATCH 14/20] store both referenced and referencing objects for better error messages --- crates/fj-core/src/validate/references.rs | 20 +++++++------------- crates/fj-core/src/validate/sketch.rs | 4 ++-- crates/fj-core/src/validate/solid.rs | 8 ++++---- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index d39ab786a..2277034fd 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -3,33 +3,27 @@ use std::hash::Hash; use crate::storage::Handle; -use super::ValidationError; - #[derive(Default)] -pub struct ReferenceCounter(HashMap, i32>); +pub struct ReferenceCounter(HashMap, Vec>>); -impl ReferenceCounter { +impl ReferenceCounter { pub fn new() -> Self { Self(HashMap::new()) } - pub fn add_count(&mut self, object: Handle) { + pub fn add_count(&mut self, object: Handle, found: Handle) { self.0 .entry(object) - .and_modify(|count| *count += 1) - .or_insert(1); + .and_modify(|references| references.push(found.clone())) + .or_insert(vec![found]); } pub fn has_multiple(&self) -> bool { - self.0.iter().any(|(_, count)| *count > 1) + self.0.iter().any(|(_, references)| references.len() > 1) } } -pub trait ValidateReferences { - fn validate(&self, errors: &mut Vec); -} - -/// Find errors and convert to [`ValidationError`] +/// Find errors and convert to [`crate::validate::ValidationError`] #[macro_export] macro_rules! validate_references { ($errors:ident, $error_ty:ty;$($counter:ident, $err:expr;)*) => { diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 7c9be34ae..ca44803ea 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -42,9 +42,9 @@ impl SketchValidationError { sketch.regions().iter().for_each(|r| { r.all_cycles().for_each(|c| { - referenced_cycles.add_count(c.clone()); + referenced_cycles.add_count(c.clone(), r.clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges.add_count(e.clone()); + referenced_edges.add_count(e.clone(), c.clone()); }) }) }); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 170c6f8c7..93f130e7c 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -151,12 +151,12 @@ impl SolidValidationError { solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { - referenced_faces.add_count(f.clone()); - referenced_regions.add_count(f.region().clone()); + referenced_faces.add_count(f.clone(), s.clone()); + referenced_regions.add_count(f.region().clone(), f.clone()); f.region().all_cycles().for_each(|c| { - referenced_cycles.add_count(c.clone()); + referenced_cycles.add_count(c.clone(), f.region().clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges.add_count(e.clone()); + referenced_edges.add_count(e.clone(), c.clone()); }) }) }) From 3bdb468f7ab7c975777293ccb15efe6171ae002c Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 16:15:00 -0800 Subject: [PATCH 15/20] show referencing and referenced objects in error message --- crates/fj-core/src/validate/references.rs | 77 ++++++++++++++++++----- crates/fj-core/src/validate/sketch.rs | 8 +-- crates/fj-core/src/validate/solid.rs | 16 ++--- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index 2277034fd..52a95c888 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::hash::Hash; +use crate::objects::{Cycle, Face, HalfEdge, Region, Shell}; use crate::storage::Handle; #[derive(Default)] @@ -18,19 +19,27 @@ impl ReferenceCounter { .or_insert(vec![found]); } - pub fn has_multiple(&self) -> bool { - self.0.iter().any(|(_, references)| references.len() > 1) + pub fn get_multiples(&self) -> Vec> { + self.0 + .iter() + .filter(|(_, references)| references.len() > 1) + .map(|(referenced, references)| MultipleReferences { + referenced: referenced.clone(), + references: references.to_vec(), + }) + .collect() } } /// Find errors and convert to [`crate::validate::ValidationError`] #[macro_export] macro_rules! validate_references { - ($errors:ident, $error_ty:ty;$($counter:ident, $err:expr;)*) => { + ($errors:ident, $error_ty:ty;$($counter:ident, $err:ident;)*) => { $( - if $counter.has_multiple() { - $errors.push(Into::<$error_ty>::into($err).into()); - } + $counter.get_multiples().iter().for_each(|multiple| { + let reference_error = ReferenceCountError::$err { references: multiple.clone() }; + $errors.push(Into::<$error_ty>::into(reference_error).into()); + }); )* }; } @@ -40,15 +49,55 @@ macro_rules! validate_references { #[derive(Clone, Debug, thiserror::Error)] pub enum ReferenceCountError { /// [`crate::objects::Region`] referenced by more than one [`crate::objects::Face`] - #[error("[`Region`] referenced by more than one [`Face`]")] - Region, + #[error( + "[`Region`] referenced by more than one [`Face`]\n{references:#?}" + )] + Region { + references: MultipleReferences, + }, /// [`crate::objects::Face`] referenced by more than one [`crate::objects::Shell`] - #[error("[`Face`] referenced by more than one [`Shell`]")] - Face, + #[error("[`Face`] referenced by more than one [`Shell`]\n{references:#?}")] + Face { + references: MultipleReferences, + }, /// [`crate::objects::HalfEdge`] referenced by more than one [`crate::objects::Cycle`] - #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] - HalfEdge, + #[error( + "[`HalfEdge`] referenced by more than one [`Cycle`]\n{references:#?}" + )] + HalfEdge { + references: MultipleReferences, + }, /// [`crate::objects::Cycle`] referenced by more than one [`crate::objects::Region`] - #[error("[`Cycle`] referenced by more than one [`Region`]")] - Cycle, + #[error( + "[`Cycle`] referenced by more than one [`Region`]\n{references:#?}" + )] + Cycle { + references: MultipleReferences, + }, +} + +pub struct MultipleReferences { + referenced: Handle, + references: Vec>, +} + +use std::fmt::Debug; + +impl Debug for MultipleReferences { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:?} referenced by {:?}", + self.referenced, self.references + ) + } +} + +impl Clone for MultipleReferences { + fn clone(&self) -> Self { + Self { + referenced: self.referenced.clone(), + references: self.references.to_vec(), + } + } } diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index ca44803ea..a7872cdf7 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -51,8 +51,8 @@ impl SketchValidationError { validate_references!( errors, SketchValidationError; - referenced_edges, ReferenceCountError::HalfEdge; - referenced_cycles, ReferenceCountError::Cycle; + referenced_edges, HalfEdge; + referenced_cycles, Cycle; ); } } @@ -88,7 +88,7 @@ mod tests { assert_contains_err!( invalid_sketch, ValidationError::Sketch(SketchValidationError::MultipleReferences( - ReferenceCountError::Cycle + ReferenceCountError::Cycle { references: _ } )) ); @@ -133,7 +133,7 @@ mod tests { assert_contains_err!( invalid_sketch, ValidationError::Sketch(SketchValidationError::MultipleReferences( - ReferenceCountError::HalfEdge + ReferenceCountError::HalfEdge { references: _ } )) ); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 93f130e7c..cf5e9a48c 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -164,10 +164,10 @@ impl SolidValidationError { validate_references!( errors, SolidValidationError; - referenced_regions, ReferenceCountError::Region; - referenced_faces, ReferenceCountError::Face; - referenced_edges, ReferenceCountError::HalfEdge; - referenced_cycles, ReferenceCountError::Cycle; + referenced_regions, Region; + referenced_faces, Face; + referenced_edges, HalfEdge; + referenced_cycles, Cycle; ); } } @@ -228,7 +228,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Face + ReferenceCountError::Face { references: _ } )) ); @@ -279,7 +279,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Region + ReferenceCountError::Region { references: _ } )) ); @@ -327,7 +327,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Cycle + ReferenceCountError::Cycle { references: _ } )) ); @@ -368,7 +368,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::HalfEdge + ReferenceCountError::HalfEdge { references: _ } )) ); From 2d2506b5f535ad7272ec7ae896b4cec4ca656153 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 16:20:35 -0800 Subject: [PATCH 16/20] rename for clarity --- crates/fj-core/src/validate/references.rs | 12 ++++++++---- crates/fj-core/src/validate/sketch.rs | 4 ++-- crates/fj-core/src/validate/solid.rs | 9 +++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index 52a95c888..fd9074940 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -12,11 +12,15 @@ impl ReferenceCounter { Self(HashMap::new()) } - pub fn add_count(&mut self, object: Handle, found: Handle) { + pub fn add_reference( + &mut self, + referenced: Handle, + reference: Handle, + ) { self.0 - .entry(object) - .and_modify(|references| references.push(found.clone())) - .or_insert(vec![found]); + .entry(referenced) + .and_modify(|references| references.push(reference.clone())) + .or_insert(vec![reference]); } pub fn get_multiples(&self) -> Vec> { diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index a7872cdf7..f50d75cf5 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -42,9 +42,9 @@ impl SketchValidationError { sketch.regions().iter().for_each(|r| { r.all_cycles().for_each(|c| { - referenced_cycles.add_count(c.clone(), r.clone()); + referenced_cycles.add_reference(c.clone(), r.clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges.add_count(e.clone(), c.clone()); + referenced_edges.add_reference(e.clone(), c.clone()); }) }) }); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index cf5e9a48c..1c8f2dbae 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -151,12 +151,13 @@ impl SolidValidationError { solid.shells().iter().for_each(|s| { s.faces().into_iter().for_each(|f| { - referenced_faces.add_count(f.clone(), s.clone()); - referenced_regions.add_count(f.region().clone(), f.clone()); + referenced_faces.add_reference(f.clone(), s.clone()); + referenced_regions.add_reference(f.region().clone(), f.clone()); f.region().all_cycles().for_each(|c| { - referenced_cycles.add_count(c.clone(), f.region().clone()); + referenced_cycles + .add_reference(c.clone(), f.region().clone()); c.half_edges().into_iter().for_each(|e| { - referenced_edges.add_count(e.clone(), c.clone()); + referenced_edges.add_reference(e.clone(), c.clone()); }) }) }) From 0900ef8322df2e0fbee103c9d57ae332d064eda9 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 16:22:47 -0800 Subject: [PATCH 17/20] cleanup, remove todos --- crates/fj-core/src/validate/sketch.rs | 8 -------- crates/fj-core/src/validate/solid.rs | 2 -- 2 files changed, 10 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index f50d75cf5..9b10d2720 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -18,12 +18,6 @@ impl Validate for Sketch { /// [`Sketch`] validation failed #[derive(Clone, Debug, thiserror::Error)] pub enum SketchValidationError { - /// [`HalfEdge`] referenced by more than one [`Cycle`] - #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] - HalfEdgeMultipleReferences, - /// [`Cycle`] referenced by more than one [`crate::objects::Region`] - #[error("[`Cycle`] referenced by more than one [`Region`]")] - CycleMultipleReferences, /// Object within sketch referenced by more than one other object #[error("Object within sketch referenced by more than one other Object")] MultipleReferences(#[from] ReferenceCountError), @@ -35,8 +29,6 @@ impl SketchValidationError { _config: &ValidationConfig, errors: &mut Vec, ) { - // todo: store referencing objects instead of just a reference count so that we can surface - // them in the error message let mut referenced_edges = ReferenceCounter::new(); let mut referenced_cycles = ReferenceCounter::new(); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 1c8f2dbae..9127d35f6 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -142,8 +142,6 @@ impl SolidValidationError { _config: &ValidationConfig, errors: &mut Vec, ) { - // todo: store referencing objects instead of just a reference count so that we can surface - // them in the error message let mut referenced_regions = ReferenceCounter::new(); let mut referenced_faces = ReferenceCounter::new(); let mut referenced_edges = ReferenceCounter::new(); From 8411b1789fd9c9b06c8a0cad44d41ad632321059 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sat, 13 Jan 2024 19:25:12 -0800 Subject: [PATCH 18/20] Make DerefMut impl on Service only available in tests --- crates/fj-core/src/services/service.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fj-core/src/services/service.rs b/crates/fj-core/src/services/service.rs index bacacd8b4..93b0cc20e 100644 --- a/crates/fj-core/src/services/service.rs +++ b/crates/fj-core/src/services/service.rs @@ -62,6 +62,7 @@ impl Deref for Service { } } +#[cfg(test)] impl DerefMut for Service { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.state From 16e18e1b8e9f1f59be106d395136bdedeff8ecd1 Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sat, 13 Jan 2024 19:25:46 -0800 Subject: [PATCH 19/20] Fix typo in method name --- crates/fj-core/src/validate/sketch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 9b10d2720..4654c58c8 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -11,7 +11,7 @@ impl Validate for Sketch { config: &ValidationConfig, errors: &mut Vec, ) { - SketchValidationError::check_obect_references(self, config, errors); + SketchValidationError::check_object_references(self, config, errors); } } @@ -24,7 +24,7 @@ pub enum SketchValidationError { } impl SketchValidationError { - fn check_obect_references( + fn check_object_references( sketch: &Sketch, _config: &ValidationConfig, errors: &mut Vec, From cdcf0153d74e205b9ba3400c58dd9c1b3661391f Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Sat, 13 Jan 2024 19:30:18 -0800 Subject: [PATCH 20/20] Make clippy happy with import --- crates/fj-core/src/services/service.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-core/src/services/service.rs b/crates/fj-core/src/services/service.rs index 93b0cc20e..8069898c5 100644 --- a/crates/fj-core/src/services/service.rs +++ b/crates/fj-core/src/services/service.rs @@ -1,4 +1,4 @@ -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; /// A service that controls access to some state /// @@ -63,7 +63,7 @@ impl Deref for Service { } #[cfg(test)] -impl DerefMut for Service { +impl std::ops::DerefMut for Service { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.state }