inc_complete/computation/
tuple_impls.rs

1use std::any::{Any, TypeId};
2
3use crate::{Cell, Computation, Db, DbHandle};
4
5macro_rules! impl_computation_for_tuple {
6    ($($Middle:ident),+ ; $Last:ident) => {
7        impl<$($Middle,)+ $Last> Computation for ($($Middle,)+ $Last) where
8            $($Middle: Computation,)+
9            $Last: Computation
10        {
11            type Storage = (
12                $($Middle::Storage,)+
13                $Last::Storage
14            );
15            type Output = ();
16
17            fn run(&self, _: &mut DbHandle<impl Computation>) -> Self::Output {
18                panic!("Type dispatch failed in `run`")
19            }
20
21            fn input_to_cell(_: &Self, _: &Self::Storage) -> Option<Cell> {
22                panic!("Type dispatch failed in `input_to_cell`")
23            }
24
25            fn insert_new_cell(_: Cell, _: Self, _: &mut Self::Storage) {
26                panic!("Type dispatch failed in `insert_new_cell`")
27            }
28
29            fn get_function_and_output(_: Cell, _: &Self::Storage) -> (&Self, Option<&Self::Output>) {
30                panic!("Type dispatch failed in `get_function_and_output`")
31            }
32
33            fn set_output(_: Cell, _: Self::Output, _: &mut Self::Storage) {
34                panic!("Type dispatch failed in `set_output`")
35            }
36
37            fn computation_id_of<Concrete: Computation>() -> u32 {
38                let mut i = 0;
39
40                $(
41                    if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
42                        return i;
43                    }
44                    i += 1;
45                )+
46
47                i + $Last::computation_id_of::<Concrete>()
48            }
49
50            fn get_storage<Concrete: Computation + 'static>(computation_id: u32, storage: &Self::Storage) -> &Concrete::Storage {
51                let mut i = 0;
52                #[allow(non_snake_case)]
53                let ($($Middle,)+ $Last,) = storage;
54
55                $(
56                    if computation_id == i {
57                        return $Middle::get_storage::<Concrete>(computation_id - i, $Middle)
58                    }
59                    i += 1;
60                )+
61
62                $Last::get_storage::<Concrete>(computation_id - i, $Last)
63            }
64
65            fn get_storage_mut<Concrete: Computation + 'static>(computation_id: u32, storage: &mut Self::Storage) -> &mut Concrete::Storage {
66                let mut i = 0;
67                #[allow(non_snake_case)]
68                let ($($Middle,)+ $Last,) = storage;
69
70                $(
71                    if computation_id == i {
72                        return $Middle::get_storage_mut::<Concrete>(computation_id - i, $Middle)
73                    }
74                    i += 1;
75                )+
76
77                $Last::get_storage_mut::<Concrete>(computation_id - i, $Last)
78            }
79
80            fn output_is_unset<FullComputation: Computation>(
81                cell: Cell,
82                computation_id: u32,
83                original_computation_id: u32,
84                db: &Db<FullComputation>,
85            ) -> bool {
86                let mut i = 0;
87
88                $(
89                    if computation_id == i {
90                        return $Middle::output_is_unset(cell, computation_id - i, original_computation_id, db);
91                    }
92                    i += 1;
93                )+
94
95                $Last::output_is_unset(cell, computation_id - i, original_computation_id, db)
96            }
97
98            fn dispatch_run<FullComputation>(
99                cell: Cell,
100                computation_id: u32,
101                original_computation_id: u32,
102                db: &mut Db<FullComputation>,
103            ) -> bool where
104                FullComputation: Computation,
105                Self: Clone,
106                Self::Output: Eq,
107            {
108                let mut i = 0;
109
110                $(
111                    if computation_id == i {
112                        return $Middle::dispatch_run(cell, computation_id - i, original_computation_id, db);
113                    }
114                    i += 1;
115                )+
116
117                $Last::dispatch_run(cell, computation_id - i, original_computation_id, db)
118            }
119
120            fn dispatch_update_output<Concrete, FullComputation>(cell: Cell, computation_id: u32, original_computation_id: u32, output: Concrete::Output, db: &mut Db<FullComputation>) -> bool
121                where Concrete: Computation,
122                    FullComputation: Computation,
123                    Self::Output: Eq,
124            {
125                let mut i = 0;
126
127                $(
128                    if computation_id == i {
129                        return $Middle::dispatch_update_output::<Concrete, FullComputation>(cell, computation_id - i, original_computation_id, output, db);
130                    }
131                    i += 1;
132                )+
133
134                $Last::dispatch_update_output::<Concrete, FullComputation>(cell, computation_id - i, original_computation_id, output, db)
135            }
136
137            fn dispatch_input_to_cell<Concrete>(input: &Concrete, storage: &Self::Storage) -> Option<Cell>
138                where Concrete: 'static + Computation + Any
139            {
140                #[allow(non_snake_case)]
141                let ($($Middle,)+ $Last) = storage;
142
143                $(
144                    if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
145                        return $Middle::dispatch_input_to_cell::<Concrete>(input, $Middle);
146                    }
147                )+
148
149                $Last::dispatch_input_to_cell::<Concrete>(input, $Last)
150            }
151
152            fn dispatch_insert_new_cell<Concrete>(cell: Cell, input: Concrete, storage: &mut Self::Storage)
153                where Concrete: 'static + Computation + Any,
154                    Concrete::Storage: 'static,
155            {
156                #[allow(non_snake_case)]
157                let ($($Middle,)+ $Last) = storage;
158
159                $(
160                    if TypeId::of::<Concrete>() == TypeId::of::<$Middle>() {
161                        return $Middle::dispatch_insert_new_cell::<Concrete>(cell, input, $Middle);
162                    }
163                )+
164
165                $Last::dispatch_insert_new_cell::<Concrete>(cell, input, $Last)
166            }
167        }
168    };
169}
170
171// Any computation with more than 26 function types to cache will have to use nested tuples
172// to specify the rest, e.g. `(fn1, fn2, .., fn25, (fn26, fn27, fn28, ..))`.
173impl_computation_for_tuple!(A; Z);
174impl_computation_for_tuple!(A, B; Z);
175impl_computation_for_tuple!(A, B, C; Z);
176impl_computation_for_tuple!(A, B, C, D; Z);
177impl_computation_for_tuple!(A, B, C, D, E; Z);
178impl_computation_for_tuple!(A, B, C, D, E, F; Z);
179impl_computation_for_tuple!(A, B, C, D, E, F, G; Z);
180impl_computation_for_tuple!(A, B, C, D, E, F, G, H; Z);
181impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I; Z);
182impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J; Z);
183impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K; Z);
184impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L; Z);
185impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M; Z);
186impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N; Z);
187impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O; Z);
188impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P; Z);
189impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q; Z);
190impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R; Z);
191impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S; Z);
192impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T; Z);
193impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U; Z);
194impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V; Z);
195impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W; Z);
196impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X; Z);
197impl_computation_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; Z);