diff --git a/src/wasm-lib/kcl/src/std/chamfer.rs b/src/wasm-lib/kcl/src/std/chamfer.rs index ec24f6f72..77865c1b0 100644 --- a/src/wasm-lib/kcl/src/std/chamfer.rs +++ b/src/wasm-lib/kcl/src/std/chamfer.rs @@ -5,6 +5,7 @@ use derive_docs::stdlib; use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::CutType, ModelingCmd}; use kittycad_modeling_cmds as kcmc; +use super::utils::unique_count; use crate::{ errors::{KclError, KclErrorDetails}, execution::{ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, Solid}, @@ -109,10 +110,8 @@ async fn inner_chamfer( args: Args, ) -> Result, KclError> { // Check if tags contains any duplicate values. - let mut tags = tags.clone(); - tags.sort(); - tags.dedup(); - if tags.len() != tags.len() { + let unique_tags = unique_count(tags.clone()); + if unique_tags != tags.len() { return Err(KclError::Type(KclErrorDetails { message: "Duplicate tags are not allowed.".to_string(), source_ranges: vec![args.source_range], diff --git a/src/wasm-lib/kcl/src/std/fillet.rs b/src/wasm-lib/kcl/src/std/fillet.rs index 706a6aa60..e44cb2616 100644 --- a/src/wasm-lib/kcl/src/std/fillet.rs +++ b/src/wasm-lib/kcl/src/std/fillet.rs @@ -11,6 +11,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; +use super::utils::unique_count; use crate::{ errors::{KclError, KclErrorDetails}, execution::{EdgeCut, ExecState, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, Solid, TagIdentifier}, @@ -20,7 +21,7 @@ use crate::{ }; /// A tag or a uuid of an edge. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq, Ord, PartialOrd, Hash)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq, Hash)] #[ts(export)] #[serde(untagged)] pub enum EdgeReference { @@ -129,10 +130,8 @@ async fn inner_fillet( args: Args, ) -> Result, KclError> { // Check if tags contains any duplicate values. - let mut unique_tags = tags.clone(); - unique_tags.sort(); - unique_tags.dedup(); - if unique_tags.len() != tags.len() { + let unique_tags = unique_count(tags.clone()); + if unique_tags != tags.len() { return Err(KclError::Type(KclErrorDetails { message: "Duplicate tags are not allowed.".to_string(), source_ranges: vec![args.source_range], diff --git a/src/wasm-lib/kcl/src/std/utils.rs b/src/wasm-lib/kcl/src/std/utils.rs index 4d7aefd79..f0e3f8643 100644 --- a/src/wasm-lib/kcl/src/std/utils.rs +++ b/src/wasm-lib/kcl/src/std/utils.rs @@ -1,4 +1,4 @@ -use std::f64::consts::PI; +use std::{collections::HashSet, f64::consts::PI}; use kittycad_modeling_cmds::shared::Angle; @@ -8,6 +8,16 @@ use crate::{ source_range::SourceRange, }; +/// Count the number of unique items in a `Vec` in O(n) time. +pub(crate) fn unique_count(vec: Vec) -> usize { + // Add to a set. + let mut set = HashSet::with_capacity(vec.len()); + for item in vec { + set.insert(item); + } + set.len() +} + /// Get the distance between two points. pub fn distance(a: Point2d, b: Point2d) -> f64 { ((b.x - a.x).powi(2) + (b.y - a.y).powi(2)).sqrt() @@ -676,6 +686,11 @@ mod get_tangential_arc_to_info_tests { (num * 1000.0).round() / 1000.0 } + #[test] + fn test_unique_count() { + assert_eq!(unique_count(vec![1, 2, 2, 3, 2]), 3); + } + #[test] fn test_basic_case() { let result = get_tangential_arc_to_info(TangentialArcInfoInput {