Skip to content

Commit

Permalink
Merge pull request #2253 from IamTheCarl/main
Browse files Browse the repository at this point in the history
Update with arbitrary containers of Handles or HandleWrappers
  • Loading branch information
hannobraun authored Mar 6, 2024
2 parents 82a90cb + 79544b5 commit 4f8fcdb
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 42 deletions.
55 changes: 48 additions & 7 deletions crates/fj-core/src/objects/object_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@ impl<T> ObjectSet<T> {
/// # Panics
///
/// Panics, if the iterator contains duplicate `Handle`s.
pub fn new(handles: impl IntoIterator<Item = Handle<T>>) -> Self
pub fn new<H>(handles: impl IntoIterator<Item = H>) -> Self
where
T: Debug + Ord,
H: Into<HandleWrapper<T>>,
{
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: {:?}",
Expand Down Expand Up @@ -149,13 +150,14 @@ impl<T> ObjectSet<T> {
///
/// Panics, if the update results in a duplicate item.
#[must_use]
pub fn replace<const N: usize>(
pub fn replace<H>(
&self,
original: &Handle<T>,
replacements: [Handle<T>; N],
replacements: impl IntoIterator<Item = H>,
) -> Option<Self>
where
T: Debug + Ord,
H: Into<Handle<T>>,
{
let mut iter = self.iter().cloned().peekable();

Expand Down Expand Up @@ -185,7 +187,7 @@ impl<T> ObjectSet<T> {
Some(
before
.into_iter()
.chain(replacements)
.chain(replacements.into_iter().map(|handle| handle.into()))
.chain(after)
.collect(),
)
Expand Down Expand Up @@ -244,7 +246,12 @@ pub type ObjectSetIntoIter<T> = 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;

Expand All @@ -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]));
}
}
16 changes: 9 additions & 7 deletions crates/fj-core/src/operations/update/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ 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<T, const N: usize>(
fn update_half_edge<T, R>(
&self,
handle: &Handle<HalfEdge>,
update: impl FnOnce(&Handle<HalfEdge>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<HalfEdge>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<HalfEdge>>;
T: Insert<Inserted = Handle<HalfEdge>>,
R: IntoIterator<Item = T>;
}

impl UpdateCycle for Cycle {
Expand All @@ -51,20 +52,21 @@ impl UpdateCycle for Cycle {
Cycle::new(half_edges)
}

fn update_half_edge<T, const N: usize>(
fn update_half_edge<T, R>(
&self,
handle: &Handle<HalfEdge>,
update: impl FnOnce(&Handle<HalfEdge>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<HalfEdge>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<HalfEdge>>,
R: IntoIterator<Item = T>,
{
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)
}),
)
Expand Down
16 changes: 9 additions & 7 deletions crates/fj-core/src/operations/update/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,17 @@ 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<T, const N: usize>(
fn update_interior<T, R>(
&self,
handle: &Handle<Cycle>,
update: impl FnOnce(&Handle<Cycle>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Cycle>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Cycle>>;
T: Insert<Inserted = Handle<Cycle>>,
R: IntoIterator<Item = T>;
}

impl UpdateRegion for Region {
Expand Down Expand Up @@ -73,20 +74,21 @@ impl UpdateRegion for Region {
Region::new(self.exterior().clone(), interiors)
}

fn update_interior<T, const N: usize>(
fn update_interior<T, R>(
&self,
handle: &Handle<Cycle>,
update: impl FnOnce(&Handle<Cycle>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Cycle>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Cycle>>,
R: IntoIterator<Item = T>,
{
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)
}),
)
Expand Down
16 changes: 9 additions & 7 deletions crates/fj-core/src/operations/update/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ 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<T, const N: usize>(
fn update_face<T, R>(
&self,
handle: &Handle<Face>,
update: impl FnOnce(&Handle<Face>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Face>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Face>>;
T: Insert<Inserted = Handle<Face>>,
R: IntoIterator<Item = T>;

/// Remove a face from the shell
#[must_use]
Expand All @@ -53,20 +54,21 @@ impl UpdateShell for Shell {
Shell::new(faces)
}

fn update_face<T, const N: usize>(
fn update_face<T, R>(
&self,
handle: &Handle<Face>,
update: impl FnOnce(&Handle<Face>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Face>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Face>>,
R: IntoIterator<Item = T>,
{
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)
}),
)
Expand Down
16 changes: 9 additions & 7 deletions crates/fj-core/src/operations/update/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ 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<T, const N: usize>(
fn update_region<T, R>(
&self,
handle: &Handle<Region>,
update: impl FnOnce(&Handle<Region>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Region>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Region>>;
T: Insert<Inserted = Handle<Region>>,
R: IntoIterator<Item = T>;
}

impl UpdateSketch for Sketch {
Expand All @@ -49,20 +50,21 @@ impl UpdateSketch for Sketch {
Sketch::new(regions)
}

fn update_region<T, const N: usize>(
fn update_region<T, R>(
&self,
handle: &Handle<Region>,
update: impl FnOnce(&Handle<Region>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Region>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Region>>,
R: IntoIterator<Item = T>,
{
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)
}),
)
Expand Down
16 changes: 9 additions & 7 deletions crates/fj-core/src/operations/update/solid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ 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<T, const N: usize>(
fn update_shell<T, R>(
&self,
handle: &Handle<Shell>,
update: impl FnOnce(&Handle<Shell>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Shell>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Shell>>;
T: Insert<Inserted = Handle<Shell>>,
R: IntoIterator<Item = T>;
}

impl UpdateSolid for Solid {
Expand All @@ -49,20 +50,21 @@ impl UpdateSolid for Solid {
Solid::new(shells)
}

fn update_shell<T, const N: usize>(
fn update_shell<T, R>(
&self,
handle: &Handle<Shell>,
update: impl FnOnce(&Handle<Shell>, &mut Core) -> [T; N],
update: impl FnOnce(&Handle<Shell>, &mut Core) -> R,
core: &mut Core,
) -> Self
where
T: Insert<Inserted = Handle<Shell>>,
R: IntoIterator<Item = T>,
{
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)
}),
)
Expand Down

0 comments on commit 4f8fcdb

Please sign in to comment.