Rename Value to Primitive and Composite to Value
This commit is contained in:
		@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::value::{NumericValue, Value};
 | 
					use crate::primitive::{NumericPrimitive, Primitive};
 | 
				
			||||||
use crate::{ExecutionError, Memory, Operand, Operation};
 | 
					use crate::{ExecutionError, Memory, Operand, Operation};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,14 +20,20 @@ macro_rules! arithmetic_body {
 | 
				
			|||||||
            $arith.operand1.eval(&$mem)?.clone(),
 | 
					            $arith.operand1.eval(&$mem)?.clone(),
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
            // If both operands are numeric, then do the arithmetic operation.
 | 
					            // If both operands are numeric, then do the arithmetic operation.
 | 
				
			||||||
            (Value::NumericValue(x), Value::NumericValue(y)) => {
 | 
					            (Primitive::NumericValue(x), Primitive::NumericValue(y)) => {
 | 
				
			||||||
                let num = match (x, y) {
 | 
					                let num = match (x, y) {
 | 
				
			||||||
                    (NumericValue::Integer(x), NumericValue::Integer(y)) => NumericValue::Integer(x.$method(y)),
 | 
					                    (NumericPrimitive::Integer(x), NumericPrimitive::Integer(y)) => {
 | 
				
			||||||
                    (NumericValue::Integer(x), NumericValue::Float(y)) => NumericValue::Float((x as f64).$method(y)),
 | 
					                        NumericPrimitive::Integer(x.$method(y))
 | 
				
			||||||
                    (NumericValue::Float(x), NumericValue::Integer(y)) => NumericValue::Float(x.$method(y as f64)),
 | 
					                    }
 | 
				
			||||||
                    (NumericValue::Float(x), NumericValue::Float(y)) => NumericValue::Float(x.$method(y)),
 | 
					                    (NumericPrimitive::Integer(x), NumericPrimitive::Float(y)) => {
 | 
				
			||||||
 | 
					                        NumericPrimitive::Float((x as f64).$method(y))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    (NumericPrimitive::Float(x), NumericPrimitive::Integer(y)) => {
 | 
				
			||||||
 | 
					                        NumericPrimitive::Float(x.$method(y as f64))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    (NumericPrimitive::Float(x), NumericPrimitive::Float(y)) => NumericPrimitive::Float(x.$method(y)),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                Ok(Value::NumericValue(num))
 | 
					                Ok(Primitive::NumericValue(num))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // This operation can only be done on numeric types.
 | 
					            // This operation can only be done on numeric types.
 | 
				
			||||||
            _ => Err(ExecutionError::CannotApplyOperation {
 | 
					            _ => Err(ExecutionError::CannotApplyOperation {
 | 
				
			||||||
@ -43,7 +49,7 @@ macro_rules! arithmetic_body {
 | 
				
			|||||||
impl Arithmetic {
 | 
					impl Arithmetic {
 | 
				
			||||||
    /// Calculate the the arithmetic equation.
 | 
					    /// Calculate the the arithmetic equation.
 | 
				
			||||||
    /// May read values from the given memory.
 | 
					    /// May read values from the given memory.
 | 
				
			||||||
    pub fn calculate(self, mem: &Memory) -> Result<Value, ExecutionError> {
 | 
					    pub fn calculate(self, mem: &Memory) -> Result<Primitive, ExecutionError> {
 | 
				
			||||||
        use std::ops::{Add, Div, Mul, Sub};
 | 
					        use std::ops::{Add, Div, Mul, Sub};
 | 
				
			||||||
        match self.operation {
 | 
					        match self.operation {
 | 
				
			||||||
            Operation::Add => {
 | 
					            Operation::Add => {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +0,0 @@
 | 
				
			|||||||
use crate::{ExecutionError, Value};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mod impls;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Types that can be written to or read from KCEP program memory,
 | 
					 | 
				
			||||||
/// but require multiple values to store.
 | 
					 | 
				
			||||||
/// They get laid out into multiple consecutive memory addresses.
 | 
					 | 
				
			||||||
pub trait Composite: Sized {
 | 
					 | 
				
			||||||
    /// Store the value in memory.
 | 
					 | 
				
			||||||
    fn into_parts(self) -> Vec<Value>;
 | 
					 | 
				
			||||||
    /// Read the value from memory.
 | 
					 | 
				
			||||||
    fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -7,13 +7,13 @@
 | 
				
			|||||||
//! the results to make other API calls.
 | 
					//! the results to make other API calls.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use self::arithmetic::Arithmetic;
 | 
					use self::arithmetic::Arithmetic;
 | 
				
			||||||
use self::value::Value;
 | 
					use self::primitive::Primitive;
 | 
				
			||||||
use composite::Composite;
 | 
					 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use std::fmt;
 | 
					use std::fmt;
 | 
				
			||||||
 | 
					use value::Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod arithmetic;
 | 
					mod arithmetic;
 | 
				
			||||||
mod composite;
 | 
					mod primitive;
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests;
 | 
					mod tests;
 | 
				
			||||||
mod value;
 | 
					mod value;
 | 
				
			||||||
@ -21,7 +21,7 @@ mod value;
 | 
				
			|||||||
/// KCEP's program memory. A flat, linear list of values.
 | 
					/// KCEP's program memory. A flat, linear list of values.
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
#[cfg_attr(test, derive(PartialEq))]
 | 
					#[cfg_attr(test, derive(PartialEq))]
 | 
				
			||||||
pub struct Memory(Vec<Option<Value>>);
 | 
					pub struct Memory(Vec<Option<Primitive>>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for Memory {
 | 
					impl Default for Memory {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
@ -47,12 +47,12 @@ impl From<usize> for Address {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl Memory {
 | 
					impl Memory {
 | 
				
			||||||
    /// Get a value from KCEP's program memory.
 | 
					    /// Get a value from KCEP's program memory.
 | 
				
			||||||
    pub fn get(&self, Address(addr): &Address) -> Option<&Value> {
 | 
					    pub fn get(&self, Address(addr): &Address) -> Option<&Primitive> {
 | 
				
			||||||
        self.0[*addr].as_ref()
 | 
					        self.0[*addr].as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Store a value in KCEP's program memory.
 | 
					    /// Store a value in KCEP's program memory.
 | 
				
			||||||
    pub fn set(&mut self, Address(addr): Address, value: Value) {
 | 
					    pub fn set(&mut self, Address(addr): Address, value: Primitive) {
 | 
				
			||||||
        // If isn't big enough for this value, double the size of memory until it is.
 | 
					        // If isn't big enough for this value, double the size of memory until it is.
 | 
				
			||||||
        while addr > self.0.len() {
 | 
					        while addr > self.0.len() {
 | 
				
			||||||
            self.0.extend(vec![None; self.0.len()]);
 | 
					            self.0.extend(vec![None; self.0.len()]);
 | 
				
			||||||
@ -60,18 +60,18 @@ impl Memory {
 | 
				
			|||||||
        self.0[addr] = Some(value);
 | 
					        self.0[addr] = Some(value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Store a composite value (i.e. a value which takes up multiple addresses in memory).
 | 
					    /// Store a value value (i.e. a value which takes up multiple addresses in memory).
 | 
				
			||||||
    /// Store its parts in consecutive memory addresses starting at `start`.
 | 
					    /// Store its parts in consecutive memory addresses starting at `start`.
 | 
				
			||||||
    pub fn set_composite<T: Composite>(&mut self, composite_value: T, start: Address) {
 | 
					    pub fn set_composite<T: Value>(&mut self, composite_value: T, start: Address) {
 | 
				
			||||||
        let parts = composite_value.into_parts().into_iter();
 | 
					        let parts = composite_value.into_parts().into_iter();
 | 
				
			||||||
        for (value, addr) in parts.zip(start.0..) {
 | 
					        for (value, addr) in parts.zip(start.0..) {
 | 
				
			||||||
            self.0[addr] = Some(value);
 | 
					            self.0[addr] = Some(value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get a composite value (i.e. a value which takes up multiple addresses in 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`.
 | 
					    /// Its parts are stored in consecutive memory addresses starting at `start`.
 | 
				
			||||||
    pub fn get_composite<T: Composite>(&self, start: Address) -> Result<T, ExecutionError> {
 | 
					    pub fn get_composite<T: Value>(&self, start: Address) -> Result<T, ExecutionError> {
 | 
				
			||||||
        let values = &self.0[start.0..];
 | 
					        let values = &self.0[start.0..];
 | 
				
			||||||
        T::from_parts(values)
 | 
					        T::from_parts(values)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -83,7 +83,7 @@ pub enum Instruction {
 | 
				
			|||||||
    /// Call the KittyCAD API.
 | 
					    /// Call the KittyCAD API.
 | 
				
			||||||
    ApiRequest {
 | 
					    ApiRequest {
 | 
				
			||||||
        /// Which ModelingCmd to call.
 | 
					        /// Which ModelingCmd to call.
 | 
				
			||||||
        /// It's a composite value starting at the given address.
 | 
					        /// It's a value value starting at the given address.
 | 
				
			||||||
        endpoint: Address,
 | 
					        endpoint: Address,
 | 
				
			||||||
        /// Which address should the response be stored in?
 | 
					        /// Which address should the response be stored in?
 | 
				
			||||||
        store_response: Option<usize>,
 | 
					        store_response: Option<usize>,
 | 
				
			||||||
@ -95,7 +95,7 @@ pub enum Instruction {
 | 
				
			|||||||
        /// Which memory address to set.
 | 
					        /// Which memory address to set.
 | 
				
			||||||
        address: Address,
 | 
					        address: Address,
 | 
				
			||||||
        /// What value to set the memory address to.
 | 
					        /// What value to set the memory address to.
 | 
				
			||||||
        value: Value,
 | 
					        value: Primitive,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /// Perform arithmetic on values in memory.
 | 
					    /// Perform arithmetic on values in memory.
 | 
				
			||||||
    Arithmetic {
 | 
					    Arithmetic {
 | 
				
			||||||
@ -130,13 +130,13 @@ impl fmt::Display for Operation {
 | 
				
			|||||||
/// Argument to an operation.
 | 
					/// Argument to an operation.
 | 
				
			||||||
#[derive(Deserialize, Serialize)]
 | 
					#[derive(Deserialize, Serialize)]
 | 
				
			||||||
pub enum Operand {
 | 
					pub enum Operand {
 | 
				
			||||||
    Literal(Value),
 | 
					    Literal(Primitive),
 | 
				
			||||||
    Reference(Address),
 | 
					    Reference(Address),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Operand {
 | 
					impl Operand {
 | 
				
			||||||
    /// Evaluate the operand, getting its value.
 | 
					    /// Evaluate the operand, getting its value.
 | 
				
			||||||
    fn eval(&self, mem: &Memory) -> Result<Value, ExecutionError> {
 | 
					    fn eval(&self, mem: &Memory) -> Result<Primitive, ExecutionError> {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Operand::Literal(v) => Ok(v.to_owned()),
 | 
					            Operand::Literal(v) => Ok(v.to_owned()),
 | 
				
			||||||
            Operand::Reference(addr) => match mem.get(addr) {
 | 
					            Operand::Reference(addr) => match mem.get(addr) {
 | 
				
			||||||
@ -173,7 +173,7 @@ pub enum ExecutionError {
 | 
				
			|||||||
    #[error("Memory address {addr} was not set")]
 | 
					    #[error("Memory address {addr} was not set")]
 | 
				
			||||||
    MemoryEmpty { addr: Address },
 | 
					    MemoryEmpty { addr: Address },
 | 
				
			||||||
    #[error("Cannot apply operation {op} to operands {operands:?}")]
 | 
					    #[error("Cannot apply operation {op} to operands {operands:?}")]
 | 
				
			||||||
    CannotApplyOperation { op: Operation, operands: Vec<Value> },
 | 
					    CannotApplyOperation { op: Operation, operands: Vec<Primitive> },
 | 
				
			||||||
    #[error("Tried to read a '{expected}' from KCEP program memory, found an '{actual}' instead")]
 | 
					    #[error("Tried to read a '{expected}' from KCEP program memory, found an '{actual}' instead")]
 | 
				
			||||||
    MemoryWrongType { expected: &'static str, actual: String },
 | 
					    MemoryWrongType { expected: &'static str, actual: String },
 | 
				
			||||||
    #[error("Wanted {expected} values but did not get enough")]
 | 
					    #[error("Wanted {expected} values but did not get enough")]
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										87
									
								
								src/wasm-lib/execution-plan/src/primitive.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/wasm-lib/execution-plan/src/primitive.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					use crate::ExecutionError;
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					use uuid::Uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A value stored in KCEP program memory.
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub enum Primitive {
 | 
				
			||||||
 | 
					    String(String),
 | 
				
			||||||
 | 
					    NumericValue(NumericPrimitive),
 | 
				
			||||||
 | 
					    Uuid(Uuid),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<Uuid> for Primitive {
 | 
				
			||||||
 | 
					    fn from(u: Uuid) -> Self {
 | 
				
			||||||
 | 
					        Self::Uuid(u)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<String> for Primitive {
 | 
				
			||||||
 | 
					    fn from(value: String) -> Self {
 | 
				
			||||||
 | 
					        Self::String(value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<f64> for Primitive {
 | 
				
			||||||
 | 
					    fn from(value: f64) -> Self {
 | 
				
			||||||
 | 
					        Self::NumericValue(NumericPrimitive::Float(value))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl TryFrom<Primitive> for String {
 | 
				
			||||||
 | 
					    type Error = ExecutionError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn try_from(value: Primitive) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        if let Primitive::String(s) = value {
 | 
				
			||||||
 | 
					            Ok(s)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(ExecutionError::MemoryWrongType {
 | 
				
			||||||
 | 
					                expected: "string",
 | 
				
			||||||
 | 
					                actual: format!("{value:?}"),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl TryFrom<Primitive> for Uuid {
 | 
				
			||||||
 | 
					    type Error = ExecutionError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn try_from(value: Primitive) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        if let Primitive::Uuid(u) = value {
 | 
				
			||||||
 | 
					            Ok(u)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(ExecutionError::MemoryWrongType {
 | 
				
			||||||
 | 
					                expected: "uuid",
 | 
				
			||||||
 | 
					                actual: format!("{value:?}"),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl TryFrom<Primitive> for f64 {
 | 
				
			||||||
 | 
					    type Error = ExecutionError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn try_from(value: Primitive) -> Result<Self, Self::Error> {
 | 
				
			||||||
 | 
					        if let Primitive::NumericValue(NumericPrimitive::Float(x)) = value {
 | 
				
			||||||
 | 
					            Ok(x)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(ExecutionError::MemoryWrongType {
 | 
				
			||||||
 | 
					                expected: "float",
 | 
				
			||||||
 | 
					                actual: format!("{value:?}"),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					impl From<usize> for Primitive {
 | 
				
			||||||
 | 
					    fn from(value: usize) -> Self {
 | 
				
			||||||
 | 
					        Self::NumericValue(NumericPrimitive::Integer(value))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub enum NumericPrimitive {
 | 
				
			||||||
 | 
					    Integer(usize),
 | 
				
			||||||
 | 
					    Float(f64),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,87 +1,13 @@
 | 
				
			|||||||
use crate::ExecutionError;
 | 
					use crate::{ExecutionError, Primitive};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					 | 
				
			||||||
use uuid::Uuid;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A value stored in KCEP program memory.
 | 
					mod impls;
 | 
				
			||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 | 
					 | 
				
			||||||
pub enum Value {
 | 
					 | 
				
			||||||
    String(String),
 | 
					 | 
				
			||||||
    NumericValue(NumericValue),
 | 
					 | 
				
			||||||
    Uuid(Uuid),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<Uuid> for Value {
 | 
					/// Types that can be written to or read from KCEP program memory.
 | 
				
			||||||
    fn from(u: Uuid) -> Self {
 | 
					/// If they require multiple memory addresses, they will be laid out
 | 
				
			||||||
        Self::Uuid(u)
 | 
					/// into multiple consecutive memory addresses.
 | 
				
			||||||
    }
 | 
					pub trait Value: Sized {
 | 
				
			||||||
}
 | 
					    /// Store the value in memory.
 | 
				
			||||||
 | 
					    fn into_parts(self) -> Vec<Primitive>;
 | 
				
			||||||
impl From<String> for Value {
 | 
					    /// Read the value from memory.
 | 
				
			||||||
    fn from(value: String) -> Self {
 | 
					    fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError>;
 | 
				
			||||||
        Self::String(value)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl From<f64> for Value {
 | 
					 | 
				
			||||||
    fn from(value: f64) -> Self {
 | 
					 | 
				
			||||||
        Self::NumericValue(NumericValue::Float(value))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<Value> for String {
 | 
					 | 
				
			||||||
    type Error = ExecutionError;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: Value) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        if let Value::String(s) = value {
 | 
					 | 
				
			||||||
            Ok(s)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Err(ExecutionError::MemoryWrongType {
 | 
					 | 
				
			||||||
                expected: "string",
 | 
					 | 
				
			||||||
                actual: format!("{value:?}"),
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<Value> for Uuid {
 | 
					 | 
				
			||||||
    type Error = ExecutionError;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: Value) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        if let Value::Uuid(u) = value {
 | 
					 | 
				
			||||||
            Ok(u)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Err(ExecutionError::MemoryWrongType {
 | 
					 | 
				
			||||||
                expected: "uuid",
 | 
					 | 
				
			||||||
                actual: format!("{value:?}"),
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TryFrom<Value> for f64 {
 | 
					 | 
				
			||||||
    type Error = ExecutionError;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn try_from(value: Value) -> Result<Self, Self::Error> {
 | 
					 | 
				
			||||||
        if let Value::NumericValue(NumericValue::Float(x)) = value {
 | 
					 | 
				
			||||||
            Ok(x)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Err(ExecutionError::MemoryWrongType {
 | 
					 | 
				
			||||||
                expected: "float",
 | 
					 | 
				
			||||||
                actual: format!("{value:?}"),
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(test)]
 | 
					 | 
				
			||||||
impl From<usize> for Value {
 | 
					 | 
				
			||||||
    fn from(value: usize) -> Self {
 | 
					 | 
				
			||||||
        Self::NumericValue(NumericValue::Integer(value))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 | 
					 | 
				
			||||||
pub enum NumericValue {
 | 
					 | 
				
			||||||
    Integer(usize),
 | 
					 | 
				
			||||||
    Float(f64),
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,21 +1,21 @@
 | 
				
			|||||||
use kittycad_modeling_cmds::{id::ModelingCmdId, shared::Point3d, MovePathPen};
 | 
					use kittycad_modeling_cmds::{id::ModelingCmdId, shared::Point3d, MovePathPen};
 | 
				
			||||||
use uuid::Uuid;
 | 
					use uuid::Uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{Address, ExecutionError, Value};
 | 
					use crate::{Address, ExecutionError, Primitive};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::Composite;
 | 
					use super::Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T> Composite for kittycad_modeling_cmds::shared::Point3d<T>
 | 
					impl<T> Value for kittycad_modeling_cmds::shared::Point3d<T>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    Value: From<T>,
 | 
					    Primitive: From<T>,
 | 
				
			||||||
    T: TryFrom<Value, Error = ExecutionError>,
 | 
					    T: TryFrom<Primitive, Error = ExecutionError>,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn into_parts(self) -> Vec<Value> {
 | 
					    fn into_parts(self) -> Vec<Primitive> {
 | 
				
			||||||
        let points = [self.x, self.y, self.z];
 | 
					        let points = [self.x, self.y, self.z];
 | 
				
			||||||
        points.into_iter().map(|component| component.into()).collect()
 | 
					        points.into_iter().map(|component| component.into()).collect()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> {
 | 
					    fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
 | 
				
			||||||
        let err = ExecutionError::MemoryWrongSize { expected: 3 };
 | 
					        let err = ExecutionError::MemoryWrongSize { expected: 3 };
 | 
				
			||||||
        let [x, y, z] = [0, 1, 2].map(|n| values.get(n).ok_or(err.clone()));
 | 
					        let [x, y, z] = [0, 1, 2].map(|n| values.get(n).ok_or(err.clone()));
 | 
				
			||||||
        let x = x?.to_owned().ok_or(err.clone())?.try_into()?;
 | 
					        let x = x?.to_owned().ok_or(err.clone())?.try_into()?;
 | 
				
			||||||
@ -28,17 +28,17 @@ where
 | 
				
			|||||||
const START_PATH: &str = "StartPath";
 | 
					const START_PATH: &str = "StartPath";
 | 
				
			||||||
const MOVE_PATH_PEN: &str = "MovePathPen";
 | 
					const MOVE_PATH_PEN: &str = "MovePathPen";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Composite for MovePathPen {
 | 
					impl Value for MovePathPen {
 | 
				
			||||||
    fn into_parts(self) -> Vec<Value> {
 | 
					    fn into_parts(self) -> Vec<Primitive> {
 | 
				
			||||||
        let MovePathPen { path, to } = self;
 | 
					        let MovePathPen { path, to } = self;
 | 
				
			||||||
        let to = to.into_parts();
 | 
					        let to = to.into_parts();
 | 
				
			||||||
        let mut vals = Vec::with_capacity(1 + to.len());
 | 
					        let mut vals = Vec::with_capacity(1 + to.len());
 | 
				
			||||||
        vals.push(Value::Uuid(path.into()));
 | 
					        vals.push(Primitive::Uuid(path.into()));
 | 
				
			||||||
        vals.extend(to);
 | 
					        vals.extend(to);
 | 
				
			||||||
        vals
 | 
					        vals
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> {
 | 
					    fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
 | 
				
			||||||
        let path = get_some(values, 0)?;
 | 
					        let path = get_some(values, 0)?;
 | 
				
			||||||
        let path = Uuid::try_from(path)?;
 | 
					        let path = Uuid::try_from(path)?;
 | 
				
			||||||
        let path = ModelingCmdId::from(path);
 | 
					        let path = ModelingCmdId::from(path);
 | 
				
			||||||
@ -51,14 +51,14 @@ impl Composite for MovePathPen {
 | 
				
			|||||||
/// Memory layout for modeling commands:
 | 
					/// Memory layout for modeling commands:
 | 
				
			||||||
/// Field 0 is the command's name.
 | 
					/// Field 0 is the command's name.
 | 
				
			||||||
/// Fields 1 onwards are the command's fields.
 | 
					/// Fields 1 onwards are the command's fields.
 | 
				
			||||||
impl Composite for kittycad_modeling_cmds::ModelingCmd {
 | 
					impl Value for kittycad_modeling_cmds::ModelingCmd {
 | 
				
			||||||
    fn into_parts(self) -> Vec<Value> {
 | 
					    fn into_parts(self) -> Vec<Primitive> {
 | 
				
			||||||
        let (endpoint_name, params) = match self {
 | 
					        let (endpoint_name, params) = match self {
 | 
				
			||||||
            kittycad_modeling_cmds::ModelingCmd::StartPath => (START_PATH, vec![]),
 | 
					            kittycad_modeling_cmds::ModelingCmd::StartPath => (START_PATH, vec![]),
 | 
				
			||||||
            kittycad_modeling_cmds::ModelingCmd::MovePathPen(MovePathPen { path, to }) => {
 | 
					            kittycad_modeling_cmds::ModelingCmd::MovePathPen(MovePathPen { path, to }) => {
 | 
				
			||||||
                let to = to.into_parts();
 | 
					                let to = to.into_parts();
 | 
				
			||||||
                let mut vals = Vec::with_capacity(1 + to.len());
 | 
					                let mut vals = Vec::with_capacity(1 + to.len());
 | 
				
			||||||
                vals.push(Value::Uuid(path.into()));
 | 
					                vals.push(Primitive::Uuid(path.into()));
 | 
				
			||||||
                vals.extend(to);
 | 
					                vals.extend(to);
 | 
				
			||||||
                (MOVE_PATH_PEN, vals)
 | 
					                (MOVE_PATH_PEN, vals)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -70,7 +70,7 @@ impl Composite for kittycad_modeling_cmds::ModelingCmd {
 | 
				
			|||||||
        out
 | 
					        out
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> {
 | 
					    fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> {
 | 
				
			||||||
        // Check the array has an element at index 0
 | 
					        // Check the array has an element at index 0
 | 
				
			||||||
        let first_memory = values
 | 
					        let first_memory = values
 | 
				
			||||||
            .get(0)
 | 
					            .get(0)
 | 
				
			||||||
@ -90,7 +90,7 @@ impl Composite for kittycad_modeling_cmds::ModelingCmd {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_some(values: &[Option<Value>], i: usize) -> Result<Value, ExecutionError> {
 | 
					fn get_some(values: &[Option<Primitive>], i: usize) -> Result<Primitive, ExecutionError> {
 | 
				
			||||||
    let addr = Address(0); // TODO: pass the `start` addr in
 | 
					    let addr = Address(0); // TODO: pass the `start` addr in
 | 
				
			||||||
    let v = values.get(i).ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
 | 
					    let v = values.get(i).ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
 | 
				
			||||||
    let v = v.ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
 | 
					    let v = v.ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned();
 | 
				
			||||||
		Reference in New Issue
	
	Block a user