my_ecs/util/
macros.rs

1//! Utility macros.
2
3/// Returns type name from the given value using
4/// [`type_name`](std::any::type_name).
5///
6/// # Examples
7///
8/// ```
9/// use my_ecs::type_name;
10///
11/// fn foo() {}
12/// struct Bar;
13/// let baz = 0;
14///
15/// println!("{}", type_name!(foo));
16/// println!("{}", type_name!(Bar));
17/// println!("{}", type_name!(baz));
18/// ```
19#[macro_export]
20macro_rules! type_name {
21    ($e:expr) => {{
22        fn name<T: ?Sized>(_t: &T) -> &str {
23            let name = std::any::type_name::<T>();
24            if matches!(name.chars().next(), Some(c) if c == '&') {
25                &name[1..]
26            } else {
27                name
28            }
29        }
30        name(&$e)
31    }};
32}
33
34/// Prints out the given string regardless of build target.
35///
36/// If build target is `wasm32`, this macro calls `web_sys::console::log_1`.
37/// Otherwise [`println`] is called.
38#[macro_export]
39macro_rules! log {
40    ($($t:tt)*) => {
41        #[cfg(target_arch = "wasm32")]
42        {
43            $crate::prelude::web_util::console_log(format!($($t)*))
44        }
45        #[cfg(not(target_arch = "wasm32"))]
46        {
47            println!($($t)*)
48        }
49    }
50}
51
52/// Implements [`From`] and [`TryFrom`] for the enum.
53///
54/// # Examples
55///
56/// ```ignore
57/// # use my_ecs::util::macros::impl_from_for_enum;
58/// # use std::borrow::Cow;
59///
60/// enum MyEnum<'a, 'b: 'a, X, Y: Send + Sync, const N: usize, const M: usize> {
61///     A(&'a Cow<'b, str>),
62///     B((X, Y)),
63///     C([char; N]),
64///     D([char; M]),
65/// }
66///
67/// impl_from_for_enum!(
68///     "lifetimes" = 'a, 'b: {'a}; "bounds" = X, Y: {Send + Sync};
69///     "consts" = N: usize, M: usize;
70///     "outer" = MyEnum; "var" = A; "inner" = &'a Cow<'b, str>
71/// );
72///
73/// ```
74macro_rules! impl_from_for_enum {
75    // ()
76    (
77        "outer" = $outer:ident;
78        "var" = $var:ident;
79        "inner" = $inner:ty $(;)?
80    ) => {
81        impl From<$inner> for $outer {
82            fn from(v: $inner) -> Self { Self::$var(v) }
83        }
84        impl TryFrom<$outer> for $inner {
85            type Error = ();
86            fn try_from(v: $outer) -> Result<Self, Self::Error> {
87                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
88            }
89        }
90        impl<'_ref> TryFrom<&'_ref $outer> for &'_ref $inner {
91            type Error = ();
92            fn try_from(v: &'_ref $outer) -> Result<Self, Self::Error> {
93                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
94            }
95        }
96        impl<'_ref> TryFrom<&'_ref mut $outer> for &'_ref mut $inner {
97            type Error = ();
98            fn try_from(v: &'_ref mut $outer) -> Result<Self, Self::Error> {
99                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
100            }
101        }
102    };
103    // (consts)
104    (
105        "consts" = $( $c_id:ident : $c_ty:ty ),*;
106        "outer" = $outer:ident;
107        "var" = $var:ident;
108        "inner" = $inner:ty $(;)?
109    ) => {
110        // inner -> outer
111        impl<
112            $( const $c_id : $c_ty ),*
113        > From<$inner> for $outer<
114            $( $c_id ),*
115        >
116        { fn from(v: $inner) -> Self { Self::$var(v) } }
117        // outer -> inner
118        impl<
119            $( const $c_id : $c_ty ),*
120        > TryFrom<$outer<
121            $( $c_id ),*
122        >> for $inner
123        {
124            type Error = ();
125            fn try_from(v: $outer<
126                $( $c_id ),*
127            >) -> Result<Self, Self::Error> {
128                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
129            }
130        }
131        // & outer -> & inner
132        impl<
133            '_ref,
134            $( const $c_id : $c_ty ),*
135        > TryFrom<&'_ref $outer<
136            $( $c_id ),*
137        >> for &'_ref $inner
138        {
139            type Error = ();
140            fn try_from(v: &'_ref $outer<
141                $( $c_id ),*
142            >) -> Result<Self, Self::Error> {
143                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
144            }
145        }
146        // &mut outer -> &mut inner
147        impl<
148            '_ref,
149            $( const $c_id : $c_ty ),*
150        > TryFrom<&'_ref mut $outer<
151            $( $c_id ),*
152        >> for &'_ref mut $inner
153        {
154            type Error = ();
155            fn try_from(v: &'_ref mut $outer<
156                $( $c_id ),*
157            >) -> Result<Self, Self::Error> {
158                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
159            }
160        }
161    };
162    // (bounds, ..)
163    (
164        "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),*;
165        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
166        "outer" = $outer:ident;
167        "var" = $var:ident;
168        "inner" = $inner:ty $(;)?
169    ) => {
170        // inner -> outer
171        impl<
172            $( $b_id $( : $($b_sup)* )? ),*
173            $(, $( const $c_id : $c_ty ),* )?
174        > From<$inner> for $outer<
175            $( $b_id ),*
176            $(, $( $c_id ),* )?
177        >
178        { fn from(v: $inner) -> Self { Self::$var(v) } }
179        // outer -> inner
180        impl<
181            $( $b_id $( : $($b_sup)* )? ),*
182            $(, $( const $c_id : $c_ty ),* )?
183        > TryFrom<$outer<
184            $( $b_id ),*
185            $(, $( $c_id ),* )?
186        >> for $inner
187        {
188            type Error = ();
189            fn try_from(v: $outer<
190                $( $b_id ),*
191                $(, $( $c_id ),* )?
192            >) -> Result<Self, Self::Error> {
193                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
194            }
195        }
196        // & outer -> & inner
197        impl<
198            '_ref,
199            $( $b_id $( : $($b_sup)* )? ),*
200            $(, $( const $c_id : $c_ty ),* )?
201        > TryFrom<&'_ref $outer<
202            $( $b_id ),*
203            $(, $( $c_id ),* )?
204        >> for &'_ref $inner
205        {
206            type Error = ();
207            fn try_from(v: &'_ref $outer<
208                $( $b_id ),*
209                $(, $( $c_id ),* )?
210            >) -> Result<Self, Self::Error> {
211                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
212            }
213        }
214        // &mut outer -> &mut inner
215        impl<
216            '_ref,
217            $( $b_id $( : $($b_sup)* )? ),*
218            $(, $( const $c_id : $c_ty ),* )?
219        > TryFrom<&'_ref mut $outer<
220            $( $b_id ),*
221            $(, $( $c_id ),* )?
222        >> for &'_ref mut $inner
223        {
224            type Error = ();
225            fn try_from(v: &'_ref mut $outer<
226                $( $b_id ),*
227                $(, $( $c_id ),* )?
228            >) -> Result<Self, Self::Error> {
229                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
230            }
231        }
232    };
233    // (lifetimes, ..)
234    (
235        "lifetimes" = $( $lt:lifetime $( : { $($lt_sup:tt)* } )? ),*;
236        $( "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),* ; )?
237        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
238        "outer" = $outer:ident;
239        "var" = $var:ident;
240        "inner" = $inner:ty $(;)?
241    ) => {
242        // inner -> outer
243        impl<
244            $( $lt $( : $($lt_sup)* )? ),*
245            $(, $( $b_id $( : $($b_sup)* )? ),* )?
246            $(, $( const $c_id : $c_ty ),* )?
247        > From<$inner> for $outer<
248            $($lt),*
249            $(, $( $b_id ),* )?
250            $(, $( $c_id ),* )?
251        >
252        { fn from(v: $inner) -> Self { Self::$var(v) } }
253        // outer -> inner
254        impl<
255            $( $lt $( : $($lt_sup)* )? ),*
256            $(, $( $b_id $( : $($b_sup)* )? ),* )?
257            $(, $( const $c_id : $c_ty ),* )?
258        > TryFrom<$outer<
259            $($lt),*
260            $(, $( $b_id ),* )?
261            $(, $( $c_id ),* )?
262        >> for $inner
263        {
264            type Error = ();
265            fn try_from(v: $outer<
266                $($lt),*
267                $(, $( $b_id ),* )?
268                $(, $( $c_id ),* )?
269            >) -> Result<Self, Self::Error> {
270                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
271            }
272        }
273        // & outer -> & inner
274        impl<
275            '_ref,
276            $( $lt $( : $($lt_sup)* )? ),*
277            $(, $( $b_id $( : $($b_sup)* )? ),* )?
278            $(, $( const $c_id : $c_ty ),* )?
279        > TryFrom<&'_ref $outer<
280            $($lt),*
281            $(, $( $b_id ),* )?
282            $(, $( $c_id ),* )?
283        >> for &'_ref $inner
284        {
285            type Error = ();
286            fn try_from(v: &'_ref $outer<
287                $($lt),*
288                $(, $( $b_id ),* )?
289                $(, $( $c_id ),* )?
290            >) -> Result<Self, Self::Error> {
291                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
292            }
293        }
294        // &mut outer -> &mut inner
295        impl<
296            '_ref,
297            $( $lt $( : $($lt_sup)* )? ),*
298            $(, $( $b_id $( : $($b_sup)* )? ),* )?
299            $(, $( const $c_id : $c_ty ),* )?
300        > TryFrom<&'_ref mut $outer<
301            $($lt),*
302            $(, $( $b_id ),* )?
303            $(, $( $c_id ),* )?
304        >> for &'_ref mut $inner
305        {
306            type Error = ();
307            fn try_from(v: &'_ref mut $outer<
308                $($lt),*
309                $(, $( $b_id ),* )?
310                $(, $( $c_id ),* )?
311            >) -> Result<Self, Self::Error> {
312                match v { $outer::$var(iv) => Ok(iv), _ => Err(()) }
313            }
314        }
315    };
316}
317pub(crate) use impl_from_for_enum;
318
319macro_rules! impl_into_iterator_body_for_parallel {
320    ($item:ty, $to:ty) => {
321        type Item = $item;
322        type IntoIter = $to;
323
324        #[inline]
325        fn into_iter(self) -> Self::IntoIter {
326            self.into_seq()
327        }
328    };
329}
330pub(crate) use impl_into_iterator_body_for_parallel;
331
332// bound matching pattern.
333macro_rules! impl_into_iterator_for_parallel {
334    // ()
335    (
336        "for" = $for:ident;
337        "to" = $to:ty;
338        "item" = $item:ty $(;)?
339    ) => {
340        impl IntoIterator for $for
341        {
342            $crate::util::macros::impl_into_iterator_body_for_parallel!($item, $to);
343        }
344    };
345    // (consts)
346    (
347        "consts" = $( $c_id:ident : $c_ty:ty ),*;
348        "for" = $for:ident;
349        "to" = $to:ty;
350        "item" = $item:ty $(;)?
351    ) => {
352        impl<
353            $( const $c_id : $c_ty ),*
354        > IntoIterator for $for<
355            $( $c_id ),*
356        >
357        {
358            $crate::util::macros::impl_into_iterator_body_for_parallel!($item, $to);
359        }
360    };
361    // (bounds, ..)
362    (
363        "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),*;
364        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
365        "for" = $for:ident;
366        "to" = $to:ty;
367        "item" = $item:ty $(;)?
368    ) => {
369        impl<
370            $( $b_id $( : $($b_sup)* )? ),*
371            $(, $( const $c_id : $c_ty ),* )?
372        > IntoIterator for $for<
373            $( $b_id ),*
374            $(, $( $c_id ),* )?
375        >
376        {
377            $crate::util::macros::impl_into_iterator_body_for_parallel!($item, $to);
378        }
379    };
380    // (lifetimes, ..)
381    (
382        "lifetimes" = $( $lt:lifetime ),*;
383        $( "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),* ; )?
384        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
385        "for" = $for:ident;
386        "to" = $to:ty;
387        "item" = $item:ty $(;)?
388    ) => {
389        impl<
390            $($lt),*
391            $(, $( $b_id $( : $($b_sup)* )? ),* )?
392            $(, $( const $c_id : $c_ty ),* )?
393        > IntoIterator for $for<
394            $($lt),*
395            $(, $( $b_id ),* )?
396            $(, $( $c_id ),* )?
397        >
398        {
399            $crate::util::macros::impl_into_iterator_body_for_parallel!($item, $to);
400        }
401    };
402}
403pub(crate) use impl_into_iterator_for_parallel;
404
405macro_rules! impl_parallel_iterator_body {
406    ($item:ty) => {
407        type Item = $item;
408
409        #[inline]
410        fn drive_unindexed<C>(self, consumer: C) -> C::Result
411        where
412            C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
413        {
414            rayon::iter::plumbing::bridge(self, consumer)
415        }
416    };
417}
418pub(crate) use impl_parallel_iterator_body;
419
420macro_rules! impl_indexed_parallel_iterator_body {
421    () => {
422        #[inline]
423        fn len(&self) -> usize {
424            Self::len(self)
425        }
426
427        #[inline]
428        fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
429            rayon::iter::plumbing::bridge(self, consumer)
430        }
431
432        #[inline]
433        fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
434            self,
435            callback: CB,
436        ) -> CB::Output {
437            callback.callback(self)
438        }
439    };
440}
441pub(crate) use impl_indexed_parallel_iterator_body;
442
443// bound matching pattern.
444macro_rules! impl_parallel_iterator {
445    // ()
446    (
447        "for" = $for:ident;
448        "item" = $item:ty $(;)?
449    ) => {
450        impl rayon::iter::ParallelIterator for $for {
451            $crate::util::macros::impl_parallel_iterator_body!($item);
452        }
453
454        impl rayon::iter::IndexedParallelIterator for $for
455        {
456            $crate::util::macros::impl_indexed_parallel_iterator_body!();
457        }
458    };
459    // (consts)
460    (
461        "consts" = $( $c_id:ident : $c_ty:ty ),*;
462        "for" = $for:ident;
463        "item" = $item:ty $(;)?
464    ) => {
465        impl<
466            $( const $c_id : $c_ty ),*
467        > rayon::iter::ParallelIterator for $for<
468            $( $c_id ),*
469        > {
470            $crate::util::macros::impl_parallel_iterator_body!($item);
471        }
472
473        impl<
474            $( $b_id $( : $($b_sup)* )? ),*
475        > rayon::iter::IndexedParallelIterator for $for<
476            $( $c_id ),*
477        >
478        {
479            $crate::util::macros::impl_indexed_parallel_iterator_body!();
480        }
481    };
482    // (bounds, ..)
483    (
484        "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),*;
485        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
486        "for" = $for:ident;
487        "item" = $item:ty $(;)?
488    ) => {
489        impl<
490            $( $b_id $( : $($b_sup)* )? ),*
491            $(, $( const $c_id : $c_ty ),* )?
492        > rayon::iter::ParallelIterator for $for<
493            $( $b_id ),*
494            $(, $( $c_id ),* )?
495        > {
496            $crate::util::macros::impl_parallel_iterator_body!($item);
497        }
498
499        impl<
500            $( $b_id $( : $($b_sup)* )? ),*
501            $(, $( const $c_id : $c_ty ),* )?
502        > rayon::iter::IndexedParallelIterator for $for<
503            $( $b_id ),*
504            $(, $( $c_id ),* )?
505        >
506        {
507            $crate::util::macros::impl_indexed_parallel_iterator_body!();
508        }
509    };
510    // (lifetimes, ..)
511    (
512        "lifetimes" = $( $lt:lifetime ),*;
513        $( "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),* ; )?
514        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
515        "for" = $for:ident;
516        "item" = $item:ty $(;)?
517    ) => {
518        impl<
519            $($lt),*
520            $(, $( $b_id $( : $($b_sup)* )? ),* )?
521            $(, $( const $c_id : $c_ty ),* )?
522        > rayon::iter::ParallelIterator for $for<
523            $($lt),*
524            $(, $( $b_id ),* )?
525            $(, $( $c_id ),* )?
526        > {
527            $crate::util::macros::impl_parallel_iterator_body!($item);
528        }
529
530        impl<
531            $($lt),*
532            $(, $( $b_id $( : $($b_sup)* )? ),* )?
533            $(, $( const $c_id : $c_ty ),* )?
534        > rayon::iter::IndexedParallelIterator for $for<
535            $($lt),*
536            $(, $( $b_id ),* )?
537            $(, $( $c_id ),* )?
538        >
539        {
540            $crate::util::macros::impl_indexed_parallel_iterator_body!();
541        }
542    };
543}
544pub(crate) use impl_parallel_iterator;
545
546macro_rules! impl_unindexed_producer_body {
547    ($item:ty) => {
548        type Item = $item;
549
550        #[inline]
551        fn split(self) -> (Self, Option<Self>) {
552            let mid = Self::len(&self) / 2;
553            let (l, r) = self.split_at(mid);
554            (l, (!r.is_empty()).then_some(r))
555        }
556
557        #[inline]
558        fn fold_with<F>(self, folder: F) -> F
559        where
560            F: rayon::iter::plumbing::Folder<Self::Item>,
561        {
562            folder.consume_iter(self.into_seq())
563        }
564    };
565}
566pub(crate) use impl_unindexed_producer_body;
567
568// bound matching pattern.
569macro_rules! impl_unindexed_producer {
570    // ()
571    (
572        "for" = $for:ident;
573        "item" = $item:ty $(;)?
574    ) => {
575        impl rayon::iter::plumbing::UnindexedProducer for $for
576        {
577            $crate::util::macros::impl_unindexed_producer_body!($item);
578        }
579    };
580    // (consts)
581    (
582        "consts" = $( $c_id:ident : $c_ty:ty ),*;
583        "for" = $for:ident;
584        "item" = $item:ty $(;)?
585    ) => {
586        impl<
587            $( const $c_id : $c_ty ),*
588        > rayon::iter::plumbing::UnindexedProducer for $for<
589            $( $c_id ),*
590        >
591        {
592            $crate::util::macros::impl_unindexed_producer_body!($item);
593        }
594    };
595    // (bounds, ..)
596    (
597        "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),*;
598        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
599        "for" = $for:ident;
600        "item" = $item:ty $(;)?
601    ) => {
602        impl<
603            $( $b_id $( : $($b_sup)* )? ),*
604            $(, $( const $c_id : $c_ty ),* )?
605        > rayon::iter::plumbing::UnindexedProducer for $for<
606            $( $b_id ),*
607            $(, $( $c_id ),* )?
608        >
609        {
610            $crate::util::macros::impl_unindexed_producer_body!($item);
611        }
612    };
613    // (lifetimes, ..)
614    (
615        "lifetimes" = $( $lt:lifetime ),*;
616        $( "bounds" = $( $b_id:ident $( : { $($b_sup:tt)* } )? ),* ; )?
617        $( "consts" = $( $c_id:ident : $c_ty:ty ),* ; )?
618        "for" = $for:ident;
619        "item" = $item:ty $(;)?
620    ) => {
621        impl<
622            $($lt),*
623            $(, $( $b_id $( : $($b_sup)* )? ),* )?
624            $(, $( const $c_id : $c_ty ),* )?
625        > rayon::iter::plumbing::UnindexedProducer for $for<
626            $($lt),*
627            $(, $( $b_id ),* )?
628            $(, $( $c_id ),* )?
629        >
630        {
631            $crate::util::macros::impl_unindexed_producer_body!($item);
632        }
633    };
634}
635pub(crate) use impl_unindexed_producer;
636
637macro_rules! debug_format {
638    ($($t:tt)*) => {{
639        #[cfg(debug_assertions)]
640        {
641            format!($($t)*)
642        }
643        #[cfg(not(debug_assertions))]
644        {
645            String::new()
646        }
647    }};
648}
649pub(crate) use debug_format;