From b7281bed9a85e52e9eabf41fbc528bfca2ff7387 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 5 Mar 2024 18:09:35 -0500 Subject: [PATCH 1/3] ObjectSet can now accept arbitrary containers of Handles or HandleWrappers --- crates/fj-core/src/objects/object_set.rs | 55 +++++++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/crates/fj-core/src/objects/object_set.rs b/crates/fj-core/src/objects/object_set.rs index 9fb8f61d5..9f727f144 100644 --- a/crates/fj-core/src/objects/object_set.rs +++ b/crates/fj-core/src/objects/object_set.rs @@ -28,16 +28,17 @@ impl ObjectSet { /// # Panics /// /// Panics, if the iterator contains duplicate `Handle`s. - pub fn new(handles: impl IntoIterator>) -> Self + pub fn new(handles: impl IntoIterator) -> Self where T: Debug + Ord, + H: Into>, { let mut added = BTreeSet::new(); let mut inner = Vec::new(); - for handle in handles { - let handle = HandleWrapper::from(handle); + let handles = handles.into_iter().map(|handle| handle.into()); + for handle in handles { if added.contains(&handle) { panic!( "Constructing `ObjectSet` with duplicate handle: {:?}", @@ -149,13 +150,14 @@ impl ObjectSet { /// /// Panics, if the update results in a duplicate item. #[must_use] - pub fn replace( + pub fn replace( &self, original: &Handle, - replacements: [Handle; N], + replacements: impl IntoIterator, ) -> Option where T: Debug + Ord, + H: Into>, { let mut iter = self.iter().cloned().peekable(); @@ -185,7 +187,7 @@ impl ObjectSet { Some( before .into_iter() - .chain(replacements) + .chain(replacements.into_iter().map(|handle| handle.into())) .chain(after) .collect(), ) @@ -244,7 +246,12 @@ pub type ObjectSetIntoIter = iter::Map< #[cfg(test)] mod tests { - use crate::{objects::Cycle, operations::insert::Insert, Core}; + use std::collections::HashSet; + + use crate::{ + objects::Cycle, operations::insert::Insert, storage::HandleWrapper, + Core, + }; use super::ObjectSet; @@ -260,4 +267,38 @@ mod tests { // Nothing more to test. `ObjectSet` panics on duplicate objects, and it // shouldn't do that in this case. } + + #[test] + fn deduplicate_with_hashset() { + let mut core = Core::new(); + + let bare_cycle = Cycle::new([]); + let cycle = bare_cycle.insert(&mut core); + + let standard_set = HashSet::from([cycle.clone(), cycle.clone()]); + + assert_eq!(standard_set, [cycle].into()); + } + + #[test] + fn object_set_from_handle_wrappers() { + let mut core = Core::new(); + + let bare_cycle = Cycle::new([]); + let cycle_a = HandleWrapper::from(bare_cycle.clone().insert(&mut core)); + let cycle_b = HandleWrapper::from(bare_cycle.insert(&mut core)); + + let _object_set = ObjectSet::new([cycle_a, cycle_b]); + } + + #[test] + fn object_set_from_deduplicated_hash_set() { + let mut core = Core::new(); + + let bare_cycle = Cycle::new([]); + let cycle_a = HandleWrapper::from(bare_cycle.clone().insert(&mut core)); + let cycle_b = HandleWrapper::from(bare_cycle.insert(&mut core)); + + let _object_set = ObjectSet::new(HashSet::from([cycle_a, cycle_b])); + } } From d1bc795e49b42c1396c52f1448c421c68fd7d189 Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 5 Mar 2024 19:28:42 -0500 Subject: [PATCH 2/3] Update operations can now accept arbitrary containers of Handles or HandleWrappers --- crates/fj-core/src/operations/update/cycle.rs | 14 ++++++++------ crates/fj-core/src/operations/update/region.rs | 14 ++++++++------ crates/fj-core/src/operations/update/shell.rs | 14 ++++++++------ crates/fj-core/src/operations/update/sketch.rs | 14 ++++++++------ crates/fj-core/src/operations/update/solid.rs | 14 ++++++++------ 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/crates/fj-core/src/operations/update/cycle.rs b/crates/fj-core/src/operations/update/cycle.rs index 1f672a424..1a2e7bf03 100644 --- a/crates/fj-core/src/operations/update/cycle.rs +++ b/crates/fj-core/src/operations/update/cycle.rs @@ -25,14 +25,15 @@ pub trait UpdateCycle { /// /// Panics, if the update results in a duplicate object. #[must_use] - fn update_half_edge( + fn update_half_edge( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where - T: Insert>; + T: Insert>, + R: IntoIterator; } impl UpdateCycle for Cycle { @@ -51,20 +52,21 @@ impl UpdateCycle for Cycle { Cycle::new(half_edges) } - fn update_half_edge( + fn update_half_edge( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where T: Insert>, + R: IntoIterator, { let edges = self .half_edges() .replace( handle, - update(handle, core).map(|object| { + update(handle, core).into_iter().map(|object| { object.insert(core).derive_from(handle, core) }), ) diff --git a/crates/fj-core/src/operations/update/region.rs b/crates/fj-core/src/operations/update/region.rs index cc83b6daa..ac21348fb 100644 --- a/crates/fj-core/src/operations/update/region.rs +++ b/crates/fj-core/src/operations/update/region.rs @@ -35,14 +35,15 @@ pub trait UpdateRegion { /// /// Panics, if the update results in a duplicate object. #[must_use] - fn update_interior( + fn update_interior( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where - T: Insert>; + T: Insert>, + R: IntoIterator; } impl UpdateRegion for Region { @@ -73,20 +74,21 @@ impl UpdateRegion for Region { Region::new(self.exterior().clone(), interiors) } - fn update_interior( + fn update_interior( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where T: Insert>, + R: IntoIterator, { let interiors = self .interiors() .replace( handle, - update(handle, core).map(|object| { + update(handle, core).into_iter().map(|object| { object.insert(core).derive_from(handle, core) }), ) diff --git a/crates/fj-core/src/operations/update/shell.rs b/crates/fj-core/src/operations/update/shell.rs index 6b46c76cd..8b0911533 100644 --- a/crates/fj-core/src/operations/update/shell.rs +++ b/crates/fj-core/src/operations/update/shell.rs @@ -25,14 +25,15 @@ pub trait UpdateShell { /// /// Panics, if the update results in a duplicate object. #[must_use] - fn update_face( + fn update_face( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where - T: Insert>; + T: Insert>, + R: IntoIterator; /// Remove a face from the shell #[must_use] @@ -53,20 +54,21 @@ impl UpdateShell for Shell { Shell::new(faces) } - fn update_face( + fn update_face( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where T: Insert>, + R: IntoIterator, { let faces = self .faces() .replace( handle, - update(handle, core).map(|object| { + update(handle, core).into_iter().map(|object| { object.insert(core).derive_from(handle, core) }), ) diff --git a/crates/fj-core/src/operations/update/sketch.rs b/crates/fj-core/src/operations/update/sketch.rs index 192e7da19..046e20599 100644 --- a/crates/fj-core/src/operations/update/sketch.rs +++ b/crates/fj-core/src/operations/update/sketch.rs @@ -25,14 +25,15 @@ pub trait UpdateSketch { /// /// Panics, if the update results in a duplicate object. #[must_use] - fn update_region( + fn update_region( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where - T: Insert>; + T: Insert>, + R: IntoIterator; } impl UpdateSketch for Sketch { @@ -49,20 +50,21 @@ impl UpdateSketch for Sketch { Sketch::new(regions) } - fn update_region( + fn update_region( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where T: Insert>, + R: IntoIterator, { let regions = self .regions() .replace( handle, - update(handle, core).map(|object| { + update(handle, core).into_iter().map(|object| { object.insert(core).derive_from(handle, core) }), ) diff --git a/crates/fj-core/src/operations/update/solid.rs b/crates/fj-core/src/operations/update/solid.rs index f7882a637..83a092487 100644 --- a/crates/fj-core/src/operations/update/solid.rs +++ b/crates/fj-core/src/operations/update/solid.rs @@ -25,14 +25,15 @@ pub trait UpdateSolid { /// /// Panics, if the update results in a duplicate object. #[must_use] - fn update_shell( + fn update_shell( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where - T: Insert>; + T: Insert>, + R: IntoIterator; } impl UpdateSolid for Solid { @@ -49,20 +50,21 @@ impl UpdateSolid for Solid { Solid::new(shells) } - fn update_shell( + fn update_shell( &self, handle: &Handle, - update: impl FnOnce(&Handle, &mut Core) -> [T; N], + update: impl FnOnce(&Handle, &mut Core) -> R, core: &mut Core, ) -> Self where T: Insert>, + R: IntoIterator, { let shells = self .shells() .replace( handle, - update(handle, core).map(|object| { + update(handle, core).into_iter().map(|object| { object.insert(core).derive_from(handle, core) }), ) From 79544b522b34a70eec3057919b537cd1ad77212b Mon Sep 17 00:00:00 2001 From: James Carl Date: Tue, 5 Mar 2024 19:34:17 -0500 Subject: [PATCH 3/3] Touch up documentation comments --- crates/fj-core/src/operations/update/cycle.rs | 2 +- crates/fj-core/src/operations/update/region.rs | 2 +- crates/fj-core/src/operations/update/shell.rs | 2 +- crates/fj-core/src/operations/update/sketch.rs | 2 +- crates/fj-core/src/operations/update/solid.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-core/src/operations/update/cycle.rs b/crates/fj-core/src/operations/update/cycle.rs index 1a2e7bf03..9d1d6353b 100644 --- a/crates/fj-core/src/operations/update/cycle.rs +++ b/crates/fj-core/src/operations/update/cycle.rs @@ -23,7 +23,7 @@ pub trait UpdateCycle { /// /// Panics, if the object can't be found. /// - /// Panics, if the update results in a duplicate object. + /// Panics, if the update results in multiple handles referencing the same object. #[must_use] fn update_half_edge( &self, diff --git a/crates/fj-core/src/operations/update/region.rs b/crates/fj-core/src/operations/update/region.rs index ac21348fb..9f28c7e83 100644 --- a/crates/fj-core/src/operations/update/region.rs +++ b/crates/fj-core/src/operations/update/region.rs @@ -33,7 +33,7 @@ pub trait UpdateRegion { /// /// Panics, if the object can't be found. /// - /// Panics, if the update results in a duplicate object. + /// Panics, if the update results in multiple handles referencing the same object. #[must_use] fn update_interior( &self, diff --git a/crates/fj-core/src/operations/update/shell.rs b/crates/fj-core/src/operations/update/shell.rs index 8b0911533..961e3b730 100644 --- a/crates/fj-core/src/operations/update/shell.rs +++ b/crates/fj-core/src/operations/update/shell.rs @@ -23,7 +23,7 @@ pub trait UpdateShell { /// /// Panics, if the object can't be found. /// - /// Panics, if the update results in a duplicate object. + /// Panics, if the update results in multiple handles referencing the same object. #[must_use] fn update_face( &self, diff --git a/crates/fj-core/src/operations/update/sketch.rs b/crates/fj-core/src/operations/update/sketch.rs index 046e20599..33a96e832 100644 --- a/crates/fj-core/src/operations/update/sketch.rs +++ b/crates/fj-core/src/operations/update/sketch.rs @@ -23,7 +23,7 @@ pub trait UpdateSketch { /// /// Panics, if the object can't be found. /// - /// Panics, if the update results in a duplicate object. + /// Panics, if the update results in multiple handles referencing the same object. #[must_use] fn update_region( &self, diff --git a/crates/fj-core/src/operations/update/solid.rs b/crates/fj-core/src/operations/update/solid.rs index 83a092487..3d30ff513 100644 --- a/crates/fj-core/src/operations/update/solid.rs +++ b/crates/fj-core/src/operations/update/solid.rs @@ -23,7 +23,7 @@ pub trait UpdateSolid { /// /// Panics, if the object can't be found. /// - /// Panics, if the update results in a duplicate object. + /// Panics, if the update results in multiple handles referencing the same object. #[must_use] fn update_shell( &self,