diff --git a/src/wasm-lib/kcl/src/std/args.rs b/src/wasm-lib/kcl/src/std/args.rs index 431e76b8c..2910609ac 100644 --- a/src/wasm-lib/kcl/src/std/args.rs +++ b/src/wasm-lib/kcl/src/std/args.rs @@ -1,4 +1,4 @@ -use std::{any::type_name, num::NonZeroU32}; +use std::{any::type_name, collections::HashMap, num::NonZeroU32}; use anyhow::Result; use kcmc::{websocket::OkWebSocketResponseData, ModelingCmd}; @@ -244,7 +244,7 @@ impl Args { .args .iter() .map(|arg| { - let Some(num) = f64::from_mem_item(arg) else { + let Some(num) = f64::from_kcl_val(arg) else { return Err(KclError::Semantic(KclErrorDetails { source_ranges: arg.metadata().iter().map(|x| x.source_range).collect(), message: format!("Expected a number but found {}", arg.human_friendly_type()), @@ -498,7 +498,7 @@ pub trait FromArgs<'a>: Sized { /// Types which impl this trait can be extracted from a `KclValue`. pub trait FromKclValue<'a>: Sized { /// Try to convert a KclValue into this type. - fn from_mem_item(arg: &'a KclValue) -> Option; + fn from_kcl_val(arg: &'a KclValue) -> Option; } impl<'a> FromArgs<'a> for Vec { @@ -531,7 +531,7 @@ where source_ranges: vec![args.source_range], })); }; - let Some(val) = T::from_mem_item(arg) else { + let Some(val) = T::from_kcl_val(arg) else { return Err(KclError::Semantic(KclErrorDetails { message: format!( "Argument at index {i} was supposed to be type {} but found {}", @@ -551,10 +551,10 @@ where { fn from_args(args: &'a Args, i: usize) -> Result { let Some(arg) = args.args.get(i) else { return Ok(None) }; - if crate::ast::types::KclNone::from_mem_item(arg).is_some() { + if crate::ast::types::KclNone::from_kcl_val(arg).is_some() { return Ok(None); } - let Some(val) = T::from_mem_item(arg) else { + let Some(val) = T::from_kcl_val(arg) else { return Err(KclError::Semantic(KclErrorDetails { message: format!( "Argument at index {i} was supposed to be type Option<{}> but found {}", @@ -610,7 +610,7 @@ where } impl<'a> FromKclValue<'a> for [f64; 2] { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Array { value, meta: _ } = arg else { return None; }; @@ -625,7 +625,7 @@ impl<'a> FromKclValue<'a> for [f64; 2] { } impl<'a> FromKclValue<'a> for [usize; 3] { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Array { value, meta: _ } = arg else { return None; }; @@ -641,7 +641,7 @@ impl<'a> FromKclValue<'a> for [usize; 3] { } impl<'a> FromKclValue<'a> for [f64; 3] { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Array { value, meta: _ } = arg else { return None; }; @@ -657,84 +657,60 @@ impl<'a> FromKclValue<'a> for [f64; 3] { } impl<'a> FromKclValue<'a> for TagNode { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.get_tag_declarator().ok() } } impl<'a> FromKclValue<'a> for TagIdentifier { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.get_tag_identifier().ok() } } impl<'a> FromKclValue<'a> for KclValue { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { Some(arg.clone()) } } -macro_rules! fields { - ($obj:ident, $typ:ident, $($field:ident),+) => { - $( - let $field = $obj.get(stringify!($field))?.$typ()?; - )+ +macro_rules! let_field_of { + // Optional field + ($obj:ident, $field:ident?) => { + let $field = $obj.get(stringify!($field)).and_then(FromKclValue::from_kcl_val); }; - ($obj:ident, $typ:ident, $($field:ident $key:literal),+) => { - $( - let $field = $obj.get($key)?.$typ()?; - )+ + // Mandatory field, but with a different string used as the key. + ($obj:ident, $field:ident $key:literal) => { + let $field = $obj.get($key).and_then(FromKclValue::from_kcl_val)?; }; -} - -macro_rules! fields_opt { - ($obj:ident, $typ:ident, $($field:ident),+) => { - $( - let $field = $obj.get(stringify!($field)).and_then(|x|x.$typ()); - )+ - }; -} - -macro_rules! fields_recurse { - ($obj:ident, $field:ident) => { - let $field = $obj.get(stringify!($field)).and_then(FromKclValue::from_mem_item)?; - }; - ($obj:ident, $field:ident $k:literal) => { - let $field = $obj.get($k).and_then(FromKclValue::from_mem_item)?; - }; -} - -macro_rules! fields_recurse_opt { - ($obj:ident, $field:ident) => { - let $field = $obj.get(stringify!($field)).and_then(FromKclValue::from_mem_item); - }; - ($obj:ident, $field:ident, $k:literal) => { - let $field = $obj.get($k).and_then(FromKclValue::from_mem_item); + // Mandatory field, optionally with a type annotation + ($obj:ident, $field:ident $(, $annotation:ty)?) => { + let $field $(: $annotation)? = $obj.get(stringify!($field)).and_then(FromKclValue::from_kcl_val)?; }; } impl<'a> FromKclValue<'a> for crate::std::import::ImportFormat { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_str, typ "type"); + let_field_of!(obj, typ "type"); match typ { "fbx" => Some(Self::Fbx {}), "gltf" => Some(Self::Gltf {}), "sldprt" => Some(Self::Sldprt {}), "step" => Some(Self::Step {}), "stl" => { - fields_recurse_opt!(obj, coords); - fields_recurse!(obj, units); + let_field_of!(obj, coords?); + let_field_of!(obj, units); Some(Self::Stl { coords, units }) } "obj" => { - fields_recurse_opt!(obj, coords); - fields_recurse!(obj, units); + let_field_of!(obj, coords?); + let_field_of!(obj, units); Some(Self::Obj { coords, units }) } "ply" => { - fields_recurse_opt!(obj, coords); - fields_recurse!(obj, units); + let_field_of!(obj, coords?); + let_field_of!(obj, units); Some(Self::Ply { coords, units }) } _ => None, @@ -743,11 +719,11 @@ impl<'a> FromKclValue<'a> for crate::std::import::ImportFormat { } impl<'a> FromKclValue<'a> for super::sketch::AngledLineThatIntersectsData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, angle); - fields_recurse!(obj, intersect_tag "intersectTag"); - fields_recurse_opt!(obj, offset); + let_field_of!(obj, angle); + let_field_of!(obj, intersect_tag "intersectTag"); + let_field_of!(obj, offset?); Some(Self { angle, intersect_tag, @@ -757,12 +733,12 @@ impl<'a> FromKclValue<'a> for super::sketch::AngledLineThatIntersectsData { } impl<'a> FromKclValue<'a> for super::shapes::PolygonData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, radius); - fields_recurse!(obj, num_sides "numSides"); - fields_recurse!(obj, center); - fields_recurse!(obj, inscribed); + let_field_of!(obj, radius); + let_field_of!(obj, num_sides "numSides"); + let_field_of!(obj, center); + let_field_of!(obj, inscribed); let polygon_type = if inscribed { PolygonType::Inscribed } else { @@ -779,21 +755,21 @@ impl<'a> FromKclValue<'a> for super::shapes::PolygonData { } impl<'a> FromKclValue<'a> for crate::std::polar::PolarCoordsData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, angle); - fields_recurse!(obj, length); + let_field_of!(obj, angle); + let_field_of!(obj, length); Some(Self { angle, length }) } } impl<'a> FromKclValue<'a> for crate::std::loft::LoftData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse_opt!(obj, v_degree); - fields_recurse_opt!(obj, bez_approximate_rational); - fields_recurse_opt!(obj, base_curve_index); - fields_recurse_opt!(obj, tolerance); + let_field_of!(obj, v_degree?); + let_field_of!(obj, bez_approximate_rational?); + let_field_of!(obj, base_curve_index?); + let_field_of!(obj, tolerance?); Some(Self { v_degree, bez_approximate_rational, @@ -804,7 +780,7 @@ impl<'a> FromKclValue<'a> for crate::std::loft::LoftData { } impl<'a> FromKclValue<'a> for crate::std::planes::StandardPlane { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let s = arg.as_str()?; match s { "XY" | "xy" => Some(Self::XY), @@ -819,32 +795,32 @@ impl<'a> FromKclValue<'a> for crate::std::planes::StandardPlane { } impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::units::UnitLength { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let s = arg.as_str()?; s.parse().ok() } } impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::System { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, forward); - fields_recurse!(obj, up); + let_field_of!(obj, forward); + let_field_of!(obj, up); Some(Self { forward, up }) } } impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::AxisDirectionPair { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, axis); - fields_recurse!(obj, direction); + let_field_of!(obj, axis); + let_field_of!(obj, direction); Some(Self { axis, direction }) } } impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::Axis { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let s = arg.as_str()?; match s { "y" => Some(Self::Y), @@ -855,7 +831,7 @@ impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::Axis { } impl<'a> FromKclValue<'a> for PolygonType { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let s = arg.as_str()?; match s { "inscribed" => Some(Self::Inscribed), @@ -865,7 +841,7 @@ impl<'a> FromKclValue<'a> for PolygonType { } impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::Direction { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let s = arg.as_str()?; match s { "positive" => Some(Self::Positive), @@ -876,14 +852,14 @@ impl<'a> FromKclValue<'a> for kittycad_modeling_cmds::coord::Direction { } impl<'a> FromKclValue<'a> for super::patterns::CircularPattern3dData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, instances); - fields!(obj, as_f64, arc_degrees "arcDegrees"); - fields!(obj, as_bool, rotate_duplicates "rotateDuplicates"); + let_field_of!(obj, instances); + let_field_of!(obj, arc_degrees "arcDegrees"); + let_field_of!(obj, rotate_duplicates "rotateDuplicates"); let instances = Uint::new(instances); - fields_recurse!(obj, axis); - fields_recurse!(obj, center); + let_field_of!(obj, axis); + let_field_of!(obj, center); Some(Self { instances, axis, @@ -895,13 +871,13 @@ impl<'a> FromKclValue<'a> for super::patterns::CircularPattern3dData { } impl<'a> FromKclValue<'a> for super::patterns::CircularPattern2dData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, instances); - fields!(obj, as_f64, arc_degrees "arcDegrees"); - fields!(obj, as_bool, rotate_duplicates "rotateDuplicates"); + let_field_of!(obj, instances); + let_field_of!(obj, arc_degrees "arcDegrees"); + let_field_of!(obj, rotate_duplicates "rotateDuplicates"); let instances = Uint::new(instances); - fields_recurse!(obj, center); + let_field_of!(obj, center); Some(Self { instances, center, @@ -912,11 +888,12 @@ impl<'a> FromKclValue<'a> for super::patterns::CircularPattern2dData { } impl<'a> FromKclValue<'a> for super::patterns::LinearPattern3dData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, instances, distance); + let_field_of!(obj, distance); + let_field_of!(obj, instances); let instances = Uint::new(instances); - fields_recurse!(obj, axis); + let_field_of!(obj, axis); Some(Self { instances, distance, @@ -926,11 +903,12 @@ impl<'a> FromKclValue<'a> for super::patterns::LinearPattern3dData { } impl<'a> FromKclValue<'a> for super::patterns::LinearPattern2dData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, instances, distance); + let_field_of!(obj, distance); + let_field_of!(obj, instances); let instances = Uint::new(instances); - fields_recurse!(obj, axis); + let_field_of!(obj, axis); Some(Self { instances, distance, @@ -940,37 +918,39 @@ impl<'a> FromKclValue<'a> for super::patterns::LinearPattern2dData { } impl<'a> FromKclValue<'a> for super::sketch::BezierData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_point2d, to, control1, control2); + let_field_of!(obj, to); + let_field_of!(obj, control1); + let_field_of!(obj, control2); Some(Self { to, control1, control2 }) } } impl<'a> FromKclValue<'a> for super::shell::ShellData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, thickness); - fields_recurse!(obj, faces); + let_field_of!(obj, thickness); + let_field_of!(obj, faces); Some(Self { thickness, faces }) } } impl<'a> FromKclValue<'a> for super::chamfer::ChamferData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, length); - fields_recurse!(obj, tags); + let_field_of!(obj, length); + let_field_of!(obj, tags); Some(Self { length, tags }) } } impl<'a> FromKclValue<'a> for super::fillet::FilletData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, radius); - fields_opt!(obj, as_f64, tolerance); - fields_recurse!(obj, tags); + let_field_of!(obj, radius); + let_field_of!(obj, tolerance?); + let_field_of!(obj, tags); Some(Self { radius, tolerance, @@ -980,11 +960,11 @@ impl<'a> FromKclValue<'a> for super::fillet::FilletData { } impl<'a> FromKclValue<'a> for super::helix::HelixData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, revolutions); - fields_opt!(obj, as_f64, length); - fields_opt!(obj, as_bool, ccw); + let_field_of!(obj, revolutions); + let_field_of!(obj, length?); + let_field_of!(obj, ccw?); let ccw = ccw.unwrap_or_default(); let angle_start = obj.get("angleStart").or_else(|| obj.get("angle_start"))?.as_f64()?; Some(Self { @@ -997,14 +977,14 @@ impl<'a> FromKclValue<'a> for super::helix::HelixData { } impl<'a> FromKclValue<'a> for FaceTag { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let case1 = || match arg.as_str() { Some("start" | "START") => Some(Self::StartOrEnd(super::sketch::StartOrEnd::Start)), Some("end" | "END") => Some(Self::StartOrEnd(super::sketch::StartOrEnd::End)), _ => None, }; let case2 = || { - let tag = TagIdentifier::from_mem_item(arg)?; + let tag = TagIdentifier::from_kcl_val(arg)?; Some(Self::Tag(Box::new(tag))) }; case1().or_else(case2) @@ -1012,11 +992,12 @@ impl<'a> FromKclValue<'a> for FaceTag { } impl<'a> FromKclValue<'a> for super::sketch::AngledLineToData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { // Deserialize from an {angle, to} object. let case1 = || { let obj = arg.as_object()?; - fields!(obj, as_f64, angle, to); + let_field_of!(obj, to); + let_field_of!(obj, angle); Some(Self { angle, to }) }; // Deserialize from an [angle, to] array. @@ -1029,9 +1010,9 @@ impl<'a> FromKclValue<'a> for super::sketch::AngledLineToData { } impl<'a> FromKclValue<'a> for super::sketch::ArcData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, radius); + let_field_of!(obj, radius); let case1 = || { let angle_start = obj.get("angleStart").or_else(|| obj.get("angle_start"))?.as_f64()?; let angle_end = obj.get("angleEnd").or_else(|| obj.get("angle_end"))?.as_f64()?; @@ -1043,7 +1024,8 @@ impl<'a> FromKclValue<'a> for super::sketch::ArcData { }; let case2 = || { let obj = arg.as_object()?; - fields!(obj, as_point2d, center, to); + let_field_of!(obj, to); + let_field_of!(obj, center); Some(Self::CenterToRadius { center, to, radius }) }; case1().or_else(case2) @@ -1051,47 +1033,50 @@ impl<'a> FromKclValue<'a> for super::sketch::ArcData { } impl<'a> FromKclValue<'a> for super::revolve::RevolveData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; let angle = obj.get("angle").and_then(|x| x.as_f64()); let tolerance = obj.get("tolerance").and_then(|x| x.as_f64()); - fields_recurse!(obj, axis); + let_field_of!(obj, axis); Some(Self { angle, axis, tolerance }) } } impl<'a> FromKclValue<'a> for super::shapes::CircleData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_point2d, center); - fields!(obj, as_f64, radius); + let_field_of!(obj, center); + let_field_of!(obj, radius); Some(Self { center, radius }) } } impl<'a> FromKclValue<'a> for super::sketch::TangentialArcData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_f64, radius, offset); + let_field_of!(obj, radius); + let_field_of!(obj, offset); Some(Self::RadiusAndOffset { radius, offset }) } } impl<'a> FromKclValue<'a> for crate::executor::Point3d { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { // Case 1: object with x/y/z fields if let Some(obj) = arg.as_object() { - fields!(obj, as_f64, x, y, z); + let_field_of!(obj, x); + let_field_of!(obj, y); + let_field_of!(obj, z); return Some(Self { x, y, z }); } // Case 2: Array of 3 numbers. - let [x, y, z]: [f64; 3] = FromKclValue::from_mem_item(arg)?; + let [x, y, z]: [f64; 3] = FromKclValue::from_kcl_val(arg)?; Some(Self { x, y, z }) } } impl<'a> FromKclValue<'a> for super::sketch::PlaneData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { // Case 0: actual plane if let KclValue::Plane(p) = arg { return Some(Self::Plane { @@ -1115,25 +1100,22 @@ impl<'a> FromKclValue<'a> for super::sketch::PlaneData { } // Case 2: custom plane let obj = arg.as_object()?; - fields!(obj, as_object, plane); - let origin = plane - .get("origin") - .and_then(FromKclValue::from_mem_item) - .map(Box::new)?; + let_field_of!(obj, plane, &std::collections::HashMap); + let origin = plane.get("origin").and_then(FromKclValue::from_kcl_val).map(Box::new)?; let x_axis = plane .get("xAxis") .or_else(|| plane.get("x_axis")) - .and_then(FromKclValue::from_mem_item) + .and_then(FromKclValue::from_kcl_val) .map(Box::new)?; let y_axis = plane .get("yAxis") .or_else(|| plane.get("y_axis")) - .and_then(FromKclValue::from_mem_item) + .and_then(FromKclValue::from_kcl_val) .map(Box::new)?; let z_axis = plane .get("zAxis") .or_else(|| plane.get("z_axis")) - .and_then(FromKclValue::from_mem_item) + .and_then(FromKclValue::from_kcl_val) .map(Box::new)?; Some(Self::Plane { origin, @@ -1145,30 +1127,30 @@ impl<'a> FromKclValue<'a> for super::sketch::PlaneData { } impl<'a> FromKclValue<'a> for crate::executor::ExtrudePlane { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_uuid, face_id "faceId"); - let tag = FromKclValue::from_mem_item(obj.get("tag")?); - fields_recurse!(obj, geo_meta "geoMeta"); + let_field_of!(obj, face_id "faceId"); + let tag = FromKclValue::from_kcl_val(obj.get("tag")?); + let_field_of!(obj, geo_meta "geoMeta"); Some(Self { face_id, tag, geo_meta }) } } impl<'a> FromKclValue<'a> for crate::executor::ExtrudeArc { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_uuid, face_id "faceId"); - let tag = FromKclValue::from_mem_item(obj.get("tag")?); - fields_recurse!(obj, geo_meta "geoMeta"); + let_field_of!(obj, face_id "faceId"); + let tag = FromKclValue::from_kcl_val(obj.get("tag")?); + let_field_of!(obj, geo_meta "geoMeta"); Some(Self { face_id, tag, geo_meta }) } } impl<'a> FromKclValue<'a> for crate::executor::GeoMeta { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_uuid, id); - fields_recurse!(obj, source_range "sourceRange"); + let_field_of!(obj, id); + let_field_of!(obj, source_range "sourceRange"); let source_range = SourceRange(source_range); Some(Self { id, @@ -1178,31 +1160,31 @@ impl<'a> FromKclValue<'a> for crate::executor::GeoMeta { } impl<'a> FromKclValue<'a> for crate::executor::ChamferSurface { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_uuid, face_id "faceId"); - let tag = FromKclValue::from_mem_item(obj.get("tag")?); - fields_recurse!(obj, geo_meta "geoMeta"); + let_field_of!(obj, face_id "faceId"); + let tag = FromKclValue::from_kcl_val(obj.get("tag")?); + let_field_of!(obj, geo_meta "geoMeta"); Some(Self { face_id, tag, geo_meta }) } } impl<'a> FromKclValue<'a> for crate::executor::FilletSurface { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_uuid, face_id "faceId"); - let tag = FromKclValue::from_mem_item(obj.get("tag")?); - fields_recurse!(obj, geo_meta "geoMeta"); + let_field_of!(obj, face_id "faceId"); + let tag = FromKclValue::from_kcl_val(obj.get("tag")?); + let_field_of!(obj, geo_meta "geoMeta"); Some(Self { face_id, tag, geo_meta }) } } impl<'a> FromKclValue<'a> for ExtrudeSurface { - fn from_mem_item(arg: &'a KclValue) -> Option { - let case1 = crate::executor::ExtrudePlane::from_mem_item; - let case2 = crate::executor::ExtrudeArc::from_mem_item; - let case3 = crate::executor::ChamferSurface::from_mem_item; - let case4 = crate::executor::FilletSurface::from_mem_item; + fn from_kcl_val(arg: &'a KclValue) -> Option { + let case1 = crate::executor::ExtrudePlane::from_kcl_val; + let case2 = crate::executor::ExtrudeArc::from_kcl_val; + let case3 = crate::executor::ChamferSurface::from_kcl_val; + let case4 = crate::executor::FilletSurface::from_kcl_val; case1(arg) .map(Self::ExtrudePlane) .or_else(|| case2(arg).map(Self::ExtrudeArc)) @@ -1212,15 +1194,15 @@ impl<'a> FromKclValue<'a> for ExtrudeSurface { } impl<'a> FromKclValue<'a> for crate::executor::EdgeCut { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields!(obj, as_str, typ "type"); - let tag = Box::new(obj.get("tag").and_then(FromKclValue::from_mem_item)); - fields!(obj, as_uuid, edge_id "edgeId"); - fields!(obj, as_uuid, id); + let_field_of!(obj, typ "type"); + let tag = Box::new(obj.get("tag").and_then(FromKclValue::from_kcl_val)); + let_field_of!(obj, edge_id "edgeId"); + let_field_of!(obj, id); match typ { "fillet" => { - fields!(obj, as_f64, radius); + let_field_of!(obj, radius); Some(Self::Fillet { edge_id, tag, @@ -1229,7 +1211,7 @@ impl<'a> FromKclValue<'a> for crate::executor::EdgeCut { }) } "chamfer" => { - fields!(obj, as_f64, length); + let_field_of!(obj, length); Some(Self::Chamfer { id, length, @@ -1245,10 +1227,10 @@ impl<'a> FromKclValue<'a> for crate::executor::EdgeCut { macro_rules! impl_from_kcl_for_vec { ($typ:path) => { impl<'a> FromKclValue<'a> for Vec<$typ> { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.as_array()? .iter() - .map(|value| FromKclValue::from_mem_item(value)) + .map(|value| FromKclValue::from_kcl_val(value)) .collect::>() } } @@ -1263,27 +1245,27 @@ impl_from_kcl_for_vec!(ExtrudeSurface); impl_from_kcl_for_vec!(Sketch); impl<'a> FromKclValue<'a> for crate::executor::SourceRange { - fn from_mem_item(arg: &'a KclValue) -> Option { - FromKclValue::from_mem_item(arg).map(crate::executor::SourceRange) + fn from_kcl_val(arg: &'a KclValue) -> Option { + FromKclValue::from_kcl_val(arg).map(crate::executor::SourceRange) } } impl<'a> FromKclValue<'a> for crate::executor::Metadata { - fn from_mem_item(arg: &'a KclValue) -> Option { - FromKclValue::from_mem_item(arg).map(|sr| Self { source_range: sr }) + fn from_kcl_val(arg: &'a KclValue) -> Option { + FromKclValue::from_kcl_val(arg).map(|sr| Self { source_range: sr }) } } impl<'a> FromKclValue<'a> for crate::executor::Solid { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.as_solid().cloned() } } impl<'a> FromKclValue<'a> for super::sketch::SketchData { - fn from_mem_item(arg: &'a KclValue) -> Option { - let case1 = super::sketch::PlaneData::from_mem_item; - let case2 = crate::executor::Solid::from_mem_item; + fn from_kcl_val(arg: &'a KclValue) -> Option { + let case1 = super::sketch::PlaneData::from_kcl_val; + let case2 = crate::executor::Solid::from_kcl_val; case1(arg) .map(Self::Plane) .or_else(|| case2(arg).map(Box::new).map(Self::Solid)) @@ -1291,7 +1273,7 @@ impl<'a> FromKclValue<'a> for super::sketch::SketchData { } impl<'a> FromKclValue<'a> for super::revolve::AxisAndOrigin { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { // Case 1: predefined planes. if let Some(s) = arg.as_str() { return match s { @@ -1304,41 +1286,43 @@ impl<'a> FromKclValue<'a> for super::revolve::AxisAndOrigin { } // Case 2: custom planes. let obj = arg.as_object()?; - fields!(obj, as_object, custom); - fields!(custom, as_point2d, axis, origin); + let_field_of!(obj, custom, &HashMap); + let_field_of!(custom, origin); + let_field_of!(custom, axis); Some(Self::Custom { axis, origin }) } } impl<'a> FromKclValue<'a> for super::fillet::EdgeReference { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let id = arg.as_uuid().map(Self::Uuid); - let tag = || TagIdentifier::from_mem_item(arg).map(Box::new).map(Self::Tag); + let tag = || TagIdentifier::from_kcl_val(arg).map(Box::new).map(Self::Tag); id.or_else(tag) } } impl<'a> FromKclValue<'a> for super::revolve::AxisOrEdgeReference { - fn from_mem_item(arg: &'a KclValue) -> Option { - let case1 = super::revolve::AxisAndOrigin::from_mem_item; - let case2 = super::fillet::EdgeReference::from_mem_item; + fn from_kcl_val(arg: &'a KclValue) -> Option { + let case1 = super::revolve::AxisAndOrigin::from_kcl_val; + let case2 = super::fillet::EdgeReference::from_kcl_val; case1(arg).map(Self::Axis).or_else(|| case2(arg).map(Self::Edge)) } } impl<'a> FromKclValue<'a> for super::mirror::Mirror2dData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let obj = arg.as_object()?; - fields_recurse!(obj, axis); + let_field_of!(obj, axis); Some(Self { axis }) } } impl<'a> FromKclValue<'a> for super::sketch::AngledLineData { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let case1 = |arg: &KclValue| { let obj = arg.as_object()?; - fields!(obj, as_f64, angle, length); + let_field_of!(obj, angle); + let_field_of!(obj, length); Some(Self::AngleAndLengthNamed { angle, length }) }; let case2 = |arg: &KclValue| { @@ -1352,7 +1336,7 @@ impl<'a> FromKclValue<'a> for super::sketch::AngledLineData { } impl<'a> FromKclValue<'a> for i64 { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Int { value, meta: _ } = arg else { return None; }; @@ -1360,8 +1344,35 @@ impl<'a> FromKclValue<'a> for i64 { } } +impl<'a> FromKclValue<'a> for &'a str { + fn from_kcl_val(arg: &'a KclValue) -> Option<&'a str> { + let KclValue::String { value, meta: _ } = arg else { + return None; + }; + Some(value) + } +} + +impl<'a> FromKclValue<'a> for &'a HashMap { + fn from_kcl_val(arg: &'a KclValue) -> Option<&'a HashMap> { + let KclValue::Object { value, meta: _ } = arg else { + return None; + }; + Some(value) + } +} + +impl<'a> FromKclValue<'a> for uuid::Uuid { + fn from_kcl_val(arg: &'a KclValue) -> Option { + let KclValue::Uuid { value, meta: _ } = arg else { + return None; + }; + Some(*value) + } +} + impl<'a> FromKclValue<'a> for u32 { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Int { value, meta: _ } = arg else { return None; }; @@ -1370,13 +1381,13 @@ impl<'a> FromKclValue<'a> for u32 { } impl<'a> FromKclValue<'a> for NonZeroU32 { - fn from_mem_item(arg: &'a KclValue) -> Option { - u32::from_mem_item(arg).and_then(|x| x.try_into().ok()) + fn from_kcl_val(arg: &'a KclValue) -> Option { + u32::from_kcl_val(arg).and_then(|x| x.try_into().ok()) } } impl<'a> FromKclValue<'a> for u64 { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Int { value, meta: _ } = arg else { return None; }; @@ -1384,7 +1395,7 @@ impl<'a> FromKclValue<'a> for u64 { } } impl<'a> FromKclValue<'a> for f64 { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { match arg { KclValue::Number { value, meta: _ } => Some(*value), KclValue::Int { value, meta: _ } => Some(*value as f64), @@ -1393,7 +1404,7 @@ impl<'a> FromKclValue<'a> for f64 { } } impl<'a> FromKclValue<'a> for Sketch { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Sketch { value } = arg else { return None; }; @@ -1401,7 +1412,7 @@ impl<'a> FromKclValue<'a> for Sketch { } } impl<'a> FromKclValue<'a> for String { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::String { value, meta: _ } = arg else { return None; }; @@ -1409,7 +1420,7 @@ impl<'a> FromKclValue<'a> for String { } } impl<'a> FromKclValue<'a> for crate::ast::types::KclNone { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::KclNone { value, meta: _ } = arg else { return None; }; @@ -1417,7 +1428,7 @@ impl<'a> FromKclValue<'a> for crate::ast::types::KclNone { } } impl<'a> FromKclValue<'a> for bool { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Bool { value, meta: _ } = arg else { return None; }; @@ -1426,12 +1437,12 @@ impl<'a> FromKclValue<'a> for bool { } impl<'a> FromKclValue<'a> for SketchSet { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { match arg { KclValue::Sketch { value: sketch } => Some(SketchSet::from(sketch.to_owned())), KclValue::Sketches { value } => Some(SketchSet::from(value.to_owned())), KclValue::Array { .. } => { - let v: Option> = FromKclValue::from_mem_item(arg); + let v: Option> = FromKclValue::from_kcl_val(arg); Some(SketchSet::Sketches(v?.iter().cloned().map(Box::new).collect())) } _ => None, @@ -1440,7 +1451,7 @@ impl<'a> FromKclValue<'a> for SketchSet { } impl<'a> FromKclValue<'a> for Box { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { let KclValue::Solid(s) = arg else { return None; }; @@ -1449,19 +1460,19 @@ impl<'a> FromKclValue<'a> for Box { } impl<'a> FromKclValue<'a> for FnAsArg<'a> { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.get_function() } } impl<'a> FromKclValue<'a> for SolidSet { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { arg.get_solid_set().ok() } } impl<'a> FromKclValue<'a> for SketchOrSurface { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { match arg { KclValue::Sketch { value: sg } => Some(Self::Sketch(sg.to_owned())), KclValue::Plane(sg) => Some(Self::SketchSurface(SketchSurface::Plane(sg.clone()))), @@ -1471,7 +1482,7 @@ impl<'a> FromKclValue<'a> for SketchOrSurface { } } impl<'a> FromKclValue<'a> for SketchSurface { - fn from_mem_item(arg: &'a KclValue) -> Option { + fn from_kcl_val(arg: &'a KclValue) -> Option { match arg { KclValue::Plane(sg) => Some(Self::Plane(sg.clone())), KclValue::Face(sg) => Some(Self::Face(sg.clone())), diff --git a/src/wasm-lib/kcl/src/std/patterns.rs b/src/wasm-lib/kcl/src/std/patterns.rs index 80e4be3d2..ca1614e01 100644 --- a/src/wasm-lib/kcl/src/std/patterns.rs +++ b/src/wasm-lib/kcl/src/std/patterns.rs @@ -462,7 +462,7 @@ fn array_to_point3d(val: &KclValue, source_ranges: Vec) -> Result