ixa/macros/
edge_impl.rs

1/*!
2
3Macros for implementing edge types.
4
5*/
6
7#[macro_export]
8macro_rules! define_edge_type {
9    // Struct (tuple) and ZST
10    (
11        struct $name:ident $( ( $($visibility:vis $field_ty:ty),* $(,)? ) )?,
12        $entity:ident
13        $(, $($extra:tt)+),*
14    ) => {
15        #[derive(Debug, PartialEq, Clone)]
16        pub struct $name $( ($($visibility $field_ty),*) )?;
17        $crate::impl_edge_type!($name, $entity $(, $($extra)+)*);
18    };
19
20    // Struct (named fields)
21    (
22        struct $name:ident { $($visibility:vis $field_name:ident : $field_ty:ty),* $(,)? },
23        $entity:ident
24        $(, $($extra:tt)+),*
25    ) => {
26        #[derive(Copy, Debug, PartialEq)]
27        pub struct $name { $($visibility $field_name : $field_ty),* }
28        $crate::impl_edge_type!($name, $entity $(, $($extra)+)*);
29    };
30
31    // Enum
32    (
33        enum $name:ident {
34            $($variant:ident),* $(,)?
35        },
36        $entity:ident
37        $(, $($extra:tt)+),*
38    ) => {
39        #[derive(Copy, Debug, PartialEq)]
40        pub enum $name {
41            $($variant),*
42        }
43        $crate::impl_edge_type!($name, $entity $(, $($extra)+)*);
44    };
45}
46
47#[macro_export]
48macro_rules! impl_edge_type {
49    (
50        $edge_type:ident,
51        $entity:ident $(,)?
52    ) => {
53        impl $crate::network::edge::EdgeType<$entity> for $edge_type {
54            fn id() -> usize {
55                // This static must be initialized with a compile-time constant expression.
56                // We use `usize::MAX` as a sentinel to mean "uninitialized". This
57                // static variable is shared among all instances of this concrete item type.
58                static INDEX: std::sync::atomic::AtomicUsize =
59                    std::sync::atomic::AtomicUsize::new(usize::MAX);
60
61                // Fast path: already initialized.
62                let index = INDEX.load(std::sync::atomic::Ordering::Relaxed);
63                if index != usize::MAX {
64                    return index;
65                }
66
67                // Slow path: initialize it.
68                $crate::network::edge::initialize_edge_type_id::<$entity>(&INDEX)
69            }
70        }
71
72        $crate::paste::paste! {
73            $crate::ctor::declarative::ctor!{
74                #[ctor]
75                fn [<_register_edge_type_ $edge_type:snake _for_ $entity:snake>]() {
76                    $crate::network::edge::add_to_edge_type_to_registry::<$entity, $edge_type>();
77                }
78            }
79        }
80    };
81}