1#[macro_export]
16macro_rules! impl_struct_data {
17    ($name:ident = $value:expr $(, $from:literal => $to:literal)* $(,)?) => {
18        impl_name_by_member! { $name }
19        impl_default_by_value! { $name = $value }
20        impl_display_by_patched_debug! { $name $(, $from => $to)* }
21    };
22}
23
24#[doc(hidden)]
26#[macro_export]
27macro_rules! impl_name_by_member {
28    ($name:ident) => {
29        impl total_space::Name for $name {
30            fn name(&self) -> String {
31                let name: &'static str = std::convert::From::from(self.name);
32                name.to_string()
33            }
34        }
35    };
36}
37
38#[macro_export]
49macro_rules! impl_enum_data {
50    ($name:ident = $value:expr $(, $from:literal => $to:literal)* $(,)?) => {
51        impl_default_by_value! { $name = $value }
52        impl_name_for_into_static_str! { $name $(, $from => $to)* }
53        impl_display_by_patched_debug! { $name, "name=" => "" $(, $from => $to)* }
54    };
55}
56
57#[doc(hidden)]
59#[macro_export]
60macro_rules! impl_default_by_value {
61    ($name:ident = $value:expr) => {
62        impl Default for $name {
63            fn default() -> Self {
64                $value
65            }
66        }
67    };
68}
69
70#[doc(hidden)]
75#[macro_export]
76macro_rules! impl_name_for_into_static_str {
77    ($name:ident $(, $from:literal => $to:literal)* $(,)?) => {
78        impl total_space::Name for $name {
79            fn name(&self) -> String {
80                let static_str: &'static str = self.into();
81                let string = static_str.to_string();
82                $(
83                    let string = string.replace($from, $to);
84                )*
85                string
86            }
87        }
88    };
89}
90
91#[doc(hidden)]
95#[macro_export]
96macro_rules! impl_display_by_patched_debug {
97    ($name:ident $(, $from:literal => $to:literal)* $(,)?) => {
98        impl Display for $name {
99            fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatterResult {
100                let string = format!("{:?}", self)
101                    .replace(" ", "")
102                    .replace(":", "=")
103                    .replace("{", "(")
104                    .replace("}", ")");
105                $(
106                    let string = string.replace($from, $to);
107                )*
108                write!(formatter, "{}", string)
109            }
110        }
111    };
112}
113
114#[macro_export]
122macro_rules! declare_agent_type_data {
123    ($name:ident, $agent:ident, $model:ident) => {
124        std::thread_local! {
125            static $name: std::cell::RefCell<
126                Option<
127                   std::rc::Rc<
128                        AgentTypeData::<
129                            $agent,
130                            <$model as MetaModel>::StateId,
131                            <$model as MetaModel>::Payload,
132                        >
133                    >
134                >
135            > = std::cell::RefCell::new(None);
136        }
137    };
138}
139
140#[macro_export]
146macro_rules! init_agent_type_data {
147    ($name:ident, $agent_type:expr) => {
148        $name.with(|data| *data.borrow_mut() = Some($agent_type.clone()))
149    };
150}
151
152#[macro_export]
157macro_rules! declare_agent_indices {
158    ($name:ident) => {
159        thread_local! {
160            static $name: std::cell::RefCell<Vec<usize>> = std::cell::RefCell::new(Vec::new());
161        }
162    };
163}
164
165#[macro_export]
170macro_rules! declare_agent_index {
171    ($name:ident) => {
172        thread_local! {
173            static $name: std::cell::RefCell<usize> = std::cell::RefCell::new(usize::max_value());
174        }
175    };
176}
177
178#[macro_export]
184macro_rules! init_agent_indices {
185    ($name:ident, $agent_type:expr) => {{
186        assert!(!$agent_type.is_singleton());
187        $name.with(|refcell| {
188            let mut indices = refcell.borrow_mut();
189            indices.clear();
190            for instance in 0..$agent_type.instances_count() {
191                indices.push($agent_type.first_index() + instance);
192            }
193        });
194    }};
195}
196
197#[macro_export]
203macro_rules! init_agent_index {
204    ($name:ident, $agent_type:expr) => {
205        assert!($agent_type.is_singleton());
206        $name.with(|refcell| *refcell.borrow_mut() = $agent_type.first_index());
207    };
208}
209
210#[macro_export]
216macro_rules! agent_index {
217    ($name:ident) => {{
218        $name.with(|refcell| *refcell.borrow())
219    }};
220    ($name:ident[$index:expr]) => {
221        $name.with(|refcell| refcell.borrow()[$index])
222    };
223}
224
225#[macro_export]
231macro_rules! agents_count {
232    ($name:ident) => {
233        $name.with(|refcell| refcell.borrow().len())
234    };
235}
236
237#[macro_export]
242macro_rules! activity_alternatives {
243    ($payload1:expr, $payload2:expr $(,)?) => {
244        total_space::Activity::Process1Of([
245            Some($payload1),
246            Some($payload2),
247            None,
248            None,
249            None,
250            None,
251        ])
252    };
253    ($payload1:expr, $payload2:expr $(,)?) => {
254        total_space::Activity::Process1Of([
255            Some($payload1),
256            Some($payload2),
257            None,
258            None,
259            None,
260            None,
261        ])
262    };
263    ($payload1:expr, $payload2:expr, $payload3:expr $(,)?) => {
264        total_space::Activity::Process1Of([
265            Some($payload1),
266            Some($payload2),
267            Some($payload3),
268            None,
269            None,
270            None,
271        ])
272    };
273    ($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr $(,)?) => {
274        total_space::Activity::Process1Of([
275            Some($payload1),
276            Some($payload2),
277            Some($payload3),
278            Some($payload4),
279            None,
280            None,
281        ])
282    };
283    ($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr, $payload5:expr $(,)?) => {
284        total_space::Activity::Process1Of([
285            Some($payload1),
286            Some($payload2),
287            Some($payload3),
288            Some($payload4),
289            Some($payload5),
290            None,
291        ])
292    };
293    ($payload1:expr, $payload2:expr, $payload3:expr, $payload4:expr, $payload5:expr, $payload6:expr $(,)?) => {
294        total_space::Activity::Process1Of([
295            Some($payload1),
296            Some($payload2),
297            Some($payload3),
298            Some($payload4),
299            Some($payload5),
300            Some($payload6),
301        ])
302    };
303    ($_:tt) => {
304        compile_error!("expected 2 to 6 payloads");
305    };
306}
307
308#[macro_export]
313macro_rules! reaction_alternatives {
314    ($action1:expr, $action2:expr $(,)?) => {
315        total_space::Reaction::Do1Of([Some(action1), Some(action2), None, None, None, None])
316    };
317    ($action1:expr, $action2:expr, $action3:expr $(,)?) => {
318        total_space::Reaction::Do1Of([
319            Some(action1),
320            Some(action2),
321            Some(action3),
322            None,
323            None,
324            None,
325        ])
326    };
327    ($action1:expr, $action2:expr, $action3:expr, $action4:expr $(,)?) => {
328        total_space::Reaction::Do1Of([
329            Some(action1),
330            Some(action2),
331            Some(action3),
332            Some(action4),
333            None,
334            None,
335        ])
336    };
337    ($action1:expr, $action2:expr, $action3:expr, $action4:expr, $action5:expr $(,)?) => {
338        total_space::Reaction::Do1Of([
339            Some(action1),
340            Some(action2),
341            Some(action3),
342            Some(action4),
343            Some(action5),
344            None,
345        ])
346    };
347    ($action1:expr, $action2:expr, $action3:expr, $action4:expr, $action5:expr, $action6:expr $(,)?) => {
348        total_space::Reaction::Do1Of([
349            Some(action1),
350            Some(action2),
351            Some(action3),
352            Some(action4),
353            Some(action5),
354            Some(action6),
355        ])
356    };
357    ($_:tt) => {
358        compile_error!("expected 2 to 6 actions");
359    };
360}
361
362#[macro_export]
366macro_rules! action_sends {
367    ($emit1:expr, $emit2:expr $(,)?) => {
368        total_space::Action::Sends([Some($emit1), Some($emit2), None, None, None, None])
369    };
370    ($emit1:expr, $emit2:expr, $emit3:expr $(,)?) => {
371        total_space::Action::Sends([Some($emit1), Some($emit2), Some($emit3), None, None, None])
372    };
373    ($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr $(,)?) => {
374        total_space::Action::Sends([
375            Some($emit1),
376            Some($emit2),
377            Some($emit3),
378            Some($emit4),
379            None,
380            None,
381        ])
382    };
383    ($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr $(,)?) => {
384        total_space::Action::Sends([
385            Some($emit1),
386            Some($emit2),
387            Some($emit3),
388            Some($emit4),
389            Some($emit5),
390            None,
391        ])
392    };
393    ($emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr, $emit6:expr $(,)?) => {
394        total_space::Action::Sends([
395            Some($emit1),
396            Some($emit2),
397            Some($emit3),
398            Some($emit4),
399            Some($emit5),
400            Some($emit6),
401        ])
402    };
403    ($_:tt) => {
404        compile_error!("expected 2 to 6 emits");
405    };
406}
407
408#[macro_export]
413macro_rules! action_change_and_sends {
414    ($state:expr, $emit1:expr, $emit2:expr $(,)?) => {
415        total_space::Action::ChangeAndSends(
416            $state,
417            [Some($emit1), Some($emit2), None, None, None, None],
418        )
419    };
420    ($state:expr, $emit1:expr, $emit2:expr, $emit3:expr $(,)?) => {
421        total_space::Action::ChangeAndSends(
422            $state,
423            [Some($emit1), Some($emit2), Some($emit3), None, None, None],
424        )
425    };
426    ($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr $(,)?) => {
427        total_space::Action::ChangeAndSends(
428            $state,
429            [
430                Some($emit1),
431                Some($emit2),
432                Some($emit3),
433                Some($emit4),
434                None,
435                None,
436            ],
437        )
438    };
439    ($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr $(,)?) => {
440        total_space::Action::ChangeAndSends(
441            $state,
442            [
443                Some($emit1),
444                Some($emit2),
445                Some($emit3),
446                Some($emit4),
447                Some($emit5),
448                None,
449            ],
450        )
451    };
452    ($state:expr, $emit1:expr, $emit2:expr, $emit3:expr, $emit4:expr, $emit5:expr, $emit6:expr $(,)?) => {
453        total_space::Action::ChangeAndSends(
454            $state,
455            [
456                Some($emit1),
457                Some($emit2),
458                Some($emit3),
459                Some($emit4),
460                Some($emit5),
461                Some($emit6),
462            ],
463        )
464    };
465    ($_:tt) => {
466        compile_error!("expected state and 2 to 6 emits");
467    };
468}
469
470#[macro_export]
475macro_rules! assert_configuration_hash_entry_size {
476    ($model:ident, $size:literal) => {
477        const _: usize = 0
478            - (std::mem::size_of::<<$model as MetaModel>::ConfigurationHashEntry>() != $size)
479                as usize;
480    };
481}
482
483#[macro_export]
490macro_rules! agent_states_iter {
491    ($configuration:expr, $name:ident, $($iter:tt)*) => {
492        $name.with(|refcell| {
493            if let Some(agent_type) = refcell.borrow().as_ref() {
494                (0..agent_type.instances_count())
495                    .map(|agent_instance| {
496                        let agent_index = agent_type.first_index() + agent_instance;
497                        let state_id = $configuration.state_ids[agent_index];
498                        agent_type.get_state(state_id)
499                    })
500                    .$($iter)*
501            } else {
502                unreachable!()
503            }
504        })
505    };
506}
507
508#[macro_export]
514macro_rules! messages_iter {
515    ($model:expr, $configuration:expr, $($iter:tt)*) => {
516        $configuration
517            .message_ids
518            .iter()
519            .take_while(|message_id| message_id.is_valid())
520            .map(|message_id| $model.get_message(*message_id))
521            .$($iter)*
522    };
523}