kittycad_execution_plan_traits/
lib.rs1pub use self::address::Address;
4use self::events::EventWriter;
5pub use self::primitive::{ListHeader, NumericPrimitive, ObjectHeader, Primitive};
6
7use serde::{Deserialize, Serialize};
8
9mod address;
10mod containers;
11pub mod events;
12#[macro_use]
13mod primitive;
14
15pub trait Value: Sized {
19 fn into_parts(self) -> Vec<Primitive>;
21 fn from_parts<I>(values: &mut I) -> Result<(Self, usize), MemoryError>
23 where
24 I: Iterator<Item = Option<Primitive>>;
25}
26
27pub trait FromMemory: Sized {
30 fn from_memory<I, M>(fields: &mut I, mem: &mut M, events: &mut EventWriter) -> Result<Self, MemoryError>
32 where
33 M: ReadMemory,
34 I: Iterator<Item = InMemory>;
35}
36
37#[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Debug)]
39pub enum InMemory {
40 Address(Address),
42 StackPop,
44 StackPeek,
46}
47
48impl From<Address> for InMemory {
49 fn from(a: Address) -> Self {
50 Self::Address(a)
51 }
52}
53
54pub trait ReadMemory {
56 fn get(&self, addr: &Address) -> Option<&Primitive>;
58 fn get_ok(&self, address: &Address) -> Result<Vec<Primitive>, MemoryError> {
60 match self.get(address) {
61 Some(prim) => Ok(vec![prim.clone()]),
62 None => Err(MemoryError::MemoryBadAccess),
63 }
64 }
65
66 fn get_composite<T: Value>(&self, start: Address) -> Result<(T, usize), MemoryError>;
68 fn stack_pop(&mut self) -> Result<Vec<Primitive>, MemoryError>;
70 fn stack_peek(&self) -> Result<Vec<Primitive>, MemoryError>;
72}
73
74#[derive(Debug, thiserror::Error)]
76pub enum MemoryError {
77 #[error("Memory was wrong size")]
79 MemoryWrongSize,
80 #[error("Bad memory access")]
82 MemoryBadAccess,
83 #[error("Tried to read a '{expected}' from KCEP program memory, found an '{actual}' instead")]
85 MemoryWrongType {
86 expected: &'static str,
88 actual: String,
90 },
91 #[error("Found an unexpected tag '{actual}' when trying to read an enum of type {expected_type} from memory. Looking for one of {}", csv(.valid_variants))]
93 InvalidEnumVariant {
94 expected_type: String,
96 actual: String,
98 valid_variants: Vec<&'static str>,
100 },
101 #[error("Stack is empty")]
103 StackEmpty,
104 #[error("Expected stack to contain a single primitive, but it had a slice of length {actual_length}")]
106 StackNotPrimitive {
107 actual_length: usize,
110 },
111 #[error("You didn't supply enough fields -- you have to supply one field per field of the original struct")]
113 NotEnoughFields,
114}
115
116fn csv(v: &[&'static str]) -> String {
117 v.join(", ")
118}
119
120#[macro_export]
124macro_rules! impl_value_on_primitive_ish {
125 ($trait:ident, $subject:ident) => {
126 impl $trait for $subject {
127 fn into_parts(self) -> Vec<Primitive> {
128 vec![self.into()]
129 }
130
131 fn from_parts<I>(values: &mut I) -> Result<(Self, usize), MemoryError>
132 where
133 I: Iterator<Item = Option<Primitive>>,
134 {
135 values
136 .next()
137 .ok_or(MemoryError::MemoryWrongSize)?
138 .to_owned()
139 .ok_or(MemoryError::MemoryWrongSize)?
140 .try_into()
141 .map(|prim| (prim, 1))
142 }
143 }
144 };
145}