dungeon_cell/marker_traits/
bound.rs

1use core::fmt::Debug;
2use core::panic::{RefUnwindSafe, UnwindSafe};
3
4use super::sealed::Sealed;
5use crate::bound::bounds;
6
7/// Marker only implemented for [`Bound`][crate::bound::Bound].
8///
9/// This trait is [sealed](https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed)
10/// and cannot be implemented by external types.
11pub trait IsBound:
12    Sealed
13    + Sized
14    + Copy
15    + Clone
16    + Sync
17    + Send
18    + Unpin
19    + RefUnwindSafe
20    + UnwindSafe
21    + 'static
22{
23    /// Flag that is `true` when the bound includes [`Send`][std::marker::Send].
24    const BOUND_BY_SEND: bool = false;
25
26    /// Flag that is `true` when the bound includes [`Sync`][std::marker::Sync].
27    const BOUND_BY_SYNC: bool = false;
28
29    /// Flag that is `true` when the bound includes [`Copy`][std::marker::Copy].
30    const BOUND_BY_COPY: bool = false;
31
32    /// Flag that is `true` when the bound includes [`Unpin`][std::marker::Unpin].
33    const BOUND_BY_UNPIN: bool = false;
34
35    /// Flag that is `true` when the bound includes [`Clone`][std::clone::Clone].
36    const BOUND_BY_CLONE: bool = false;
37
38    /// Flag that is `true` when the bound includes [`Debug`][std::fmt::Debug].
39    const BOUND_BY_DEBUG: bool = false;
40
41    /// Marker type that will implement [`Send`][std::marker::Send] if the bound includes it.
42    ///
43    /// Because `Send` is an auto trait, storing this marker will automatically disable
44    /// implementing `Send` when the bound doesn't have it.
45    type SendMarker: Sized
46        + Sync
47        + Copy
48        + Clone
49        + Debug
50        + Unpin
51        + RefUnwindSafe
52        + UnwindSafe
53        + 'static;
54
55    /// Marker type that will implement [`Sync`][std::marker::Sync] if the bound includes it.
56    ///
57    /// Because `Sync` is an auto trait, storing this marker will automatically disable
58    /// implementing `sync` when the bound doesn't have it.
59    type SyncMarker: Sized
60        + Send
61        + Copy
62        + Clone
63        + Debug
64        + Unpin
65        + RefUnwindSafe
66        + UnwindSafe
67        + 'static;
68
69    /// Marker type that will implement [`Copy`][std::marker::Copy] if the bound includes it.
70    type CopyMarker: Sized
71        + Send
72        + Sync
73        + Clone
74        + Debug
75        + Unpin
76        + RefUnwindSafe
77        + UnwindSafe
78        + 'static;
79
80    /// Marker type that will implement [`Clone`][std::clone::Clone] if the bound includes it.
81    type CloneMarker: Sized
82        + Send
83        + Sync
84        + Debug
85        + Unpin
86        + RefUnwindSafe
87        + UnwindSafe
88        + 'static;
89
90    /// Marker type that will implement [`Unpin`][std::marker::Unpin] if the bound includes it.
91    ///
92    /// Because `Unpin` is an auto trait, storing this marker will automatically disable
93    /// implementing `Unpin` when the bound doesn't have it.
94    type UnpinMarker: Sized
95        + Send
96        + Sync
97        + Copy
98        + Clone
99        + Debug
100        + RefUnwindSafe
101        + UnwindSafe
102        + 'static;
103
104    /// Marker type that will implement [`Debug`][std::fmt::Debug] if the bound includes it.
105    type DebugMarker: Sized
106        + Send
107        + Sync
108        + Copy
109        + Clone
110        + Unpin
111        + RefUnwindSafe
112        + UnwindSafe
113        + 'static;
114}
115
116mod sealed {
117    use super::*;
118    use crate::bound::{traits, Bound};
119    use core::marker::{PhantomData, PhantomPinned};
120
121    #[derive(Copy, Clone, Debug)]
122    pub struct SendMarker;
123
124    #[derive(Copy, Clone, Debug)]
125    pub struct NotSendMarker(PhantomData<*const ()>);
126
127    // SAFETY: This is safe because this type is only used as a marker.
128    // There are no issues accessing it in a Sync manner.
129    unsafe impl Sync for NotSendMarker {}
130
131    #[derive(Copy, Clone, Debug)]
132    pub struct SyncMarker;
133
134    #[derive(Copy, Clone, Debug)]
135    pub struct NotSyncMarker(PhantomData<*const ()>);
136
137    // SAFETY: This is safe because this type is only used as a marker.
138    // There are no issues accessing it in a Send manner.
139    unsafe impl Send for NotSyncMarker {}
140
141    #[derive(Copy, Clone, Debug)]
142    pub struct CopyMarker;
143
144    #[derive(Debug, Clone)]
145    pub struct NotCopyMarker;
146
147    #[derive(Copy, Clone, Debug)]
148    pub struct UnpinMarker;
149
150    #[derive(Copy, Clone, Debug)]
151    pub struct NotUnpinMarker(PhantomPinned);
152
153    #[derive(Clone, Debug)]
154    pub struct CloneMarker;
155
156    #[derive(Debug)]
157    pub struct NotCloneMarker;
158
159    #[derive(Clone, Copy, Debug)]
160    pub struct DebugMarker;
161
162    #[derive(Clone, Copy)]
163    pub struct NotDebugMarker;
164
165    impl Sealed for bounds::Empty {}
166    impl IsBound for bounds::Empty {
167        type SendMarker = NotSendMarker;
168
169        type SyncMarker = NotSyncMarker;
170
171        type CopyMarker = NotCopyMarker;
172
173        type UnpinMarker = NotUnpinMarker;
174
175        type CloneMarker = NotCloneMarker;
176
177        type DebugMarker = NotDebugMarker;
178    }
179
180    macro_rules! bound_impl {
181        (@send, __) => {
182            type SendMarker = NotSendMarker;
183        };
184        (@sync, __) => {
185            type SyncMarker = NotSyncMarker;
186        };
187        (@copy, __) => {
188            type CopyMarker = NotCopyMarker;
189        };
190        (@clone, __) => {
191            type CloneMarker = NotCloneMarker;
192        };
193        (@unpin, __) => {
194            type UnpinMarker = NotUnpinMarker;
195        };
196        (@debug, __) => {
197            type DebugMarker = NotDebugMarker;
198        };
199        (@send, Send) => {
200            const BOUND_BY_SEND: bool = true;
201            type SendMarker = SendMarker;
202        };
203        (@sync, Sync) => {
204            const BOUND_BY_SYNC: bool = true;
205            type SyncMarker = SyncMarker;
206        };
207        (@copy, Copy) => {
208            const BOUND_BY_COPY: bool = true;
209            type CopyMarker = CopyMarker;
210        };
211        (@clone, Clone) => {
212            const BOUND_BY_CLONE: bool = true;
213            type CloneMarker = CloneMarker;
214        };
215        (@unpin, Unpin) => {
216            const BOUND_BY_UNPIN: bool = true;
217            type UnpinMarker = UnpinMarker;
218        };
219        (@debug, Debug) => {
220            const BOUND_BY_DEBUG: bool = true;
221            type DebugMarker = DebugMarker;
222        };
223    }
224
225    macro_rules! powerset {
226        (
227            @helper
228            $empty:ident
229            []
230            [$($bounds:ident),*]
231        ) => {
232        };
233        (
234            @helper
235            $empty:ident
236            [$trait:ident $(, $traits:ident)*]
237            [$send:ident, $sync:ident, $copy:ident, $clone:ident, $unpin:ident, $debug:ident]
238        ) => {
239            impl Sealed for Bound<
240              traits::$send, traits::$sync, traits::$copy, traits::$clone, traits::$unpin, traits::$debug
241            > {}
242
243            impl IsBound for Bound<
244              traits::$send, traits::$sync, traits::$copy, traits::$clone, traits::$unpin, traits::$debug
245            > {
246                bound_impl!(@clone, $clone);
247                bound_impl!(@debug, $debug);
248                bound_impl!(@send, $send);
249                bound_impl!(@sync, $sync);
250                bound_impl!(@copy, $copy);
251                bound_impl!(@unpin, $unpin);
252            }
253        };
254        // @helper [traitB, traitD] [(boundA, false), (boundB, true), (boundC, false), (boundD, true)] bound => trait, ...
255        (
256            @helper
257            $empty:ident
258            [$($trait:ident),*]
259            [$($bound:ident),*]
260            $next_trait:ident
261            $(, $traits:ident)*
262        ) => {
263            powerset!(@helper $empty [$($trait),*] [$($bound,)* $empty] $($traits),*);
264            powerset!(@helper $empty [$($trait,)* $next_trait] [$($bound,)* $next_trait] $($traits),*);
265        };
266        ($empty:ident, $($trait:ident),*) => {
267            powerset!(@helper $empty [] [] $($trait),*);
268        };
269    }
270
271    powerset![__, Send, Sync, Copy, Clone, Unpin, Debug];
272}