1#![macro_use]
2
3#[macro_export]
5macro_rules! godot_print {
6 ($($args:tt)*) => ({
7 $crate::log::print(::std::format_args!($($args)*));
8 });
9}
10
11#[macro_export]
16macro_rules! godot_dbg {
17 () => {
18 $crate::godot_print!("[{}:{}]", ::std::file!(), ::std::line!());
19 };
20 ($val:expr) => {
21 match $val {
24 tmp => {
25 $crate::godot_print!("[{}:{}] {} = {:#?}",
26 ::std::file!(), ::std::line!(), ::std::stringify!($val), &tmp);
27 tmp
28 }
29 }
30 };
31 ($val:expr,) => { $crate::godot_dbg!($val) };
33 ($($val:expr),+ $(,)?) => {
34 ($($crate::godot_dbg!($val)),+,)
35 };
36}
37
38#[macro_export]
53macro_rules! godot_site {
54 () => {{
55 #[allow(unused_unsafe)]
58 let site: $crate::log::Site<'static> = unsafe {
59 let file = ::std::ffi::CStr::from_bytes_with_nul_unchecked(
60 ::std::concat!(::std::file!(), "\0").as_bytes(),
61 );
62 let func = ::std::ffi::CStr::from_bytes_with_nul_unchecked(b"<unset>\0");
63 $crate::log::Site::new(file, func, ::std::line!())
64 };
65
66 site
67 }};
68 ($($path:tt)+) => {{
69 #[allow(unused_unsafe)]
72 let site: $crate::log::Site<'static> = unsafe {
73 let file = ::std::ffi::CStr::from_bytes_with_nul_unchecked(
74 ::std::concat!(::std::file!(), "\0").as_bytes(),
75 );
76 let func = ::std::ffi::CStr::from_bytes_with_nul_unchecked(
77 ::std::concat!(::std::stringify!($($path)+), "\0").as_bytes(),
78 );
79 $crate::log::Site::new(file, func, ::std::line!())
80 };
81
82 site
83 }};
84}
85
86#[macro_export]
95macro_rules! godot_warn {
96 ($($args:tt)*) => ({
97 $crate::log::warn($crate::godot_site!(), ::std::format_args!($($args)*));
98 });
99}
100
101#[macro_export]
110macro_rules! godot_error {
111 ($($args:tt)*) => ({
112 $crate::log::error($crate::godot_site!(), ::std::format_args!($($args)*));
113 });
114}
115
116macro_rules! impl_basic_trait_as_sys {
117 (
118 Drop for $Type:ty as $GdType:ident : $gd_method:ident
119 ) => {
120 impl Drop for $Type {
121 #[inline]
122 fn drop(&mut self) {
123 unsafe { (get_api().$gd_method)(self.sys_mut()) }
124 }
125 }
126 };
127
128 (
129 Clone for $Type:ty as $GdType:ident : $gd_method:ident
130 ) => {
131 impl Clone for $Type {
132 #[inline]
133 fn clone(&self) -> Self {
134 unsafe {
135 let mut result = sys::$GdType::default();
136 (get_api().$gd_method)(&mut result, self.sys());
137 <$Type>::from_sys(result)
138 }
139 }
140 }
141 };
142
143 (
144 Default for $Type:ty as $GdType:ident : $gd_method:ident
145 ) => {
146 impl Default for $Type {
147 #[inline]
148 fn default() -> Self {
149 unsafe {
150 let mut gd_val = sys::$GdType::default();
151 (get_api().$gd_method)(&mut gd_val);
152 <$Type>::from_sys(gd_val)
153 }
154 }
155 }
156 };
157
158 (
159 PartialEq for $Type:ty as $GdType:ident : $gd_method:ident
160 ) => {
161 impl PartialEq for $Type {
162 #[inline]
163 fn eq(&self, other: &Self) -> bool {
164 unsafe { (get_api().$gd_method)(self.sys(), other.sys()) }
165 }
166 }
167 };
168
169 (
170 Eq for $Type:ty as $GdType:ident : $gd_method:ident
171 ) => {
172 impl_basic_trait_as_sys!(PartialEq for $Type as $GdType : $gd_method);
173 impl Eq for $Type {}
174 };
175
176 (
177 Ord for $Type:ty as $GdType:ident : $gd_method:ident
178 ) => {
179 impl PartialOrd for $Type {
180 #[inline]
181 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
182 Some(self.cmp(other))
183 }
184 }
185 impl Ord for $Type {
186 #[inline]
187 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
188 let op_less = get_api().$gd_method;
189 if unsafe { op_less(&self.0, &other.0) } {
190 std::cmp::Ordering::Less
191 } else if unsafe { op_less(&other.0, &self.0) } {
192 std::cmp::Ordering::Greater
193 } else {
194 std::cmp::Ordering::Equal
195 }
196 }
197 }
198 };
199
200 (
201 NewRef for $Type:ty as $GdType:ident : $gd_method:ident
202 ) => {
203 impl NewRef for $Type {
204 #[inline]
205 fn new_ref(&self) -> $Type {
206 unsafe {
207 let mut result = Default::default();
208 (get_api().$gd_method)(&mut result, self.sys());
209 <$Type>::from_sys(result)
210 }
211 }
212 }
213 };
214}
215
216macro_rules! impl_basic_traits_as_sys {
217 (
218 for $Type:ty as $GdType:ident {
219 $( $Trait:ident => $gd_method:ident; )*
220 }
221 ) => (
222 $(
223 impl_basic_trait_as_sys!(
224 $Trait for $Type as $GdType : $gd_method
225 );
226 )*
227 )
228}
229
230#[doc(hidden)]
231#[macro_export]
232macro_rules! godot_test_impl {
233 ( $( $test_name:ident $body:block $($attrs:tt)* )* ) => {
234 $(
235 $($attrs)*
236 #[doc(hidden)]
237 #[inline]
238 #[must_use]
239 pub fn $test_name() -> bool {
240 let str_name = stringify!($test_name);
241 println!(" -- {}", str_name);
242
243 let ok = ::std::panic::catch_unwind(
244 || $body
245 ).is_ok();
246
247 if !ok {
248 if ::std::panic::catch_unwind(|| {
249 $crate::godot_error!(" !! Test {} failed", str_name);
250 }).is_err() {
251 eprintln!(" !! Test {} failed", str_name);
252 eprintln!(" !! And failed to call Godot API to log error message");
253 }
254 }
255
256 ok
257 }
258 )*
259 }
260}
261
262#[doc(hidden)]
269macro_rules! godot_test {
270 ($($test_name:ident $body:block)*) => {
271 $(
272 godot_test_impl!($test_name $body #[cfg(feature = "gd-test")]);
273 )*
274 }
275}
276
277#[doc(hidden)]
284#[macro_export]
285macro_rules! godot_itest {
286 ($($test_name:ident $body:block)*) => {
287 $(
288 $crate::godot_test_impl!($test_name $body);
289 )*
290 }
291}