1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
/// Defines a resource (or channel endpoint) which can be stored on the bus, and how it is taken or cloned. /// /// Lifeline provides helper macros which can implement the Clone or Take operations: /// [impl_storage_take!(Struct)](./macro.impl_storage_take.html), and [impl_storage_clone!(Struct)](./macro.impl_storage_clone.html) /// /// ## Resource Example /// ``` /// use lifeline::impl_storage_clone; /// /// #[derive(Debug, Clone)] /// struct ExampleConfiguration { /// value: bool /// } /// /// impl_storage_clone!(ExampleConfiguration); /// ``` /// /// ## Channel Example /// Lifeline also provides [impl_channel_take!(Struct\<T\>)](./macro.impl_channel_take.html) and [impl_channel_clone!(Struct\<T\>)](./macro.impl_channel_take.html), /// which configure the generic bounds required for a channel implementation: /// ``` /// use lifeline::impl_channel_take; /// use std::marker::PhantomData; /// /// #[derive(Debug)] /// struct ExampleSender<T> { /// _t: PhantomData<T> /// } /// /// impl_channel_take!(ExampleSender<T>); /// ``` pub trait Storage: Sized + 'static { /// If Self::Tx implements clone, clone it. Otherwise use Option::take fn take_or_clone(res: &mut Option<Self>) -> Option<Self>; /// Helper which clones the provided option, requiring that Self: Clone fn clone_slot(res: &mut Option<Self>) -> Option<Self> where Self: Clone, { res.as_ref().map(|t| t.clone()) } /// Helper which takes the provided option, returning None if it's already been taken fn take_slot(res: &mut Option<Self>) -> Option<Self> { res.take() } } /// Specifies that this resource is taken, and is !Clone. /// ## Example: /// ``` /// use lifeline::impl_storage_take; /// /// struct ExampleResource {} /// /// impl_storage_take!(ExampleResource); /// ``` #[macro_export] macro_rules! impl_storage_take { ( $name:ty ) => { impl $crate::Storage for $name { fn take_or_clone(res: &mut Option<Self>) -> Option<Self> { Self::take_slot(res) } } }; } /// Specifies that this channel endpoint (Sender or Receiver) is taken. Provides a generic type T with the bounds required for the implementation. /// ## Example: /// ``` /// use std::marker::PhantomData; /// use lifeline::impl_channel_take; /// /// struct ExampleReceiver<T> { /// _t: PhantomData<T> /// } /// /// impl_channel_take!(ExampleReceiver<T>); /// ``` #[macro_export] macro_rules! impl_channel_take { ( $name:ty ) => { impl<T: Send + 'static> $crate::Storage for $name { fn take_or_clone(res: &mut Option<Self>) -> Option<Self> { Self::take_slot(res) } } }; } /// Specifies that this resource is cloned. /// ## Example: /// ``` /// use lifeline::impl_storage_clone; /// /// #[derive(Clone)] /// struct ExampleResource {} /// /// impl_storage_clone!(ExampleResource); /// ``` #[macro_export] macro_rules! impl_storage_clone { ( $name:ty ) => { impl $crate::Storage for $name { fn take_or_clone(res: &mut Option<Self>) -> Option<Self> { Self::clone_slot(res) } } }; } /// Specifies that this channel endpoint (Sender or Receiver) is clonable. Provides a generic type T with the bounds required for the implementation. /// ## Example: /// ``` /// use std::marker::PhantomData; /// use lifeline::impl_channel_clone; /// /// struct ExampleReceiver<T> { /// _t: PhantomData<T> /// } /// /// impl<T> Clone for ExampleReceiver<T> { /// fn clone(&self) -> Self { /// Self { _t: PhantomData } /// } /// } /// /// impl_channel_clone!(ExampleReceiver<T>); /// ``` #[macro_export] macro_rules! impl_channel_clone { ( $name:ty ) => { impl<T: Send + 'static> $crate::Storage for $name { fn take_or_clone(res: &mut Option<Self>) -> Option<Self> { Self::clone_slot(res) } } }; }