From 8f01bbdc17e85e9a5b835606205cd33400120f0f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 10 Jan 2023 12:49:35 +0100 Subject: [PATCH 1/3] Add `ObjectArgument` --- crates/fj-kernel/src/builder/mod.rs | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index ee3bb86a0..6eeae17cf 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -22,3 +22,56 @@ pub use self::{ surface::SurfaceBuilder, vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder}, }; + +/// Pass objects to a builder method +/// +/// Many builder methods receive objects as arguments, and many builder +/// arguments return objects back, based on their input. In the general case, +/// the number of objects passed and returned is usually arbitrary, but many +/// callers pass a specific number of objects, and expect the same number of +/// objects back. +/// +/// This trait can be used to do exactly that. It is implemented for `Vec` and +/// arrays. When passing a `Vec`, a `Vec` is returned. When passing an array, an +/// array of the same size is returned. +pub trait ObjectArgument: IntoIterator { + /// The value returned, if the implementing type is passed on an argument + /// + /// The return value has the same length as the implementing type, but it is + /// not necessarily of the same type. For this reason, this associated type + /// is generic. + type ReturnValue; + + /// Create a return value by mapping the implementing type + fn map(self, f: F) -> Self::ReturnValue + where + F: FnMut(T) -> R; +} + +impl ObjectArgument for Vec { + type ReturnValue = Vec; + + fn map(self, mut f: F) -> Self::ReturnValue + where + F: FnMut(T) -> R, + { + let mut ret = Vec::new(); + + for item in self { + ret.push(f(item)); + } + + ret + } +} + +impl ObjectArgument for [T; N] { + type ReturnValue = [R; N]; + + fn map(self, f: F) -> Self::ReturnValue + where + F: FnMut(T) -> R, + { + self.map(f) + } +} From 18477a17d04e0ad067a0dd2371b730c324df4e62 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 11 Jan 2023 12:19:00 +0100 Subject: [PATCH 2/3] Make use of `ObjectArgument` in `CycleBuilder` --- crates/fj-kernel/src/builder/cycle.rs | 34 ++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 68749a828..1a3d16b31 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -6,7 +6,7 @@ use crate::{ partial::{Partial, PartialCycle}, }; -use super::HalfEdgeBuilder; +use super::{HalfEdgeBuilder, ObjectArgument}; /// Builder API for [`PartialCycle`] pub trait CycleBuilder { @@ -35,10 +35,13 @@ pub trait CycleBuilder { ) -> Partial; /// Update cycle as a polygon from the provided points - fn update_as_polygon_from_points( + fn update_as_polygon_from_points( &mut self, - points: impl IntoIterator>>, - ) -> Vec>; + points: O, + ) -> O::ReturnValue> + where + O: ObjectArgument

, + P: Into>; /// Update cycle as a polygon /// @@ -124,19 +127,17 @@ impl CycleBuilder for PartialCycle { half_edge } - fn update_as_polygon_from_points( + fn update_as_polygon_from_points( &mut self, - points: impl IntoIterator>>, - ) -> Vec> { - let mut half_edges = Vec::new(); - - for point in points { - let half_edge = self.add_half_edge_from_point_to_start(point); - half_edges.push(half_edge); - } - + points: O, + ) -> O::ReturnValue> + where + O: ObjectArgument

, + P: Into>, + { + let half_edges = + points.map(|point| self.add_half_edge_from_point_to_start(point)); self.update_as_polygon(); - half_edges } @@ -154,7 +155,8 @@ impl CycleBuilder for PartialCycle { .surface .write() .update_as_plane_from_points(points_global); - let mut edges = self.update_as_polygon_from_points(points_surface); + let mut edges = + self.update_as_polygon_from_points(points_surface.to_vec()); // None of the following should panic, as we just created a polygon from // three points, so we should have exactly three edges. From 5d98422730573f559a3bf9952b18806c32d235e3 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 11 Jan 2023 12:30:48 +0100 Subject: [PATCH 3/3] Refactor --- crates/fj-kernel/src/builder/cycle.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 1a3d16b31..107016e86 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -155,16 +155,6 @@ impl CycleBuilder for PartialCycle { .surface .write() .update_as_plane_from_points(points_global); - let mut edges = - self.update_as_polygon_from_points(points_surface.to_vec()); - - // None of the following should panic, as we just created a polygon from - // three points, so we should have exactly three edges. - let c = edges.pop().unwrap(); - let b = edges.pop().unwrap(); - let a = edges.pop().unwrap(); - assert!(edges.pop().is_none()); - - [a, b, c] + self.update_as_polygon_from_points(points_surface) } }