Refactor: Clean up FromKclValue code (#4489)

* Rename ::from_mem_item to ::from_kcl_val

The old name is from a dark time lost to human memory,
when we had an enum called MemoryItem.

* Simplify the FromKclValue macros

There's only really need for one macro, not three.
This commit is contained in:
Adam Chalmers
2024-11-16 11:19:00 -06:00
committed by GitHub
parent 16c7a2457a
commit fbb7b08b62
2 changed files with 223 additions and 212 deletions

View File

@ -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<Self>;
fn from_kcl_val(arg: &'a KclValue) -> Option<Self>;
}
impl<'a> FromArgs<'a> for Vec<KclValue> {
@ -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<Self, KclError> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.get_tag_declarator().ok()
}
}
impl<'a> FromKclValue<'a> for TagIdentifier {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.get_tag_identifier().ok()
}
}
impl<'a> FromKclValue<'a> for KclValue {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
// 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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
// 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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
// 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<String, KclValue>);
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
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<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.as_array()?
.iter()
.map(|value| FromKclValue::from_mem_item(value))
.map(|value| FromKclValue::from_kcl_val(value))
.collect::<Option<_>>()
}
}
@ -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<Self> {
FromKclValue::from_mem_item(arg).map(crate::executor::SourceRange)
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
FromKclValue::from_mem_item(arg).map(|sr| Self { source_range: sr })
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.as_solid().cloned()
}
}
impl<'a> FromKclValue<'a> for super::sketch::SketchData {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
let case1 = super::sketch::PlaneData::from_mem_item;
let case2 = crate::executor::Solid::from_mem_item;
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
// 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<String, KclValue>);
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
let case1 = super::revolve::AxisAndOrigin::from_mem_item;
let case2 = super::fillet::EdgeReference::from_mem_item;
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<String, KclValue> {
fn from_kcl_val(arg: &'a KclValue) -> Option<&'a HashMap<String, KclValue>> {
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<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
u32::from_mem_item(arg).and_then(|x| x.try_into().ok())
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Vec<Sketch>> = FromKclValue::from_mem_item(arg);
let v: Option<Vec<Sketch>> = 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<Solid> {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let KclValue::Solid(s) = arg else {
return None;
};
@ -1449,19 +1460,19 @@ impl<'a> FromKclValue<'a> for Box<Solid> {
}
impl<'a> FromKclValue<'a> for FnAsArg<'a> {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.get_function()
}
}
impl<'a> FromKclValue<'a> for SolidSet {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
arg.get_solid_set().ok()
}
}
impl<'a> FromKclValue<'a> for SketchOrSurface {
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
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<Self> {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
match arg {
KclValue::Plane(sg) => Some(Self::Plane(sg.clone())),
KclValue::Face(sg) => Some(Self::Face(sg.clone())),

View File

@ -462,7 +462,7 @@ fn array_to_point3d(val: &KclValue, source_ranges: Vec<SourceRange>) -> Result<P
// Gets an f64 from a KCL value.
let f = |k: &KclValue, component: char| {
use super::args::FromKclValue;
if let Some(value) = f64::from_mem_item(k) {
if let Some(value) = f64::from_kcl_val(k) {
Ok(value)
} else {
Err(KclError::Semantic(KclErrorDetails {