lifeline/dyn_bus/
macros.rs

1/// Defines a lifeline bus: it's struct, `Bus` impl, and `DynBus` impl.
2///
3/// ## Examples
4/// ```
5/// use lifeline::prelude::*;
6/// use tokio::sync::mpsc;
7///
8/// lifeline_bus!(pub struct ExampleBus);
9///
10/// // carry ExampleMessage on the bus, using a tokio mpsc sender.
11/// #[derive(Debug)]
12/// pub struct ExampleMessage {}
13/// impl Message<ExampleBus> for ExampleMessage {
14///     type Channel = mpsc::Sender<Self>;
15/// }
16/// ```
17/// You can also define private structs:
18/// ```
19/// use lifeline::prelude::*;
20///
21/// lifeline_bus!(struct PrivateExampleBus);
22/// ```
23/// You can also define generics (which are constrained to Debug):
24/// ```
25/// use lifeline::prelude::*;
26/// lifeline_bus!(pub struct ExampleBus<T>);
27/// ```
28/// ## Prelude, auto-imports, and rust-analyzer
29/// Unfortunately, rust-analyzer doesn't handle auto-imports for structures defined in macros.
30/// There is an ergonomic solution: define a prelude module in your crate root, and `pub use` all your bus structs.
31/// If you want, you can `pub use lifeline::prelude::*` as well.
32#[macro_export]
33macro_rules! lifeline_bus (
34    (struct $name:ident $(< $( $gen:ident ),+ >)? ) => {
35        lifeline_bus! { () struct $name $(< $( $gen ),+ >)? }
36    };
37
38    (pub struct $name:ident $(< $( $gen:ident ),+ >)* ) => {
39        lifeline_bus! { (pub) struct $name $(< $( $gen ),+ >)* }
40    };
41
42    (($($vis:tt)*) struct $name:ident $(< $( $gen:ident ),+ >)? ) => {
43        #[derive(Debug)]
44        #[allow(non_snake_case)]
45        $($vis)* struct $name $(< $( $gen: std::fmt::Debug ),+ >)? {
46            storage: $crate::dyn_bus::DynBusStorage<Self>,
47            $(
48                $( $gen: std::marker::PhantomData<$gen> ),+
49            )?
50        }
51
52        impl$(< $( $gen: std::fmt::Debug ),+ >)? std::default::Default for $name $(< $( $gen ),+ >)? {
53            fn default() -> Self {
54                Self {
55                    storage: $crate::dyn_bus::DynBusStorage::default(),
56                    $(
57                        $( $gen: std::marker::PhantomData::<$gen> ),+
58                    )?
59                }
60            }
61        }
62
63        impl$(< $( $gen: std::fmt::Debug ),+ >)? $crate::dyn_bus::DynBus for $name$(< $( $gen ),+ >)? {
64            fn store_rx<Msg>(&self, rx: <Msg::Channel as $crate::Channel>::Rx) -> Result<(), $crate::error::AlreadyLinkedError>
65                where Msg: $crate::Message<Self> + 'static
66            {
67                self.storage().store_channel::<Msg, Msg::Channel, Self>(Some(rx), None)
68            }
69
70            fn store_tx<Msg>(&self, tx: <Msg::Channel as $crate::Channel>::Tx) -> Result<(), $crate::error::AlreadyLinkedError>
71                where Msg: $crate::Message<Self> + 'static
72            {
73                self.storage().store_channel::<Msg, Msg::Channel, Self>(None, Some(tx))
74            }
75
76            fn store_channel<Msg>(
77                &self,
78                rx: <Msg::Channel as $crate::Channel>::Rx,
79                tx: <Msg::Channel as $crate::Channel>::Tx
80            ) -> Result<(), $crate::error::AlreadyLinkedError>
81                where Msg: $crate::Message<Self> + 'static
82            {
83                self.storage().store_channel::<Msg, Msg::Channel, Self>(Some(rx), Some(tx))
84            }
85
86            fn store_resource<R: $crate::Resource<Self>>(&self, resource: R) {
87                self.storage.store_resource::<R, Self>(resource)
88            }
89
90            fn storage(&self) -> &$crate::dyn_bus::DynBusStorage<Self> {
91                &self.storage
92            }
93        }
94    }
95);