1use super::*;
9use crate::builtin::*;
10use crate::global;
11use crate::meta::error::{ConvertError, FromVariantError};
12use crate::meta::{
13 ArrayElement, GodotFfiVariant, GodotType, PropertyHintInfo, PropertyInfo, RefArg,
14};
15use godot_ffi as sys;
16macro_rules! impl_ffi_variant {
27 (ref $T:ty, $from_fn:ident, $to_fn:ident $(; $GodotTy:ident)?) => {
28 impl_ffi_variant!(@impls by_ref; $T, $from_fn, $to_fn $(; $GodotTy)?);
29 };
30 ($T:ty, $from_fn:ident, $to_fn:ident $(; $GodotTy:ident)?) => {
31 impl_ffi_variant!(@impls by_val; $T, $from_fn, $to_fn $(; $GodotTy)?);
32 };
33
34 (@impls $by_ref_or_val:ident; $T:ty, $from_fn:ident, $to_fn:ident $(; $GodotTy:ident)?) => {
36 impl GodotFfiVariant for $T {
37 fn ffi_to_variant(&self) -> Variant {
38 let variant = unsafe {
39 Variant::new_with_var_uninit(|variant_ptr| {
40 let converter = sys::builtin_fn!($from_fn);
41 converter(variant_ptr, sys::SysPtr::force_mut(self.sys()));
42 })
43 };
44
45 variant
46 }
47
48 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
49 if variant.get_type() != Self::VARIANT_TYPE {
51 return Err(FromVariantError::BadType {
52 expected: Self::VARIANT_TYPE,
53 actual: variant.get_type(),
54 }
55 .into_error(variant.clone()));
56 }
57
58 let result = unsafe {
59 Self::new_with_uninit(|self_ptr| {
60 let converter = sys::builtin_fn!($to_fn);
61 converter(self_ptr, sys::SysPtr::force_mut(variant.var_sys()));
62 })
63 };
64
65 Ok(result)
66 }
67 }
68
69 impl GodotType for $T {
70 type Ffi = Self;
71 impl_ffi_variant!(@assoc_to_ffi $by_ref_or_val);
72
73 fn into_ffi(self) -> Self::Ffi {
74 self
75 }
76
77 fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
78 Ok(ffi)
79 }
80
81 impl_ffi_variant!(@godot_type_name $T $(, $GodotTy)?);
82 }
83
84 impl ArrayElement for $T {}
85
86 impl_ffi_variant!(@as_arg $by_ref_or_val $T);
87 };
88
89 (@godot_type_name $T:ty) => {
90 fn godot_type_name() -> String {
91 stringify!($T).into()
92 }
93 };
94
95 (@godot_type_name $T:ty, $godot_type_name:ident) => {
96 fn godot_type_name() -> String {
97 stringify!($godot_type_name).into()
98 }
99 };
100
101 (@assoc_to_ffi by_ref) => {
102 type ToFfi<'a> = RefArg<'a, Self>;
103
104 fn to_ffi(&self) -> Self::ToFfi<'_> {
105 RefArg::new(self)
106 }
107 };
108
109 (@assoc_to_ffi by_val) => {
110 type ToFfi<'a> = Self;
111
112 fn to_ffi(&self) -> Self::ToFfi<'_> {
113 self.clone()
114 }
115 };
116
117 (@as_arg by_ref $T:ty) => {
118 $crate::meta::impl_asarg_by_ref!($T);
119 };
120
121 (@as_arg by_val $T:ty) => {
122 $crate::meta::impl_asarg_by_value!($T);
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; int);
139 impl_ffi_variant!(f64, float_to_variant, float_from_variant; float);
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; AABB);
155 impl_ffi_variant!(Color, color_to_variant, color_from_variant);
156 impl_ffi_variant!(Rid, rid_to_variant, rid_from_variant; RID);
157 impl_ffi_variant!(ref GString, string_to_variant, string_from_variant; String);
158 impl_ffi_variant!(ref StringName, string_name_to_variant, string_name_from_variant);
159 impl_ffi_variant!(ref NodePath, node_path_to_variant, node_path_from_variant);
160 impl_ffi_variant!(ref Dictionary, dictionary_to_variant, dictionary_from_variant);
161 impl_ffi_variant!(ref PackedByteArray, packed_byte_array_to_variant, packed_byte_array_from_variant);
162 impl_ffi_variant!(ref PackedInt32Array, packed_int32_array_to_variant, packed_int32_array_from_variant);
163 impl_ffi_variant!(ref PackedInt64Array, packed_int64_array_to_variant, packed_int64_array_from_variant);
164 impl_ffi_variant!(ref PackedFloat32Array, packed_float32_array_to_variant, packed_float32_array_from_variant);
165 impl_ffi_variant!(ref PackedFloat64Array, packed_float64_array_to_variant, packed_float64_array_from_variant);
166 impl_ffi_variant!(ref PackedStringArray, packed_string_array_to_variant, packed_string_array_from_variant);
167 impl_ffi_variant!(ref PackedVector2Array, packed_vector2_array_to_variant, packed_vector2_array_from_variant);
168 impl_ffi_variant!(ref PackedVector3Array, packed_vector3_array_to_variant, packed_vector3_array_from_variant);
169 impl_ffi_variant!(ref PackedColorArray, packed_color_array_to_variant, packed_color_array_from_variant);
170 impl_ffi_variant!(ref Signal, signal_to_variant, signal_from_variant);
171 impl_ffi_variant!(ref Callable, callable_to_variant, callable_from_variant);
172
173 #[cfg(since_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.2")))]
174 mod api_4_2 {
175 use crate::builtin::Array;
176 use crate::meta::ArrayElement;
177 use crate::meta::sealed::Sealed;
178 use crate::task::{impl_dynamic_send, DynamicSend, IntoDynamicSend, ThreadConfined};
179
180
181 impl_dynamic_send!(
182 Send;
183 bool, u8, u16, u32, u64, i8, i16, i32, i64, f32, f64
184 );
185
186 impl_dynamic_send!(
187 Send;
188 builtin::{
189 StringName, Transform2D, Transform3D, Vector2, Vector2i, Vector2Axis,
190 Vector3, Vector3i, Vector3Axis, Vector4, Vector4i, Rect2, Rect2i, Plane, Quaternion, Aabb, Basis, Projection, Color, Rid
191 }
192 );
193
194 impl<T: ArrayElement> Sealed for ThreadConfined<Array<T>> {}
195
196 unsafe impl<T:ArrayElement> DynamicSend for ThreadConfined<Array<T>> {
197 type Inner = Array<T>;
198 fn extract_if_safe(self) -> Option<Self::Inner> {
199 self.extract()
200 }
201 }
202
203 impl<T: ArrayElement> IntoDynamicSend for Array<T> {
204 type Target = ThreadConfined<Array<T>>;
205 fn into_dynamic_send(self) -> Self::Target {
206 crate::task::ThreadConfined::new(self)
207 }
208 }
209
210 impl_dynamic_send!(
211 !Send;
212 Variant, GString, Dictionary, Callable, NodePath, PackedByteArray, PackedInt32Array, PackedInt64Array, PackedFloat32Array,
213 PackedFloat64Array, PackedStringArray, PackedVector2Array, PackedVector3Array, PackedColorArray, Signal
214 );
215
216 impl_dynamic_send!(tuple; );
218 impl_dynamic_send!(tuple; arg1: A1);
219 impl_dynamic_send!(tuple; arg1: A1, arg2: A2);
220 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3);
221 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4);
222 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5);
223 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6);
224 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7);
225 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7, arg8: A8);
226 impl_dynamic_send!(tuple; arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6, arg7: A7, arg8: A8, arg9: A9);
227 }
228
229 #[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
230 mod api_4_3 {
231 use crate::task::impl_dynamic_send;
232
233 use super::*;
234
235 impl_ffi_variant!(ref PackedVector4Array, packed_vector4_array_to_variant, packed_vector4_array_from_variant);
236
237 impl_dynamic_send!(!Send; PackedVector4Array);
238 }
239}
240
241const _: () = {
247 use crate::classes::Object;
248 use crate::obj::{Gd, IndexEnum};
249
250 #[cfg(before_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(before_api = "4.2")))]
251 const fn variant_type<T: GodotType + ArrayElement>() -> VariantType {
252 <T::Ffi as sys::GodotFfi>::VARIANT_TYPE
253 }
254
255 #[cfg(since_api = "4.2")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.2")))]
256 const fn variant_type<T: crate::task::IntoDynamicSend + GodotType + ArrayElement>(
257 ) -> VariantType {
258 <T::Ffi as sys::GodotFfi>::VARIANT_TYPE
259 }
260
261 const NIL: VariantType = variant_type::<Variant>();
262 const BOOL: VariantType = variant_type::<bool>();
263 const I64: VariantType = variant_type::<i64>();
264 const F64: VariantType = variant_type::<f64>();
265 const GSTRING: VariantType = variant_type::<GString>();
266
267 const VECTOR2: VariantType = variant_type::<Vector2>();
268 const VECTOR2I: VariantType = variant_type::<Vector2i>();
269 const RECT2: VariantType = variant_type::<Rect2>();
270 const RECT2I: VariantType = variant_type::<Rect2i>();
271 const VECTOR3: VariantType = variant_type::<Vector3>();
272 const VECTOR3I: VariantType = variant_type::<Vector3i>();
273 const TRANSFORM2D: VariantType = variant_type::<Transform2D>();
274 const TRANSFORM3D: VariantType = variant_type::<Transform3D>();
275 const VECTOR4: VariantType = variant_type::<Vector4>();
276 const VECTOR4I: VariantType = variant_type::<Vector4i>();
277 const PLANE: VariantType = variant_type::<Plane>();
278 const QUATERNION: VariantType = variant_type::<Quaternion>();
279 const AABB: VariantType = variant_type::<Aabb>();
280 const BASIS: VariantType = variant_type::<Basis>();
281 const PROJECTION: VariantType = variant_type::<Projection>();
282 const COLOR: VariantType = variant_type::<Color>();
283 const STRING_NAME: VariantType = variant_type::<StringName>();
284 const NODE_PATH: VariantType = variant_type::<NodePath>();
285 const RID: VariantType = variant_type::<Rid>();
286 const OBJECT: VariantType = variant_type::<Gd<Object>>();
287 const CALLABLE: VariantType = variant_type::<Callable>();
288 const SIGNAL: VariantType = variant_type::<Signal>();
289 const DICTIONARY: VariantType = variant_type::<Dictionary>();
290 const ARRAY: VariantType = variant_type::<VariantArray>();
291 const PACKED_BYTE_ARRAY: VariantType = variant_type::<PackedByteArray>();
292 const PACKED_INT32_ARRAY: VariantType = variant_type::<PackedInt32Array>();
293 const PACKED_INT64_ARRAY: VariantType = variant_type::<PackedInt64Array>();
294 const PACKED_FLOAT32_ARRAY: VariantType = variant_type::<PackedFloat32Array>();
295 const PACKED_FLOAT64_ARRAY: VariantType = variant_type::<PackedFloat64Array>();
296 const PACKED_STRING_ARRAY: VariantType = variant_type::<PackedStringArray>();
297 const PACKED_VECTOR2_ARRAY: VariantType = variant_type::<PackedVector2Array>();
298 const PACKED_VECTOR3_ARRAY: VariantType = variant_type::<PackedVector3Array>();
299 const PACKED_COLOR_ARRAY: VariantType = variant_type::<PackedColorArray>();
300
301 #[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
302 const PACKED_VECTOR4_ARRAY: VariantType = variant_type::<PackedVector4Array>();
303
304 const MAX: i32 = VariantType::ENUMERATOR_COUNT as i32;
305
306 #[deny(unreachable_patterns)]
308 match VariantType::STRING {
309 VariantType { ord: i32::MIN..0 } => panic!("ord is out of defined range!"),
310 NIL => (),
311 BOOL => (),
312 I64 => (),
313 F64 => (),
314 GSTRING => (),
315 VECTOR2 => (),
316 VECTOR2I => (),
317 RECT2 => (),
318 RECT2I => (),
319 VECTOR3 => (),
320 VECTOR3I => (),
321 TRANSFORM2D => (),
322 VECTOR4 => (),
323 VECTOR4I => (),
324 PLANE => (),
325 QUATERNION => (),
326 AABB => (),
327 BASIS => (),
328 TRANSFORM3D => (),
329 PROJECTION => (),
330 COLOR => (),
331 STRING_NAME => (),
332 NODE_PATH => (),
333 RID => (),
334 OBJECT => (),
335 CALLABLE => (),
336 SIGNAL => (),
337 DICTIONARY => (),
338 ARRAY => (),
339 PACKED_BYTE_ARRAY => (),
340 PACKED_INT32_ARRAY => (),
341 PACKED_INT64_ARRAY => (),
342 PACKED_FLOAT32_ARRAY => (),
343 PACKED_FLOAT64_ARRAY => (),
344 PACKED_STRING_ARRAY => (),
345 PACKED_VECTOR2_ARRAY => (),
346 PACKED_VECTOR3_ARRAY => (),
347 PACKED_COLOR_ARRAY => (),
348
349 #[cfg(since_api = "4.3")] #[cfg_attr(published_docs, doc(cfg(since_api = "4.3")))]
350 PACKED_VECTOR4_ARRAY => (),
351 VariantType { ord: MAX.. } => panic!("ord is out of defined range!"),
352 }
353};
354
355impl GodotFfiVariant for () {
360 fn ffi_to_variant(&self) -> Variant {
361 Variant::nil()
362 }
363
364 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
365 if variant.is_nil() {
366 return Ok(());
367 }
368
369 Err(FromVariantError::BadType {
370 expected: VariantType::NIL,
371 actual: variant.get_type(),
372 }
373 .into_error(variant.clone()))
374 }
375}
376
377impl GodotType for () {
378 type Ffi = ();
379 type ToFfi<'a> = ();
380
381 fn to_ffi(&self) -> Self::ToFfi<'_> {}
382
383 fn into_ffi(self) -> Self::Ffi {}
384
385 fn try_from_ffi(_: Self::Ffi) -> Result<Self, ConvertError> {
386 Ok(())
387 }
388
389 fn godot_type_name() -> String {
390 "Variant".to_string()
391 }
392}
393
394impl GodotFfiVariant for Variant {
395 fn ffi_to_variant(&self) -> Variant {
396 self.clone()
397 }
398
399 fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
400 Ok(variant.clone())
401 }
402}
403
404impl GodotType for Variant {
405 type Ffi = Variant;
406 type ToFfi<'a> = RefArg<'a, Variant>;
407
408 fn to_ffi(&self) -> Self::ToFfi<'_> {
409 RefArg::new(self)
410 }
411
412 fn into_ffi(self) -> Self::Ffi {
413 self
414 }
415
416 fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
417 Ok(ffi)
418 }
419
420 fn param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
421 sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE
422 }
423
424 fn property_info(property_name: &str) -> PropertyInfo {
425 PropertyInfo {
426 variant_type: Self::VARIANT_TYPE,
427 class_name: Self::class_name(),
428 property_name: StringName::from(property_name),
429 hint_info: PropertyHintInfo::none(),
430 usage: global::PropertyUsageFlags::DEFAULT | global::PropertyUsageFlags::NIL_IS_VARIANT,
431 }
432 }
433
434 fn godot_type_name() -> String {
435 "Variant".to_string()
436 }
437}