1pub mod implementation {
2 #[macro_export]
3 macro_rules! node_sub_enum {
4 ($(#[$config:meta])* $vis:vis enum $wrapper:ident {
5 $($name:ident($modifier:tt $($t:tt)?)$(,)?)*
6 }) => {$crate::paste! {
7 #[derive($crate::RefCast)]
8 #[repr(transparent)]
9 $(
10 #[$config]
11 )*
12 $vis struct $wrapper($crate::graph::AnyNode);
13
14 $vis enum [<$wrapper Enum>]<'lt> {
15 $(
16 $name(&'lt $crate::ty!($modifier $($t)?)),
17 )*
18 }
19
20 $vis enum [<$wrapper EnumMut>]<'lt> {
21 $(
22 $name(&'lt mut $crate::ty!($modifier $($t)?)),
23 )*
24 }
25
26 impl $crate::graph::SubEnum for $wrapper {
27 const VARIANTS: &'static [$crate::graph::AnyNodeD] =
28 $crate::concat_slices!([$crate::graph::AnyNodeD]: $($crate::node_sub_enum_entry!($modifier $($t)?), )*);
29 }
30
31 $(impl From<$crate::ty!($modifier $($t)?)> for $wrapper {
32 #[inline]
33 fn from(value: $crate::ty!($modifier $($t)?)) -> Self {
34 Self(value.into())
35 }
36 })*
37
38 impl From<$wrapper> for $crate::graph::AnyNode {
39 #[inline]
40 fn from(value: $wrapper) -> Self {
41 value.0
42 }
43 }
44
45 impl<'a> TryFrom<&'a $crate::graph::AnyNode> for &'a $wrapper {
46 type Error = $crate::utils::Skip<std::convert::Infallible>;
47 #[inline]
48 fn try_from(value: &'a $crate::graph::AnyNode) -> Result<Self, Self::Error> {
49 if <$wrapper as $crate::graph::SubEnum>::contains(value) {
50 Ok(<$wrapper as $crate::RefCast>::ref_cast(value))
51 } else {
52 Err($crate::utils::Skip::Skipped)
53 }
54 }
55 }
56
57 impl<'a> TryFrom<&'a mut $crate::graph::AnyNode> for &'a mut $wrapper {
58 type Error = $crate::utils::Skip<std::convert::Infallible>;
59 #[inline]
60 fn try_from(value: &'a mut $crate::graph::AnyNode) -> Result<Self, Self::Error> {
61 if <$wrapper as $crate::graph::SubEnum>::contains(value) {
62 Ok(<$wrapper as $crate::RefCast>::ref_cast_mut(value))
63 } else {
64 Err($crate::utils::Skip::Skipped)
65 }
66 }
67 }
68
69 impl $crate::traits::Identifiable for $wrapper {
70 #[inline]
71 fn get_id(&self) -> $crate::graph::NodeId<Self> {
72 self.0.get_id().coerce()
73 }
74 }
75
76 impl<'lt> $crate::traits::AsEnum for &'lt $wrapper {
77 type Enum = [<$wrapper Enum>]<'lt>;
78
79 #[inline]
80 fn as_enum(self) -> Self::Enum {
81 $(
82 $crate::node_sub_enum_match_entry!(self.0 => $name, $modifier $($t)?);
83 )*
84 unreachable!()
85 }
86 }
87
88 impl<'lt> $crate::traits::AsEnum for &'lt mut $wrapper {
89 type Enum = [<$wrapper EnumMut>]<'lt>;
90
91 #[inline]
92 fn as_enum(self) -> Self::Enum {
93 $(
94 $crate::node_sub_enum_match_entry!(self.0 => mut $name, $modifier $($t)?);
95 )*
96 unreachable!()
97 }
98 }
99 }};
100 }
101
102 #[macro_export]
103 macro_rules! node_sub_enum_match_entry {
104 ($this:expr => $name:ident, $t:ident) => {
105 if let $crate::graph::AnyNode::$t(ref x) = $this {
106 return Self::Enum::$name(x);
107 }
108 };
109 ($this:expr => mut $name:ident, $t:ident) => {
110 if let $crate::graph::AnyNode::$t(ref mut x) = $this {
111 return Self::Enum::$name(x);
112 }
113 };
114 ($this:expr => $name:ident, forward $t:ty) => {
115 if <$t as $crate::graph::SubEnum>::contains(&$this) {
116 return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast(&$this))
117 }
118 };
119 ($this:expr => mut $name:ident, forward $t:ty) => {
120 if <$t as $crate::graph::SubEnum>::contains(&$this) {
121 return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast_mut(&mut $this))
122 }
123 };
124 }
125
126 #[macro_export]
127 macro_rules! ty {
128 ($t:ty) => { $t };
129 (forward $t:ty) => { $t };
130 }
131
132 #[macro_export]
133 macro_rules! node_sub_enum_entry {
134 ($t:ident) => { &[$crate::graph::AnyNodeD::$t] };
135 (forward $t:ty) => { <$t as $crate::graph::SubEnum>::VARIANTS };
136 }
137
138 macro_rules! node {
139 ($(#[$config:meta])* $vis:vis struct $name:ident {
140 $($field_vis:vis $field_name:ident: $field_type:ty,)*;
141 $($graph_vis:vis $graph_name:ident: $graph_type:ty$( as $tag:tt)?,)*
142 }) => {
143 #[cfg(feature = "serde")]
144 $(#[$config])*
145 $vis struct $name {
146 id: once_cell_serde::unsync::OnceCell<$crate::graph::NodeId<$name>>,
147 $($field_vis $field_name: $field_type,)*
148 }
149
150 #[cfg(not(feature = "serde"))]
151 $(#[$config])*
152 $vis struct $name {
153 id: std::cell::OnceCell<$crate::graph::NodeId<$name>>,
154 $($field_vis $field_name: $field_type,)*
155 }
156
157 impl $crate::node_properties::Node for $name {}
158
159 impl $name {
160 pub fn uninit($($field_name: $field_type,)*) -> $crate::Uninit<Self> {
161 $crate::Uninit::new(Self {
162 id: Default::default(),
163 $(
164 $field_name,
165 )*
166 })
167 }
168
169 pub fn into_uninit(self) -> $crate::Uninit<Self> {
170 Self::uninit($(self.$field_name, )*)
171 }
172 }
173
174 impl $crate::graph::Identifiable for $name {
175 fn get_id(&self) -> $crate::graph::NodeId<Self> {
176 self.id.get().copied().expect("Unreachable")
177 }
178
179 fn set_id(&self, value: $crate::graph::NodeId<Self>) {
180 if let Err(_) = self.id.set(value) {
181 tracing::warn!("Tried to set id twice");
182 }
183 }
184 }
185
186 $crate::with_children! [$name => {
187 $($graph_vis $graph_name: $graph_type $( as $tag)?,)*
188 }];
189 };
190 ($(#[$config:meta])* $vis:vis struct $name:ident;) => {
191 node!($(#[$config])* $vis struct $name {;});
192 }
193}
194
195 pub(crate) use node;
196}