Skip to content

Commit

Permalink
Impl Value for PathSegment
Browse files Browse the repository at this point in the history
This required some refactoring.
  • Loading branch information
adamchalmers committed Dec 15, 2023
1 parent 37b7366 commit 198107e
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 62 deletions.
12 changes: 6 additions & 6 deletions execution-plan/src/api_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ impl ApiEndpoint for MovePathPen {
where
I: Iterator<Item = Address>,
{
let path: Uuid = read::<Primitive>(values.next(), 2, mem)?.try_into()?;
let path: Uuid = read::<Primitive>(values.next(), mem)?.try_into()?;
let path = ModelingCmdId::from(path);
let to = read(values.next(), 2, mem)?;
let to = read(values.next(), mem)?;
Ok(Self { path, to })
}
}
Expand All @@ -39,15 +39,15 @@ impl ApiEndpoint for ExtendPath {
where
I: Iterator<Item = Address>,
{
let path = read::<Primitive>(values.next(), 2, mem)
let path = read::<Primitive>(values.next(), mem)
.and_then(Uuid::try_from)
.map(ModelingCmdId::from)?;
let segment = read(values.next(), 2, mem)?;
let segment = read(values.next(), mem)?;
Ok(Self { path, segment })
}
}

fn read<T: Value>(start_addr: Option<Address>, expected_num: usize, mem: &Memory) -> Result<T> {
let start_addr = start_addr.ok_or(ExecutionError::MemoryWrongSize { expected: expected_num })?;
fn read<T: Value>(start_addr: Option<Address>, mem: &Memory) -> Result<T> {
let start_addr = start_addr.ok_or(ExecutionError::MemoryWrongSize)?;
mem.get_composite(start_addr)
}
11 changes: 4 additions & 7 deletions execution-plan/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ impl Memory {
/// Get a value value (i.e. a value which takes up multiple addresses in memory).
/// Its parts are stored in consecutive memory addresses starting at `start`.
pub fn get_composite<T: Value>(&self, start: Address) -> Result<T> {
let values = &self.0[start.0..];
T::from_parts(values)
let mut values = self.0.iter().skip(start.0).cloned();
T::from_parts(&mut values)
}
}

Expand Down Expand Up @@ -238,11 +238,8 @@ pub enum ExecutionError {
actual: String,
},
/// Memory address was not set.
#[error("Wanted {expected} values but did not get enough")]
MemoryWrongSize {
/// How many values were expected
expected: usize,
},
#[error("Tried to read from empty memory address")]
MemoryWrongSize,
/// You tried to call a KittyCAD endpoint that doesn't exist or isn't implemented.
#[error("No endpoint {name} recognized")]
UnrecognizedEndpoint {
Expand Down
11 changes: 8 additions & 3 deletions execution-plan/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,14 @@ impl crate::value::Value for Primitive {
vec![self]
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let v = values.get(0).ok_or(ExecutionError::MemoryWrongSize { expected: 1 })?;
v.to_owned().ok_or(ExecutionError::MemoryWrongSize { expected: 1 })
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
values
.next()
.and_then(|v| v.to_owned())
.ok_or(ExecutionError::MemoryWrongSize)
}
}

Expand Down
4 changes: 3 additions & 1 deletion execution-plan/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ pub trait Value: Sized {
/// Store the value in memory.
fn into_parts(self) -> Vec<Primitive>;
/// Read the value from memory.
fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError>;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>;
}
126 changes: 81 additions & 45 deletions execution-plan/src/value/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
use kittycad_modeling_cmds::{
ok_response::OkModelingCmdResponse,
output,
shared::{PathSegment, Point2d, Point3d},
shared::{Angle, PathSegment, Point2d, Point3d},
};

use super::Value;
use crate::{Address, ExecutionError, Primitive};
use crate::{ExecutionError, Primitive};

const EMPTY: &str = "EMPTY";
const TAKE_SNAPSHOT: &str = "TAKE_SNAPSHOT";
Expand All @@ -21,6 +21,10 @@ const TAN_ARC: &str = "tan_arc";
const TAN_ARC_TO: &str = "tan_arc_to";
const BEZIER: &str = "bezier";

fn err() -> ExecutionError {
ExecutionError::MemoryWrongSize
}

impl<T> Value for Point2d<T>
where
Primitive: From<T>,
Expand All @@ -31,17 +35,12 @@ where
points.into_iter().map(|component| component.into()).collect()
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let err = || ExecutionError::MemoryWrongSize { expected: 2 };
let [x, y] = [0, 1].map(|n| values.get(n).ok_or(err()));
let x = x?
.to_owned()
.ok_or(ExecutionError::MemoryWrongSize { expected: 2 })?
.try_into()?;
let y = y?
.to_owned()
.ok_or(ExecutionError::MemoryWrongSize { expected: 2 })?
.try_into()?;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
let x = values.next().ok_or(err())?.to_owned().ok_or(err())?.try_into()?;
let y = values.next().ok_or(err())?.to_owned().ok_or(err())?.try_into()?;
Ok(Self { x, y })
}
}
Expand All @@ -56,21 +55,13 @@ where
points.into_iter().map(|component| component.into()).collect()
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let err = || ExecutionError::MemoryWrongSize { expected: 3 };
let [x, y, z] = [0, 1, 2].map(|n| values.get(n).ok_or(err()));
let x = x?
.to_owned()
.ok_or(ExecutionError::MemoryWrongSize { expected: 3 })?
.try_into()?;
let y = y?
.to_owned()
.ok_or(ExecutionError::MemoryWrongSize { expected: 3 })?
.try_into()?;
let z = z?
.to_owned()
.ok_or(ExecutionError::MemoryWrongSize { expected: 3 })?
.try_into()?;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
let x = values.next().ok_or(err())?.to_owned().ok_or(err())?.try_into()?;
let y = values.next().ok_or(err())?.to_owned().ok_or(err())?.try_into()?;
let z = values.next().ok_or(err())?.to_owned().ok_or(err())?.try_into()?;
Ok(Self { x, y, z })
}
}
Expand All @@ -91,12 +82,15 @@ impl Value for OkModelingCmdResponse {
}
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let variant_name: String = get_some(values, 0)?.try_into()?;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
let variant_name: String = next(values)?;
match variant_name.as_str() {
EMPTY => Ok(OkModelingCmdResponse::Empty),
TAKE_SNAPSHOT => {
let contents: Vec<u8> = get_some(values, 1)?.try_into()?;
let contents: Vec<u8> = next(values)?;
Ok(OkModelingCmdResponse::TakeSnapshot(output::TakeSnapshot {
contents: contents.into(),
}))
Expand All @@ -112,19 +106,27 @@ impl Value for output::TakeSnapshot {
vec![Primitive::Bytes(self.contents.into())]
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let contents: Vec<u8> = get_some(values, 0)?.try_into()?;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
let contents: Vec<u8> = next(values)?;
Ok(Self {
contents: contents.into(),
})
}
}

fn get_some(values: &[Option<Primitive>], i: usize) -> Result<Primitive, ExecutionError> {
let addr = Address(0); // TODO: pass the `start` addr in
let v = values.get(i).ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
let v = v.ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
Ok(v)
/// Read the next primitive.
/// If it's
fn next<I, T>(values: &mut I) -> Result<T, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
T: TryFrom<Primitive, Error = ExecutionError>,
{
let v = values.next().ok_or_else(err)?;
let v = v.ok_or_else(err)?;
T::try_from(v)
}

/// Layout:
Expand Down Expand Up @@ -193,25 +195,59 @@ impl Value for PathSegment {
parts
}

fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
let variant_name: String = get_some(values, 0)?.try_into()?;
fn from_parts<I>(values: &mut I) -> Result<Self, ExecutionError>
where
I: Iterator<Item = Option<Primitive>>,
{
let variant_name: String = next(values)?;
match variant_name.as_str() {
LINE => {
let end = Point3d::from_parts(values)?;
let relative = get_some(values, 1)?.try_into()?;
let relative = next(values)?;
Ok(Self::Line { end, relative })
}
ARC => {
todo!()
let center = Point2d::from_parts(values)?;
let radius = Primitive::from_parts(values)?.try_into()?;
let start = Primitive::from_parts(values)?.try_into()?;
let end = Primitive::from_parts(values)?.try_into()?;
let relative = Primitive::from_parts(values)?.try_into()?;
Ok(Self::Arc {
center,
radius,
start,
end,
relative,
})
}
BEZIER => {
todo!()
let control1 = Point3d::from_parts(values)?;
let control2 = Point3d::from_parts(values)?;
let end = Point3d::from_parts(values)?;
let relative = Primitive::from_parts(values)?.try_into()?;
Ok(Self::Bezier {
control1,
control2,
end,
relative,
})
}
TAN_ARC => {
todo!()
let radius = Primitive::from_parts(values).and_then(f64::try_from)?;
let offset = Primitive::from_parts(values).and_then(Angle::try_from)?;
Ok(Self::TangentialArc { radius, offset })
}
TAN_ARC_TO => {
todo!()
let to = Point3d::from_parts(values)?;
let angle_snap_increment = if let Some(Some(primitive)) = values.next() {
Some(Angle::try_from(primitive)?)
} else {
None
};
Ok(Self::TangentialArcTo {
to,
angle_snap_increment,
})
}
other => Err(ExecutionError::InvalidEnumVariant {
expected_type: "line segment".to_owned(),
Expand Down

0 comments on commit 198107e

Please sign in to comment.