1use godot_ffi as sys;
9use sys::GodotFfi;
10
11use crate::builtin::*;
12use crate::meta::error::{ConvertError, FromVariantError};
13use crate::meta::sealed::Sealed;
14use crate::meta::{Element, GodotFfiVariant, GodotType, RefArg};
15use crate::registry::info::ParamMetadata;
16use crate::task::{DynamicSend, IntoDynamicSend, ThreadConfined, impl_dynamic_send};
17
18macro_rules! impl_ffi_variant {
28 (ref $T:ty, $from_fn:ident, $to_fn:ident; $metadata:expr) => {
30 impl_ffi_variant!(@impls by_ref, $metadata, main_thread; $T, $from_fn, $to_fn);
31 };
32 ($T:ty, $from_fn:ident, $to_fn:ident; $metadata:expr) => {
33 impl_ffi_variant!(@impls by_val, $metadata, main_thread; $T, $from_fn, $to_fn);
34 };
35
36 (ref $T:ty, $from_fn:ident, $to_fn:ident) => {
38 impl_ffi_variant!(@impls by_ref, ParamMetadata::NONE, main_thread; $T, $from_fn, $to_fn);
39 };
40 ($T:ty, $from_fn:ident, $to_fn:ident) => {
41 impl_ffi_variant!(@impls by_val, ParamMetadata::NONE, main_thread; $T, $from_fn, $to_fn);
42 };
43
44 (thread_safe ref $T:ty, $from_fn:ident, $to_fn:ident) => {
47 impl_ffi_variant!(@impls by_ref, ParamMetadata::NONE, thread_safe; $T, $from_fn, $to_fn);
48 };
49
50 (@converter main_thread, $fn:ident) => { sys::builtin_fn!($fn) };
52 (@converter thread_safe, $fn:ident) => { sys::thread_safe_lifecycle().$fn };
53
54 (@impls $by_ref_or_val:ident, $metadata:expr, $mode:ident; $T:ty, $from_fn:ident, $to_fn:ident) => {
56 impl GodotFfiVariant for $T {
57 fn ffi_to_variant(&self) -> Variant {
58 let variant = unsafe {
59 Variant::new_with_var_uninit(|variant_ptr| {
60 let converter = impl_ffi_variant!(@converter $mode, $from_fn);
61 converter(variant_ptr, sys::SysPtr::force_mut(self.sys()));
62 })
63 };
64
65 variant
66 }
67
68 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
69 if variant.get_type() != Self::VARIANT_TYPE.variant_as_nil() {
71 return Err(FromVariantError::BadType {
72 expected: Self::VARIANT_TYPE.variant_as_nil(),
73 actual: variant.get_type(),
74 }
75 .into_error(variant.clone()));
76 }
77
78 let result = unsafe {
79 Self::new_with_uninit(|self_ptr| {
80 let converter = impl_ffi_variant!(@converter $mode, $to_fn);
81 converter(self_ptr, sys::SysPtr::force_mut(variant.var_sys()));
82 })
83 };
84
85 Ok(result)
86 }
87 }
88
89 impl GodotType for $T {
90 type Ffi = Self;
91 impl_ffi_variant!(@assoc_to_ffi $by_ref_or_val);
92
93 fn into_ffi(self) -> Self::Ffi {
94 self
95 }
96
97 fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
98 Ok(ffi)
99 }
100
101 fn default_metadata() -> ParamMetadata {
102 $metadata
103 }
104 }
105
106 impl Element for $T {}
107 };
108
109 (@assoc_to_ffi by_ref) => {
110 type ToFfi<'a> = RefArg<'a, Self>;
111
112 fn to_ffi(&self) -> Self::ToFfi<'_> {
113 RefArg::new(self)
114 }
115 };
116
117 (@assoc_to_ffi by_val) => {
118 type ToFfi<'a> = Self;
119
120 fn to_ffi(&self) -> Self::ToFfi<'_> {
121 self.clone()
122 }
123 };
124}
125
126#[rustfmt::skip]
130#[allow(clippy::module_inception)]
131mod impls {
132 use super::*;
133
134 impl_ffi_variant!(bool, bool_to_variant, bool_from_variant);
138 impl_ffi_variant!(i64, int_to_variant, int_from_variant; ParamMetadata::INT_IS_INT64);
139 impl_ffi_variant!(f64, float_to_variant, float_from_variant; ParamMetadata::REAL_IS_DOUBLE);
140 impl_ffi_variant!(Vector2, vector2_to_variant, vector2_from_variant);
141 impl_ffi_variant!(Vector3, vector3_to_variant, vector3_from_variant);
142 impl_ffi_variant!(Vector4, vector4_to_variant, vector4_from_variant);
143 impl_ffi_variant!(Vector2i, vector2i_to_variant, vector2i_from_variant);
144 impl_ffi_variant!(Vector3i, vector3i_to_variant, vector3i_from_variant);
145 impl_ffi_variant!(Vector4i, vector4i_to_variant, vector4i_from_variant);
146 impl_ffi_variant!(Quaternion, quaternion_to_variant, quaternion_from_variant);
147 impl_ffi_variant!(Transform2D, transform_2d_to_variant, transform_2d_from_variant);
148 impl_ffi_variant!(Transform3D, transform_3d_to_variant, transform_3d_from_variant);
149 impl_ffi_variant!(Basis, basis_to_variant, basis_from_variant);
150 impl_ffi_variant!(Projection, projection_to_variant, projection_from_variant);
151 impl_ffi_variant!(Plane, plane_to_variant, plane_from_variant);
152 impl_ffi_variant!(Rect2, rect2_to_variant, rect2_from_variant);
153 impl_ffi_variant!(Rect2i, rect2i_to_variant, rect2i_from_variant);
154 impl_ffi_variant!(Aabb, aabb_to_variant, aabb_from_variant);
155 impl_ffi_variant!(Color, color_to_variant, color_from_variant);
156 impl_ffi_variant!(Rid, rid_to_variant, rid_from_variant);
157 impl_ffi_variant!(ref NodePath, node_path_to_variant, node_path_from_variant);
158 impl_ffi_variant!(ref Signal, signal_to_variant, signal_from_variant);
159 impl_ffi_variant!(ref Callable, callable_to_variant, callable_from_variant);
160
161 impl_ffi_variant!(thread_safe ref GString, string_to_variant, string_from_variant);
163 impl_ffi_variant!(thread_safe ref StringName, string_name_to_variant, string_name_from_variant);
164}
165
166impl<T: Element> Sealed for ThreadConfined<Array<T>> {}
170
171unsafe impl<T: Element> DynamicSend for ThreadConfined<Array<T>> {
172 type Inner = Array<T>;
173 fn extract_if_safe(self) -> Option<Self::Inner> {
174 self.extract()
175 }
176}
177
178impl<T: Element> IntoDynamicSend for Array<T> {
179 type Target = ThreadConfined<Array<T>>;
180 fn into_dynamic_send(self) -> Self::Target {
181 ThreadConfined::new(self)
182 }
183}
184
185impl_dynamic_send!(
186 Send;
187 bool, u8, u16, u32, u64, i8, i16, i32, i64, f32, f64
188);
189
190impl_dynamic_send!(
191 Send;
192 StringName, Color, Rid,
193 Vector2, Vector2i, Vector2Axis,
194 Vector3, Vector3i, Vector3Axis,
195 Vector4, Vector4i,
196 Rect2, Rect2i, Aabb,
197 Transform2D, Transform3D, Basis,
198 Plane, Quaternion, Projection
199);
200
201impl_dynamic_send!(
202 !Send;
203 Variant, NodePath, GString, VarDictionary, Callable, Signal,
204 PackedByteArray, PackedInt32Array, PackedInt64Array, PackedFloat32Array, PackedFloat64Array, PackedStringArray,
205 PackedVector2Array, PackedVector3Array, PackedColorArray
206);
207
208impl_dynamic_send!(tuple; );
210impl_dynamic_send!(tuple; arg1: A1);
211impl_dynamic_send!(tuple; arg1: A1, arg2: A2);
212impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3);
213impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4);
214impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5);
215impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6);
216impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7);
217impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7, arg8: A8);
218impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7, arg8: A8, arg9: A9);
219
220#[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
221mod api_4_3 {
222 use crate::task::impl_dynamic_send;
223
224 impl_dynamic_send!(!Send; PackedVector4Array);
225}
226
227const _: () = {
236 use crate::classes::Object;
237 use crate::obj::{Gd, IndexEnum};
238
239 const fn variant_type<T: crate::task::IntoDynamicSend + GodotType + Element>() -> VariantType {
240 <T::Ffi as sys::GodotFfi>::VARIANT_TYPE.variant_as_nil()
241 }
242
243 const NIL: VariantType = variant_type::<Variant>();
244 const BOOL: VariantType = variant_type::<bool>();
245 const I64: VariantType = variant_type::<i64>();
246 const F64: VariantType = variant_type::<f64>();
247 const GSTRING: VariantType = variant_type::<GString>();
248
249 const VECTOR2: VariantType = variant_type::<Vector2>();
250 const VECTOR2I: VariantType = variant_type::<Vector2i>();
251 const RECT2: VariantType = variant_type::<Rect2>();
252 const RECT2I: VariantType = variant_type::<Rect2i>();
253 const VECTOR3: VariantType = variant_type::<Vector3>();
254 const VECTOR3I: VariantType = variant_type::<Vector3i>();
255 const TRANSFORM2D: VariantType = variant_type::<Transform2D>();
256 const TRANSFORM3D: VariantType = variant_type::<Transform3D>();
257 const VECTOR4: VariantType = variant_type::<Vector4>();
258 const VECTOR4I: VariantType = variant_type::<Vector4i>();
259 const PLANE: VariantType = variant_type::<Plane>();
260 const QUATERNION: VariantType = variant_type::<Quaternion>();
261 const AABB: VariantType = variant_type::<Aabb>();
262 const BASIS: VariantType = variant_type::<Basis>();
263 const PROJECTION: VariantType = variant_type::<Projection>();
264 const COLOR: VariantType = variant_type::<Color>();
265 const STRING_NAME: VariantType = variant_type::<StringName>();
266 const NODE_PATH: VariantType = variant_type::<NodePath>();
267 const RID: VariantType = variant_type::<Rid>();
268 const OBJECT: VariantType = variant_type::<Gd<Object>>();
269 const CALLABLE: VariantType = variant_type::<Callable>();
270 const SIGNAL: VariantType = variant_type::<Signal>();
271 const DICTIONARY: VariantType = variant_type::<VarDictionary>();
272 const ARRAY: VariantType = variant_type::<VarArray>();
273 const PACKED_BYTE_ARRAY: VariantType = variant_type::<PackedByteArray>();
274 const PACKED_INT32_ARRAY: VariantType = variant_type::<PackedInt32Array>();
275 const PACKED_INT64_ARRAY: VariantType = variant_type::<PackedInt64Array>();
276 const PACKED_FLOAT32_ARRAY: VariantType = variant_type::<PackedFloat32Array>();
277 const PACKED_FLOAT64_ARRAY: VariantType = variant_type::<PackedFloat64Array>();
278 const PACKED_STRING_ARRAY: VariantType = variant_type::<PackedStringArray>();
279 const PACKED_VECTOR2_ARRAY: VariantType = variant_type::<PackedVector2Array>();
280 const PACKED_VECTOR3_ARRAY: VariantType = variant_type::<PackedVector3Array>();
281 const PACKED_COLOR_ARRAY: VariantType = variant_type::<PackedColorArray>();
282
283 #[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
284 const PACKED_VECTOR4_ARRAY: VariantType = variant_type::<PackedVector4Array>();
285
286 const MAX: i32 = VariantType::ENUMERATOR_COUNT as i32;
287
288 #[deny(unreachable_patterns)]
290 match VariantType::STRING {
291 VariantType { ord: i32::MIN..0 } => panic!("ord is out of defined range!"),
292 NIL => (),
293 BOOL => (),
294 I64 => (),
295 F64 => (),
296 GSTRING => (),
297 VECTOR2 => (),
298 VECTOR2I => (),
299 RECT2 => (),
300 RECT2I => (),
301 VECTOR3 => (),
302 VECTOR3I => (),
303 TRANSFORM2D => (),
304 VECTOR4 => (),
305 VECTOR4I => (),
306 PLANE => (),
307 QUATERNION => (),
308 AABB => (),
309 BASIS => (),
310 TRANSFORM3D => (),
311 PROJECTION => (),
312 COLOR => (),
313 STRING_NAME => (),
314 NODE_PATH => (),
315 RID => (),
316 OBJECT => (),
317 CALLABLE => (),
318 SIGNAL => (),
319 DICTIONARY => (),
320 ARRAY => (),
321 PACKED_BYTE_ARRAY => (),
322 PACKED_INT32_ARRAY => (),
323 PACKED_INT64_ARRAY => (),
324 PACKED_FLOAT32_ARRAY => (),
325 PACKED_FLOAT64_ARRAY => (),
326 PACKED_STRING_ARRAY => (),
327 PACKED_VECTOR2_ARRAY => (),
328 PACKED_VECTOR3_ARRAY => (),
329 PACKED_COLOR_ARRAY => (),
330
331 #[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
332 PACKED_VECTOR4_ARRAY => (),
333 VariantType { ord: MAX.. } => panic!("ord is out of defined range!"),
334 }
335};
336
337impl GodotFfiVariant for () {
342 fn ffi_to_variant(&self) -> Variant {
343 Variant::nil()
344 }
345
346 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
347 if variant.is_nil() {
348 return Ok(());
349 }
350
351 Err(FromVariantError::BadType {
352 expected: VariantType::NIL,
353 actual: variant.get_type(),
354 }
355 .into_error(variant.clone()))
356 }
357}
358
359impl GodotType for () {
360 type Ffi = ();
361 type ToFfi<'a> = ();
362
363 fn to_ffi(&self) -> Self::ToFfi<'_> {}
364
365 fn into_ffi(self) -> Self::Ffi {}
366
367 fn try_from_ffi(_: Self::Ffi) -> Result<Self, ConvertError> {
368 Ok(())
369 }
370}
371
372impl GodotFfiVariant for Variant {
373 fn ffi_to_variant(&self) -> Variant {
374 self.clone()
375 }
376
377 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
378 Ok(variant.clone())
379 }
380}
381
382impl GodotType for Variant {
383 type Ffi = Variant;
384 type ToFfi<'a> = RefArg<'a, Variant>;
385
386 fn to_ffi(&self) -> Self::ToFfi<'_> {
387 RefArg::new(self)
388 }
389
390 fn into_ffi(self) -> Self::Ffi {
391 self
392 }
393
394 fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
395 Ok(ffi)
396 }
397}