ixa/
plugin_context.rs

1use crate::{
2    context::{Context, ContextBase},
3    ContextGlobalPropertiesExt, ContextNetworkExt, ContextPeopleExt, ContextRandomExt,
4    ContextReportExt,
5};
6
7/// A supertrait that exposes useful methods from `Context`
8/// for plugins implementing Context extensions.
9///
10/// Usage:
11// This example triggers the error "#[ctor]/#[dtor] is not supported
12// on the current target," which appears to be spurious, so we
13// ignore it.
14/// ```ignore
15/// use ixa::prelude_for_plugins::*;
16/// define_data_plugin!(MyData, bool, false);
17/// pub trait MyPlugin: PluginContext {
18///     fn set_my_data(&mut self) {
19///         let my_data = self.get_data_container_mut(MyData);
20///         *my_data = true;
21///     }
22/// }
23pub trait PluginContext:
24    ContextBase
25    + ContextPeopleExt
26    + ContextRandomExt
27    + ContextReportExt
28    + ContextNetworkExt
29    + ContextGlobalPropertiesExt
30{
31}
32
33impl PluginContext for Context {}
34
35// Tests for the PluginContext trait, including:
36// - Making sure all the methods work identically to Context
37// - Defining a trait extension that uses it compiles correctly
38// - External functions can use impl PluginContext if necessary
39#[cfg(test)]
40mod test_plugin_context {
41    use crate::prelude_for_plugins::*;
42    #[derive(Copy, Clone, IxaEvent)]
43    struct MyEvent {
44        pub data: usize,
45    }
46
47    define_data_plugin!(MyData, i32, 0);
48
49    fn do_stuff_with_context(context: &mut impl PluginContext) {
50        context.add_plan(1.0, |context| {
51            let data = context.get_data(MyData);
52            assert_eq!(*data, 42);
53        });
54    }
55
56    trait MyDataExt: PluginContext {
57        fn all_methods(&mut self) {
58            assert_eq!(self.get_current_time(), 0.0);
59        }
60        fn all_methods_mut(&mut self) {
61            self.setup();
62            self.subscribe_to_event(|_: &mut Context, event: MyEvent| {
63                assert_eq!(event.data, 42);
64            });
65            self.emit_event(MyEvent { data: 42 });
66            self.add_plan_with_phase(
67                1.0,
68                |context| {
69                    let data = context.get_data(MyData);
70                    assert_eq!(*data, 42);
71                    context.set_my_data(100);
72                },
73                crate::ExecutionPhase::Last,
74            );
75            self.add_plan(1.0, |context| {
76                assert_eq!(context.get_my_data(), 42);
77            });
78            self.add_periodic_plan_with_phase(
79                1.0,
80                |context| {
81                    println!(
82                        "Periodic plan at time {} with data {}",
83                        context.get_current_time(),
84                        context.get_my_data()
85                    );
86                },
87                crate::ExecutionPhase::Normal,
88            );
89            self.queue_callback(|context| {
90                let data = context.get_data(MyData);
91                assert_eq!(*data, 42);
92            });
93        }
94        fn setup(&mut self) {
95            let data = self.get_data_mut(MyData);
96            *data = 42;
97            do_stuff_with_context(self);
98        }
99        fn get_my_data(&self) -> i32 {
100            *self.get_data(MyData)
101        }
102        fn set_my_data(&mut self, value: i32) {
103            let data = self.get_data_mut(MyData);
104            *data = value;
105        }
106        fn test_external_function(&mut self) {
107            self.setup();
108            do_stuff_with_context(self);
109        }
110    }
111    impl MyDataExt for Context {}
112
113    #[test]
114    fn test_all_methods() {
115        let mut context = Context::new();
116        context.all_methods_mut();
117        context.all_methods();
118        context.execute();
119    }
120
121    #[test]
122    fn test_plugin_context() {
123        let mut context = Context::new();
124        context.setup();
125        assert_eq!(context.get_my_data(), 42);
126    }
127
128    #[test]
129    fn test_external_function() {
130        let mut context = Context::new();
131        context.test_external_function();
132        assert_eq!(context.get_my_data(), 42);
133    }
134}