1#[cfg(not(feature = "async"))]
38#[macro_export]
39macro_rules! define_intermediate {
40 ( $id:tt, $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+, $run_function:expr) => {
41 define_intermediate!(@ $id, $type_name -> $output_type, false, $( $storage_type )|+, $run_function);
42 };
43 ( $id:tt, assume_changed $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+, $run_function:expr) => {
44 define_intermediate!(@ $id, $type_name -> $output_type, true, $( $storage_type )|+, $run_function);
45 };
46 (@ $id:tt, $type_name:ident -> $output_type:ty, $assume_changed:expr, $( $storage_type:ty )|+, $run_function:expr) => {
47 impl $crate::OutputType for $type_name {
48 type Output = $output_type;
49 const IS_INPUT: bool = false;
50 const ASSUME_CHANGED: bool = $assume_changed;
51 }
52
53 impl $crate::ComputationId for $type_name {
54 fn computation_id() -> u32 {
55 $id
56 }
57 }
58
59 impl $type_name {
60 #[allow(unused)]
61 pub fn get(self, db: &impl $crate::DbGet<$type_name>) -> $output_type {
62 db.get(self)
63 }
64 }
65
66 $(
67 impl $crate::Run<$storage_type> for $type_name {
68 fn run(&self, db: &$crate::DbHandle<$storage_type>) -> $output_type {
69 let f: fn(&Self, &$crate::DbHandle<$storage_type>) -> $output_type =
72 $run_function;
73 f(self, db)
74 }
75 }
76 )+
77 };
78}
79
80#[cfg(feature = "async")]
81#[macro_export]
82macro_rules! define_intermediate {
83 ( $id:tt, $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+, $run_function:expr) => {
84 define_intermediate!(@ $id, $type_name -> $output_type, false, $( $storage_type )|+, $run_function);
85 };
86 ( $id:tt, assume_changed $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+, $run_function:expr) => {
87 define_intermediate!(@ $id, $type_name -> $output_type, true, $( $storage_type )|+, $run_function);
88 };
89 (@ $id:tt, $type_name:ident -> $output_type:ty, $assume_changed:expr, $( $storage_type:ty )|+, $run_function:expr) => {
90 impl $crate::OutputType for $type_name {
91 type Output = $output_type;
92 const IS_INPUT: bool = false;
93 const ASSUME_CHANGED: bool = $assume_changed;
94 }
95
96 impl $crate::ComputationId for $type_name {
97 fn computation_id() -> u32 {
98 $id
99 }
100 }
101
102 impl $type_name {
103 #[allow(unused)]
104 pub fn get(self, db: &impl $crate::DbGet<$type_name>) -> impl Future<Output = $output_type> + Send {
105 db.get(self)
106 }
107 }
108
109 $(
110 impl $crate::Run<$storage_type> for $type_name {
111 fn run<'db>(&self, db: &$crate::DbHandle<'db, $storage_type>) -> impl Future<Output = $output_type> {
112 $run_function(self, db)
113 }
114 }
115 )+
116 };
117}
118
119#[macro_export]
148macro_rules! define_input {
149 ( $id:tt, $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+ ) => {
150 define_input!(@ $id, $type_name -> $output_type, false, $( $storage_type )|+);
151 };
152 ( $id:tt, assume_changed $type_name:ident -> $output_type:ty, $( $storage_type:ty )|+ ) => {
153 define_input!(@ $id, $type_name -> $output_type, true, $( $storage_type )|+);
154 };
155 (@ $id:tt, $type_name:ident -> $output_type:ty, $assume_changed:expr, $( $storage_type:ty )|+ ) => {
156 impl $crate::OutputType for $type_name {
157 type Output = $output_type;
158 const IS_INPUT: bool = true;
159 const ASSUME_CHANGED: bool = $assume_changed;
160 }
161
162 impl $crate::ComputationId for $type_name {
163 fn computation_id() -> u32 {
164 $id
165 }
166 }
167
168 impl $type_name {
169 #[allow(unused)]
170 pub fn get(self, db: &impl $crate::DbGet<$type_name>) -> $output_type {
171 db.get(self)
172 }
173
174 #[allow(unused)]
175 pub fn set<S>(self, db: &mut $crate::Db<S>, value: $output_type) where S: $crate::Storage + $crate::StorageFor<$type_name> {
176 db.update_input(self, value);
177 }
178 }
179
180 $(
181 impl $crate::Run<$storage_type> for $type_name {
182 fn run(&self, _: &$crate::DbHandle<$storage_type>) -> $output_type {
183 panic!("Attempted to call `run` function on input {}, did you forget to call `update_input`?",
184 stringify!($type_name))
185 }
186 }
187 )+
188 };
189}
190
191#[macro_export]
228macro_rules! impl_storage {
229 ($typ:ty, $( $field:ident : $computation_type:ty ),* $(, )? ) => {
230 impl $crate::Storage for $typ {
231 fn output_is_unset(&self, cell: $crate::Cell, computation_id: u32) -> bool {
232 use $crate::StorageFor;
233 match computation_id {
234 $(
235 x if x == <$computation_type as $crate::ComputationId>::computation_id() => {
236 self.$field.get_output(cell).is_none()
237 },
238 )*
239 id => panic!("Unknown computation id: {id}"),
240 }
241 }
242
243 $crate::run_computation!( $($field: $computation_type),* );
244 }
245
246 $(
247 impl $crate::StorageFor<$computation_type> for $typ {
248 fn get_cell_for_computation(&self, key: &$computation_type) -> Option<$crate::Cell> {
249 self.$field.get_cell_for_computation(key)
250 }
251
252 fn insert_new_cell(&self, cell: $crate::Cell, key: $computation_type) {
253 self.$field.insert_new_cell(cell, key)
254 }
255
256 fn get_input(&self, cell: $crate::Cell) -> $computation_type {
257 self.$field.get_input(cell)
258 }
259
260 fn get_output(&self, cell: $crate::Cell) -> Option<<$computation_type as $crate::OutputType>::Output> {
261 self.$field.get_output(cell)
262 }
263
264 fn update_output(&self, cell: $crate::Cell, new_value: <$computation_type as $crate::OutputType>::Output) -> bool {
265 self.$field.update_output(cell, new_value)
266 }
267 })*
268 };
269}
270
271#[cfg(not(feature = "async"))]
272#[doc(hidden)]
273#[macro_export]
274macro_rules! run_computation {
275 ( $($field:ident: $computation_type:ty),* ) => {
276 fn run_computation(db: &$crate::DbHandle<Self>, cell: $crate::Cell, computation_id: u32) -> bool {
277 use $crate::{ StorageFor, Run };
278 match computation_id {
279 $(
280 x if x == <$computation_type as $crate::ComputationId>::computation_id() => {
281 let new_value = db.storage().$field.get_input(cell).run(db);
282 db.storage().$field.update_output(cell, new_value)
283 }
284 )*
285 id => panic!("Unknown computation id: {id}"),
286 }
287 }
288 }
289}
290
291#[cfg(feature = "async")]
292#[doc(hidden)]
293#[macro_export]
294macro_rules! run_computation {
295 ( $($field:ident: $computation_type:ty),* ) => {
296 async fn run_computation<'db>(db: &$crate::DbHandle<'db, Self>, cell: $crate::Cell, computation_id: u32) -> bool {
297 use $crate::{ StorageFor, Run };
298 match computation_id {
299 $(
300 x if x == <$computation_type as $crate::ComputationId>::computation_id() => {
301 let new_value = db.storage().$field.get_input(cell).run(db).await;
302 db.storage().$field.update_output(cell, new_value)
303 }
304 )*
305 id => panic!("Unknown computation id: {id}"),
306 }
307 }
308 }
309}