gdnative_core/core_types/
variant.rs

1use crate::*;
2use std::borrow::Cow;
3use std::collections::{HashMap, HashSet};
4use std::default::Default;
5use std::fmt;
6use std::hash::Hash;
7use std::mem::{forget, transmute};
8use std::ptr;
9
10use crate::core_types::*;
11use crate::object::ownership::*;
12use crate::object::*;
13use crate::private::{get_api, ManuallyManagedClassPlaceholder};
14
15#[cfg(feature = "serde")]
16mod serialize;
17
18/// A `Variant` can represent all Godot values (core types or `Object` class instances).
19///
20/// The underlying data is either stored inline or reference-counted on the heap,
21/// depending on the size of the type and whether the it is trivially copyable.
22///
23/// If you compile godot-rust with the `serde` feature enabled, you will have
24/// access to serialization/deserialization support: the traits `Serialize`
25/// and `Deserialize` will be automatically implemented on [`VariantDispatch`]
26/// as well as most of the types in [`core_types`].
27pub struct Variant(pub(crate) sys::godot_variant);
28
29macro_rules! impl_coerce_from_variant_inner {
30    (impl CoerceFromVariant for $type:path = transmute($to_gd_method:ident)) => {
31        impl private::Sealed for $type {}
32        impl CoerceFromVariant for $type {
33            #[inline]
34            fn coerce_from_variant(v: &Variant) -> Self {
35                unsafe {
36                    #[allow(clippy::useless_transmute)]
37                    transmute((get_api().$to_gd_method)(&v.0))
38                }
39            }
40        }
41    };
42    (impl CoerceFromVariant for $type:path = from_sys($to_gd_method:ident)) => {
43        impl private::Sealed for $type {}
44        impl CoerceFromVariant for $type {
45            #[inline]
46            fn coerce_from_variant(v: &Variant) -> Self {
47                unsafe { Self::from_sys((get_api().$to_gd_method)(&v.0)) }
48            }
49        }
50    };
51}
52
53macro_rules! impl_coerce_from_variant {
54    (
55        $(
56            impl CoerceFromVariant for $type:path = $kind:ident ($to_gd_method:ident);
57        )*
58    ) => {
59        $(
60            impl_coerce_from_variant_inner!(impl CoerceFromVariant for $type = $kind($to_gd_method));
61        )*
62    }
63}
64
65macro_rules! variant_dispatch_arm {
66    ($v:expr, $variant:ident ( $inner:ty )) => {
67        VariantDispatch::$variant(<$inner>::from_variant($v).unwrap())
68    };
69    ($v:expr, $variant:ident) => {
70        VariantDispatch::$variant
71    };
72}
73
74macro_rules! decl_variant_type {
75    (
76        pub enum VariantType, VariantDispatch {
77            $(
78                $variant:ident $( ($inner:ty) )? = $c_const:path,
79            )*
80        }
81    ) => {
82        #[repr(u32)]
83        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
84        pub enum VariantType {
85            $(
86                $variant = $c_const as u32,
87            )*
88        }
89
90        impl VariantType {
91            /// The potential names of VariantTypes. Mostly used for serialization.
92            pub const NAMES: &'static [&'static str] = &[
93                $(stringify!($variant),)*
94            ];
95        }
96
97        /// Rust enum associating each primitive variant type to its value.
98        ///
99        /// For `Variant`s containing objects, the original `Variant` is returned unchanged, due to
100        /// the limitations of statically-determined memory management.
101        #[repr(u32)]
102        pub enum VariantDispatch {
103            $(
104                $variant $( ($inner) )?,
105            )*
106        }
107
108        impl<'a> From<&'a Variant> for VariantDispatch {
109            #[inline]
110            fn from(v: &'a Variant) -> Self {
111                match v.get_type() {
112                    $(
113                        VariantType::$variant => {
114                            variant_dispatch_arm!(v, $variant $( ($inner) )?)
115                        },
116                    )*
117                }
118            }
119        }
120
121        impl<'a> From<&'a VariantDispatch> for Variant {
122            #[inline]
123            fn from(v: &'a VariantDispatch) -> Self {
124                match v {
125                    $($(VariantDispatch::$variant(v) => {
126                        let v: &$inner = v;
127                        v.to_variant()
128                    })?)*
129                    _ => Variant::nil()
130                }
131            }
132        }
133    }
134}
135
136decl_variant_type!(
137    pub enum VariantType, VariantDispatch {
138        Nil = sys::godot_variant_type_GODOT_VARIANT_TYPE_NIL,
139        Bool(bool) = sys::godot_variant_type_GODOT_VARIANT_TYPE_BOOL,
140        I64(i64) = sys::godot_variant_type_GODOT_VARIANT_TYPE_INT,
141        F64(f64) = sys::godot_variant_type_GODOT_VARIANT_TYPE_REAL,
142        GodotString(GodotString) = sys::godot_variant_type_GODOT_VARIANT_TYPE_STRING,
143        Vector2(Vector2) = sys::godot_variant_type_GODOT_VARIANT_TYPE_VECTOR2,
144        Rect2(Rect2) = sys::godot_variant_type_GODOT_VARIANT_TYPE_RECT2,
145        Vector3(Vector3) = sys::godot_variant_type_GODOT_VARIANT_TYPE_VECTOR3,
146        Transform2D(Transform2D) = sys::godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM2D,
147        Plane(Plane) = sys::godot_variant_type_GODOT_VARIANT_TYPE_PLANE,
148        Quat(Quat) = sys::godot_variant_type_GODOT_VARIANT_TYPE_QUAT,
149        Aabb(Aabb) = sys::godot_variant_type_GODOT_VARIANT_TYPE_AABB,
150        Basis(Basis) = sys::godot_variant_type_GODOT_VARIANT_TYPE_BASIS,
151        Transform(Transform) = sys::godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM,
152        Color(Color) = sys::godot_variant_type_GODOT_VARIANT_TYPE_COLOR,
153        NodePath(NodePath) = sys::godot_variant_type_GODOT_VARIANT_TYPE_NODE_PATH,
154        Rid(Rid) = sys::godot_variant_type_GODOT_VARIANT_TYPE_RID,
155        Object(Variant) = sys::godot_variant_type_GODOT_VARIANT_TYPE_OBJECT,
156        Dictionary(Dictionary) = sys::godot_variant_type_GODOT_VARIANT_TYPE_DICTIONARY,
157        VariantArray(VariantArray) = sys::godot_variant_type_GODOT_VARIANT_TYPE_ARRAY,
158        ByteArray(PoolArray<u8>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY,
159        Int32Array(PoolArray<i32>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_INT_ARRAY,
160        Float32Array(PoolArray<f32>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_REAL_ARRAY,
161        StringArray(PoolArray<GodotString>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_STRING_ARRAY,
162        Vector2Array(PoolArray<Vector2>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR2_ARRAY,
163        Vector3Array(PoolArray<Vector3>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR3_ARRAY,
164        ColorArray(PoolArray<Color>) = sys::godot_variant_type_GODOT_VARIANT_TYPE_POOL_COLOR_ARRAY,
165    }
166);
167
168impl VariantType {
169    #[allow(clippy::unnecessary_cast)] // False positives: casts necessary for cross-platform
170    #[doc(hidden)]
171    #[inline]
172    pub fn from_sys(v: sys::godot_variant_type) -> VariantType {
173        unsafe { transmute(v as u32) }
174    }
175
176    /// The `stringify!` representation of this variant. Mostly used for serialization.
177    #[inline]
178    pub const fn name(self) -> &'static str {
179        // NOTE: this assumes that the discriminants remain sequential, since any additions to the
180        // VariantType enum would require a breaking change anyway since it is not marked as non-exhaustive.
181        // See also the Deserialize implementation in the serde submodule.
182        Self::NAMES[self as usize]
183    }
184}
185
186#[allow(clippy::unnecessary_cast)] // False positives: casts necessary for cross-platform
187#[repr(u32)]
188#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
189pub enum CallError {
190    InvalidMethod =
191        sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD as u32,
192    InvalidArgument =
193        sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_INVALID_ARGUMENT as u32,
194    TooManyArguments =
195        sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_TOO_MANY_ARGUMENTS as u32,
196    TooFewArguments =
197        sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_TOO_FEW_ARGUMENTS as u32,
198    InstanceIsNull =
199        sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL as u32,
200}
201
202impl CallError {
203    #[allow(clippy::unnecessary_cast)] // False positives: casts necessary for cross-platform
204    #[inline]
205    fn from_sys(v: sys::godot_variant_call_error_error) -> Result<(), CallError> {
206        if v == sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_OK {
207            Ok(())
208        } else {
209            debug_assert!(
210                (v as u32) <= sys::godot_variant_call_error_error_GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL as u32,
211                "Godot should have passed a known error",
212            );
213
214            Err(unsafe { transmute(v as u32) })
215        }
216    }
217}
218
219impl std::fmt::Display for CallError {
220    #[inline]
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        use CallError::*;
223        match self {
224            InvalidMethod => write!(f, "invalid method"),
225            InvalidArgument => write!(f, "invalid argument"),
226            TooManyArguments => write!(f, "too many arguments"),
227            TooFewArguments => write!(f, "too few arguments"),
228            InstanceIsNull => write!(f, "instance is null"),
229        }
230    }
231}
232
233impl std::error::Error for CallError {}
234
235/// Godot variant operator kind.
236#[allow(clippy::unnecessary_cast)] // False positives: casts necessary for cross-platform
237#[repr(u32)]
238#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
239pub enum VariantOperator {
240    // Comparison
241    Equal = sys::godot_variant_operator_GODOT_VARIANT_OP_EQUAL as u32,
242    NotEqual = sys::godot_variant_operator_GODOT_VARIANT_OP_NOT_EQUAL as u32,
243    Less = sys::godot_variant_operator_GODOT_VARIANT_OP_LESS as u32,
244    LessEqual = sys::godot_variant_operator_GODOT_VARIANT_OP_LESS_EQUAL as u32,
245    Greater = sys::godot_variant_operator_GODOT_VARIANT_OP_GREATER as u32,
246    GreaterEqual = sys::godot_variant_operator_GODOT_VARIANT_OP_GREATER_EQUAL as u32,
247
248    // Mathematic
249    Add = sys::godot_variant_operator_GODOT_VARIANT_OP_ADD as u32,
250    Subtract = sys::godot_variant_operator_GODOT_VARIANT_OP_SUBTRACT as u32,
251    Multiply = sys::godot_variant_operator_GODOT_VARIANT_OP_MULTIPLY as u32,
252    Divide = sys::godot_variant_operator_GODOT_VARIANT_OP_DIVIDE as u32,
253    Negate = sys::godot_variant_operator_GODOT_VARIANT_OP_NEGATE as u32,
254    Positive = sys::godot_variant_operator_GODOT_VARIANT_OP_POSITIVE as u32,
255    Module = sys::godot_variant_operator_GODOT_VARIANT_OP_MODULE as u32,
256    StringConcat = sys::godot_variant_operator_GODOT_VARIANT_OP_STRING_CONCAT as u32,
257
258    // Bitwise
259    ShiftLeft = sys::godot_variant_operator_GODOT_VARIANT_OP_SHIFT_LEFT as u32,
260    ShiftRight = sys::godot_variant_operator_GODOT_VARIANT_OP_SHIFT_RIGHT as u32,
261    BitAnd = sys::godot_variant_operator_GODOT_VARIANT_OP_BIT_AND as u32,
262    BitOr = sys::godot_variant_operator_GODOT_VARIANT_OP_BIT_OR as u32,
263    BitXor = sys::godot_variant_operator_GODOT_VARIANT_OP_BIT_XOR as u32,
264    BitNegate = sys::godot_variant_operator_GODOT_VARIANT_OP_BIT_NEGATE as u32,
265
266    // Logic
267    And = sys::godot_variant_operator_GODOT_VARIANT_OP_AND as u32,
268    Or = sys::godot_variant_operator_GODOT_VARIANT_OP_OR as u32,
269    Xor = sys::godot_variant_operator_GODOT_VARIANT_OP_XOR as u32,
270    Not = sys::godot_variant_operator_GODOT_VARIANT_OP_NOT as u32,
271
272    // Containment
273    In = sys::godot_variant_operator_GODOT_VARIANT_OP_IN as u32,
274}
275
276#[allow(clippy::unnecessary_cast)] // False positives: casts necessary for cross-platform
277impl VariantOperator {
278    const MAX: u32 = sys::godot_variant_operator_GODOT_VARIANT_OP_MAX as u32;
279
280    #[doc(hidden)]
281    #[inline]
282    pub fn to_sys(self) -> sys::godot_variant_operator {
283        self as u32 as sys::godot_variant_operator
284    }
285
286    #[doc(hidden)]
287    #[inline]
288    pub fn try_from_sys(op: sys::godot_variant_operator) -> Option<Self> {
289        let op = op as u32;
290        if op >= Self::MAX {
291            return None;
292        }
293
294        // SAFETY: Max value is checked, and Self is repr(u32)
295        unsafe { std::mem::transmute(op) }
296    }
297}
298
299/// Error indicating that an operator result is invalid.
300#[derive(Copy, Clone, Eq, PartialEq, Hash, Default, Debug)]
301pub struct InvalidOp;
302
303// These aliases are just here so the type name matches the VariantType's variant names
304// to make writing macros easier.
305type Bool = bool;
306
307impl Variant {
308    /// Creates a `Variant` from a value that implements [`ToVariant`].
309    #[inline]
310    pub fn new<T: OwnedToVariant>(from: T) -> Self {
311        from.owned_to_variant()
312    }
313
314    /// Creates an empty `Variant`.
315    #[inline]
316    pub fn nil() -> Self {
317        unsafe {
318            let api = get_api();
319            let mut dest = sys::godot_variant::default();
320            (api.godot_variant_new_nil)(&mut dest);
321            Variant(dest)
322        }
323    }
324
325    /// Creates a `Variant` from a raw object pointer.
326    ///
327    /// # Safety
328    ///
329    /// The object pointer must be a valid pointer to a godot object.
330    #[doc(hidden)]
331    #[inline]
332    pub unsafe fn from_object_ptr(val: *mut sys::godot_object) -> Variant {
333        let api = get_api();
334        let mut dest = sys::godot_variant::default();
335        (api.godot_variant_new_object)(&mut dest, val);
336        Variant(dest)
337    }
338
339    #[inline]
340    fn try_as_sys_of_type(
341        &self,
342        expected: VariantType,
343    ) -> Result<&sys::godot_variant, FromVariantError> {
344        let variant_type = self.get_type();
345        if variant_type != expected {
346            return Err(FromVariantError::InvalidVariantType {
347                expected,
348                variant_type,
349            });
350        }
351        Ok(&self.0)
352    }
353
354    /// Performs a strongly-typed, structure-aware conversion to `T` from this variant, if it
355    /// is a valid representation of said type. This is the same as `T::from_variant(self).ok()`.
356    ///
357    /// This is the same conversion used to parse arguments of exported methods. See
358    /// [`FromVariant`] for more details.
359    #[inline]
360    pub fn to<T: FromVariant>(&self) -> Option<T> {
361        self.try_to().ok()
362    }
363
364    /// Performs a strongly-typed, structure-aware conversion to `T` from this variant, if it
365    /// is a valid representation of said type. This is the same as `T::from_variant(self)`.
366    ///
367    /// This is the same conversion used to parse arguments of exported methods. See
368    /// [`FromVariant`] for more details.
369    #[inline]
370    pub fn try_to<T: FromVariant>(&self) -> Result<T, FromVariantError> {
371        T::from_variant(self)
372    }
373
374    /// Coerce a value of type `T` out of this variant, through what Godot presents as a
375    /// "best-effort" conversion, possibly returning a default value.
376    ///
377    /// See [`CoerceFromVariant`] for more details.
378    ///
379    /// See also [`Variant::to`] and [`Variant::try_to`] for strongly-typed, structure-aware
380    /// conversions into Rust types.
381    #[inline]
382    pub fn coerce_to<T: CoerceFromVariant>(&self) -> T {
383        T::coerce_from_variant(self)
384    }
385
386    /// Convenience method to extract a `Ref<T, Shared>` from this variant, if the type
387    /// matches. This is the same as `Ref::<T, Shared>::from_variant(self).ok()`.
388    ///
389    /// This is the same conversion used to parse arguments of exported methods. See
390    /// [`FromVariant`] for more details.
391    #[inline]
392    pub fn to_object<T>(&self) -> Option<Ref<T, Shared>>
393    where
394        T: GodotObject,
395    {
396        self.try_to_object::<T>().ok()
397    }
398
399    /// Convenience method to extract a `Ref<T, Shared>` from this variant, if the type
400    /// matches. This is the same as `Ref::<T, Shared>::from_variant(self)`.
401    ///
402    /// This is the same conversion used to parse arguments of exported methods. See
403    /// [`FromVariant`] for more details.
404    #[inline]
405    pub fn try_to_object<T>(&self) -> Result<Ref<T, Shared>, FromVariantError>
406    where
407        T: GodotObject,
408    {
409        unsafe {
410            let api = get_api();
411            let obj = self.try_as_sys_of_type(VariantType::Object)?;
412            let obj = ptr::NonNull::new((api.godot_variant_as_object)(obj))
413                .ok_or(FromVariantError::InvalidNil)?;
414            let obj =
415                object::RawObject::<ManuallyManagedClassPlaceholder>::from_sys_ref_unchecked(obj);
416            let obj = obj
417                .cast::<T>()
418                .ok_or_else(|| FromVariantError::CannotCast {
419                    class: obj.class_name(),
420                    to: T::class_name(),
421                })?;
422
423            Ok(Ref::from_sys(obj.sys()))
424        }
425    }
426
427    /// Returns this variant's type.
428    #[inline]
429    pub fn get_type(&self) -> VariantType {
430        unsafe { VariantType::from_sys((get_api().godot_variant_get_type)(&self.0)) }
431    }
432
433    /// Converts this variant to a primitive value depending on its type.
434    ///
435    /// # Examples
436    ///
437    /// ```ignore
438    /// let variant = 42.to_variant();
439    /// let number_as_float = match variant.dispatch() {
440    ///     VariantDispatch::I64(i) => i as f64,
441    ///     VariantDispatch::F64(f) => f,
442    ///     _ => panic!("not a number"),
443    /// };
444    /// approx::assert_relative_eq!(42.0, number_as_float);
445    /// ```
446    #[inline]
447    pub fn dispatch(&self) -> VariantDispatch {
448        self.into()
449    }
450
451    /// Returns true if this is an empty variant.
452    #[inline]
453    pub fn is_nil(&self) -> bool {
454        match self.get_type() {
455            VariantType::Nil => true,
456            VariantType::Object => {
457                let ptr = unsafe { (get_api().godot_variant_as_object)(&self.0) };
458                ptr.is_null()
459            }
460            _ => false,
461        }
462    }
463
464    #[inline]
465    pub fn has_method(&self, method: impl Into<GodotString>) -> bool {
466        let method = method.into();
467        unsafe { (get_api().godot_variant_has_method)(&self.0, &method.0) }
468    }
469
470    /// Invokes a method on the held object.
471    ///
472    /// # Safety
473    /// This method may invoke [Object::call()] internally, which is unsafe, as it allows
474    /// execution of arbitrary code (including user-defined code in GDScript or unsafe Rust).
475    #[inline]
476    pub unsafe fn call(
477        &mut self,
478        method: impl Into<GodotString>,
479        args: &[Variant],
480    ) -> Result<Variant, CallError> {
481        let method = method.into();
482
483        let api = get_api();
484        let mut err = sys::godot_variant_call_error::default();
485        let mut arg_refs = args.iter().map(Variant::sys).collect::<Vec<_>>();
486        let variant = (api.godot_variant_call)(
487            &mut self.0,
488            &method.0,
489            arg_refs.as_mut_ptr(),
490            args.len() as i32,
491            &mut err,
492        );
493
494        CallError::from_sys(err.error).map(|_| Variant::from_sys(variant))
495    }
496
497    /// Evaluates a variant operator on `self` and `rhs` and returns the result on success.
498    ///
499    /// # Errors
500    ///
501    /// Returns `Err(InvalidOp)` if the result is not valid.
502    #[inline]
503    pub fn evaluate(&self, op: VariantOperator, rhs: &Self) -> Result<Variant, InvalidOp> {
504        unsafe {
505            let api = get_api();
506            let mut ret = Variant::nil();
507            let mut valid = false;
508
509            (api.godot_variant_evaluate)(
510                op.to_sys(),
511                self.sys(),
512                rhs.sys(),
513                ret.sys_mut(),
514                &mut valid,
515            );
516
517            if valid {
518                Ok(ret)
519            } else {
520                Err(InvalidOp)
521            }
522        }
523    }
524
525    /// Get a reference to a `godot-rust` Variant from a raw sys::pointer.
526    ///
527    /// # Safety
528    ///
529    /// The pointer must be a valid pointer to a `sys::godot_variant`.
530    #[inline]
531    pub(crate) unsafe fn cast_ref<'l>(ptr: *const sys::godot_variant) -> &'l Variant {
532        &*(ptr as *const variant::Variant)
533    }
534
535    #[inline]
536    pub(crate) fn cast_mut_ref<'l>(ptr: *mut sys::godot_variant) -> &'l mut Variant {
537        unsafe { &mut *(ptr as *mut variant::Variant) }
538    }
539
540    /// Returns the internal FFI representation of the variant and consumes
541    /// the Rust object without running the destructor.
542    ///
543    /// The returned object has no `Drop` implementation. The caller is
544    /// responsible of manually ensuring destruction.
545    #[inline]
546    #[doc(hidden)]
547    pub fn leak(self) -> sys::godot_variant {
548        let v = self.0;
549        forget(self);
550        v
551    }
552
553    // Returns a copy of the internal ffi representation of the variant.
554    //
555    // The variant remains owned by the rust wrapper and the receiver of
556    // the ffi representation should not run its destructor.
557    #[doc(hidden)]
558    #[inline]
559    pub fn to_sys(&self) -> sys::godot_variant {
560        self.0
561    }
562
563    #[doc(hidden)]
564    #[inline]
565    pub fn sys(&self) -> *const sys::godot_variant {
566        &self.0
567    }
568
569    #[doc(hidden)]
570    #[inline]
571    pub fn sys_mut(&mut self) -> *mut sys::godot_variant {
572        &mut self.0
573    }
574
575    #[doc(hidden)]
576    #[inline]
577    pub fn from_sys(sys: sys::godot_variant) -> Self {
578        Variant(sys)
579    }
580}
581
582impl_coerce_from_variant!(
583    impl CoerceFromVariant for Vector2 = transmute(godot_variant_as_vector2);
584    impl CoerceFromVariant for Vector3 = transmute(godot_variant_as_vector3);
585    impl CoerceFromVariant for Quat = transmute(godot_variant_as_quat);
586    impl CoerceFromVariant for Rect2 = transmute(godot_variant_as_rect2);
587    impl CoerceFromVariant for Transform2D = transmute(godot_variant_as_transform2d);
588    impl CoerceFromVariant for f64 = transmute(godot_variant_as_real);
589    impl CoerceFromVariant for i64 = transmute(godot_variant_as_int);
590    impl CoerceFromVariant for u64 = transmute(godot_variant_as_uint);
591    impl CoerceFromVariant for Bool = transmute(godot_variant_as_bool);
592    impl CoerceFromVariant for Plane = from_sys(godot_variant_as_plane);
593    impl CoerceFromVariant for Transform = from_sys(godot_variant_as_transform);
594    impl CoerceFromVariant for Color = from_sys(godot_variant_as_color);
595    impl CoerceFromVariant for Basis = from_sys(godot_variant_as_basis);
596    impl CoerceFromVariant for Aabb = from_sys(godot_variant_as_aabb);
597    impl CoerceFromVariant for NodePath = from_sys(godot_variant_as_node_path);
598    impl CoerceFromVariant for GodotString = from_sys(godot_variant_as_string);
599    impl CoerceFromVariant for Rid = from_sys(godot_variant_as_rid);
600    impl CoerceFromVariant for VariantArray<Shared> = from_sys(godot_variant_as_array);
601    impl CoerceFromVariant for PoolArray<u8> = from_sys(godot_variant_as_pool_byte_array);
602    impl CoerceFromVariant for PoolArray<i32> = from_sys(godot_variant_as_pool_int_array);
603    impl CoerceFromVariant for PoolArray<f32> = from_sys(godot_variant_as_pool_real_array);
604    impl CoerceFromVariant for PoolArray<GodotString> = from_sys(godot_variant_as_pool_string_array);
605    impl CoerceFromVariant for PoolArray<Vector2> = from_sys(godot_variant_as_pool_vector2_array);
606    impl CoerceFromVariant for PoolArray<Vector3> = from_sys(godot_variant_as_pool_vector3_array);
607    impl CoerceFromVariant for PoolArray<Color> = from_sys(godot_variant_as_pool_color_array);
608    impl CoerceFromVariant for Dictionary<Shared> = from_sys(godot_variant_as_dictionary);
609);
610
611impl_basic_traits_as_sys!(
612    for Variant as godot_variant {
613        Drop => godot_variant_destroy;
614        Clone => godot_variant_new_copy;
615        PartialEq => godot_variant_operator_equal;
616        Ord => godot_variant_operator_less;
617    }
618);
619
620impl Eq for Variant {}
621
622impl fmt::Display for Variant {
623    #[inline]
624    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
625        self.coerce_to::<GodotString>().fmt(f)
626    }
627}
628
629impl Default for Variant {
630    #[inline]
631    fn default() -> Self {
632        Variant::nil()
633    }
634}
635
636impl fmt::Debug for Variant {
637    #[inline]
638    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
639        write!(f, "{:?}({})", self.get_type(), self)
640    }
641}
642
643godot_test!(
644    test_variant_nil {
645        let nil = Variant::nil();
646        assert!(nil.is_nil());
647
648        assert!(nil.try_to::<VariantArray>().is_err());
649        assert!(nil.try_to::<Rid>().is_err());
650        assert!(nil.try_to::<i64>().is_err());
651        assert!(nil.try_to::<bool>().is_err());
652        assert!(nil.try_to::<Aabb>().is_err());
653        assert!(nil.try_to::<Vector2>().is_err());
654        assert!(nil.try_to::<Basis>().is_err());
655
656        assert!(!nil.has_method("foo"));
657
658        let clone = nil.clone();
659        assert!(clone == nil);
660    }
661
662    test_variant_i64 {
663        let v_42 = Variant::new(42);
664        assert_eq!(v_42.get_type(), VariantType::I64);
665
666        assert!(!v_42.is_nil());
667        assert_eq!(v_42.try_to::<i64>(), Ok(42));
668        assert!(v_42.try_to::<f64>().is_err());
669        assert!(v_42.try_to::<VariantArray>().is_err());
670
671        let v_m1 = Variant::new(-1);
672        assert_eq!(v_m1.get_type(), VariantType::I64);
673
674        assert!(!v_m1.is_nil());
675        assert_eq!(v_m1.try_to::<i64>(), Ok(-1));
676        assert!(v_m1.try_to::<f64>().is_err());
677        assert!(v_m1.try_to::<VariantArray>().is_err());
678    }
679
680    test_variant_bool {
681        let v_true = Variant::new(true);
682        assert_eq!(v_true.get_type(), VariantType::Bool);
683
684        assert!(!v_true.is_nil());
685        assert_eq!(v_true.try_to::<bool>(), Ok(true));
686        assert!(v_true.try_to::<f64>().is_err());
687        assert!(v_true.try_to::<VariantArray>().is_err());
688
689        let v_false = Variant::new(false);
690        assert_eq!(v_false.get_type(), VariantType::Bool);
691
692        assert!(!v_false.is_nil());
693        assert_eq!(v_false.try_to::<bool>(), Ok(false));
694        assert!(v_false.try_to::<f64>().is_err());
695        assert!(v_false.try_to::<VariantArray>().is_err());
696
697    }
698);
699
700/// Types that can be converted to a `Variant`.
701///
702/// ## Wrappers and collections
703///
704/// Implementations are provided for a few common Rust wrappers and collections:
705///
706/// - `Option<T>` is unwrapped to inner value, or `Nil` if `None`
707/// - `Result<T, E>` is represented as an externally tagged `Dictionary` (see below).
708/// - `PhantomData<T>` is represented as `Nil`.
709/// - `&[T]` and `Vec<T>` are represented as `VariantArray`s. `FromVariant` is only implemented
710/// for `Vec<T>`.
711///
712/// ## Deriving `ToVariant`
713///
714/// The derive macro does the following mapping between Rust structures and Godot types:
715///
716/// - `Newtype(inner)` is unwrapped to `inner`
717/// - `Tuple(a, b, c)` is represented as a `VariantArray` (`[a, b, c]`)
718/// - `Struct { a, b, c }` is represented as a `Dictionary` (`{ "a": a, "b": b, "c": c }`)
719/// - `Unit` is represented as an empty `Dictionary` (`{}`)
720/// - `Enum::Variant(a, b, c)` is represented as an externally tagged `Dictionary`
721///   (`{ "Variant": [a, b, c] }`), unless another representation is specified with
722///   `#[variant(enum)]` (see below).
723///
724/// Behavior of the derive macros can be customized using attributes:
725///
726/// ### Item attributes
727///
728/// - `#[variant(enum = "str")]`
729///
730/// Only applicable to field-less enums. Variants of types annotated with this attribute
731/// are represented as stringified values of their names, i.e. `"Variant"` for `Enum::Variant`.
732///
733/// - `#[variant(enum = "repr")]`
734///
735/// Only applicable to field-less enums with a explicit primitive `#[repr]` type. Variants of
736/// types annotated with this attribute are represented as their primitive integral values.
737///
738/// ### Field attributes
739///
740/// - `#[variant(to_variant_with = "path::to::func")]`
741///
742/// Use the given function to convert the field to `Variant`. The function's signature is
743/// expected to be `fn(&T) -> Variant`, although it can be generic over `T`.
744///
745/// - `#[variant(from_variant_with = "path::to::func")]`
746///
747/// Use the given function to convert from a `Variant`. The function's signature is
748/// expected to be `fn(&Variant) -> Result<T, FromVariantError>`, although it can be generic
749/// over `T`.
750///
751/// - `#[variant(with = "path::to::mod")]`
752///
753/// Convenience attribute that sets `to_variant_with` to `path::to::mod::to_variant` and
754/// `from_variant_with` to `path::to::mod::from_variant`.
755///
756/// - `#[variant(skip_to_variant)]`
757///
758/// Skip the field when converting to `Variant`.
759///
760/// - `#[variant(skip_from_variant)]`
761///
762/// Skip the field when converting from `Variant`. A default vale will be obtained using
763/// `Default::default()`.
764///
765/// - `#[variant(skip)]`
766///
767/// Convenience attribute that sets `skip_to_variant` and `skip_from_variant`.
768pub trait ToVariant {
769    fn to_variant(&self) -> Variant;
770}
771
772/// Types that can only be safely converted to a `Variant` as owned values. Such types cannot
773/// implement `ToVariant` in general, but can still be passed to API methods as arguments, or
774/// used as return values. Notably, this includes `Unique` arrays, dictionaries, and references
775/// to Godot objects and instances.
776///
777/// This has a blanket implementation for all types that have `ToVariant`. As such, users
778/// should only derive or implement `OwnedToVariant` when `ToVariant` is not applicable.
779///
780/// This trait is used for return types of exported methods.
781///
782/// ## Deriving `OwnedToVariant`
783///
784/// The derive macro behaves the same as `ToVariant`. See the documentation for the latter for
785/// a detailed explanation.
786pub trait OwnedToVariant {
787    fn owned_to_variant(self) -> Variant;
788}
789
790/// Trait for types whose `ToVariant` implementations preserve equivalence.
791///
792/// This means that for all values `a` and `b`, `a == b` is equivalent to
793/// `a.to_variant() == b.to_variant()`. Most of the time, this means that `to_variant` must
794/// return a "value" type, such as a primitive `i32`, a `GodotString`, or a `PoolArray`.
795///
796/// This is mostly useful as a bound for `Dictionary` keys, where the difference between Rust's
797/// structural equality and Godot's referential equality semantics can lead to surprising
798/// behaviors.
799///
800/// This property cannot be checked by the compiler, so `ToVariantEq` has no extra methods.
801///
802/// ## Implementing `ToVariantEq`
803///
804/// The `ToVariantEq` trait is not derivable, because most derived implementations of
805/// `ToVariant` don't satisfy the requirements. If you are sure that your type satisfies the
806/// trait, specify that your type implements it with an empty `impl`:
807///
808/// ```ignore
809/// #[derive(Eq, PartialEq, ToVariant)]
810/// struct MyTypedInt(i32);
811///
812/// impl ToVariantEq for MyTypedInt {}
813/// ```
814pub trait ToVariantEq: Eq {}
815
816/// Types that can be converted from a `Variant`. Conversions are performed in Rust, and can be
817/// implemented for custom types.
818///
819/// [`FromVariant`] generally avoids inexact conversions, favoring returning an error instead,
820/// with the noted exception of integer and float types that are not supported by Godot natively.
821/// This is stricter than what GDScript performs by default. For weakly-typed coercions of GDScript
822/// built-in typed, see [`CoerceFromVariant`] instead.
823///
824/// This trait is used for argument types of exported methods.
825///
826/// ## `Option<T>` and `MaybeNot<T>`
827///
828/// `Option<T>` requires the Variant to be `T` or `Nil`, in that order. For looser semantics,
829/// use `MaybeNot<T>`, which will catch all variant values that are not `T` as well.
830///
831/// ## `Vec<T>`
832///
833/// The `FromVariant` implementation for `Vec<T>` only allow homogeneous arrays. If you want to
834/// manually handle potentially heterogeneous values e.g. for error reporting, use `VariantArray`
835/// directly or compose with an appropriate wrapper: `Vec<Option<T>>` or `Vec<MaybeNot<T>>`.
836///
837/// ## Deriving `FromVariant`
838///
839/// The derive macro provides implementation consistent with derived `ToVariant`. See `ToVariant`
840/// for detailed documentation.
841pub trait FromVariant: Sized {
842    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError>;
843}
844
845/// Types that can be coerced from a `Variant`. Coercions are provided by Godot, with results
846/// consistent with GDScript. This cannot be implemented for custom types.
847///
848/// [`CoerceFromVariant`] exposes what Godot presents as "best-effort" conversions. These are
849/// weakly-typed conversions to GDScript built-in types, that will never fail, but can return
850/// empty or "default" values, as defined by Godot.
851///
852/// For strongly-typed conversions that can be implemented or derived for custom types, see
853/// [`FromVariant`].
854pub trait CoerceFromVariant: Sized + private::Sealed {
855    fn coerce_from_variant(variant: &Variant) -> Self;
856}
857
858#[derive(Clone, PartialEq, Eq, Debug)]
859/// Error type returned by `FromVariant::from_variant`.
860pub enum FromVariantError {
861    /// An unspecified error.
862    Unspecified,
863    /// A custom error message.
864    Custom(String),
865    /// Null value given for a non-nullable type, with no further information given.
866    InvalidNil,
867    /// Variant type is different from the expected one.
868    InvalidVariantType {
869        variant_type: VariantType,
870        expected: VariantType,
871    },
872    /// Cannot cast the object to the given Godot class.
873    CannotCast { class: String, to: &'static str },
874    /// Length of the collection is different from the expected one.
875    InvalidLength { len: usize, expected: usize },
876    /// Invalid enum representation.
877    InvalidEnumRepr {
878        expected: VariantEnumRepr,
879        error: Box<FromVariantError>,
880    },
881    /// Invalid struct representation.
882    InvalidStructRepr {
883        expected: VariantStructRepr,
884        error: Box<FromVariantError>,
885    },
886
887    /// Error indicating that the implementation encountered an enum variant that does not exist
888    /// at compile time.
889    ///
890    /// For example, trying to create a `Result<T, E>` from `{ "Foo": "Bar" }` will result in this
891    /// error, since `Foo` is not a valid variant of `Result`.
892    UnknownEnumVariant {
893        /// Name of the unknown variant
894        variant: String,
895        /// Names of all expected variants known at compile time
896        expected: &'static [&'static str],
897    },
898
899    /// Error indicating that the implementation encountered a known enum variant, but the value
900    /// is invalid for the definition.
901    ///
902    /// This could result from multiple underlying reasons, detailed in the `error` field:
903    ///
904    /// - Missing fields.
905    /// - Unexpected representation, e.g. `{ "0": "foo", "1": "bar" }` for a tuple.
906    /// - Error in a nested field.
907    InvalidEnumVariant {
908        variant: &'static str,
909        error: Box<FromVariantError>,
910    },
911
912    /// Given object is not an instance of the expected NativeClass.
913    InvalidInstance { expected: Cow<'static, str> },
914    /// Collection contains an invalid field.
915    InvalidField {
916        field_name: &'static str,
917        error: Box<FromVariantError>,
918    },
919    /// Collection contains an invalid item.
920    InvalidItem {
921        index: usize,
922        error: Box<FromVariantError>,
923    },
924}
925
926#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
927pub enum VariantEnumRepr {
928    ExternallyTagged,
929}
930
931#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
932pub enum VariantStructRepr {
933    Unit,
934    Tuple,
935    Struct,
936}
937
938impl FromVariantError {
939    /// Returns a `FromVariantError` with a custom message.
940    #[inline]
941    pub fn custom<T: fmt::Display>(message: T) -> Self {
942        FromVariantError::Custom(format!("{message}"))
943    }
944}
945
946impl fmt::Display for FromVariantError {
947    #[inline]
948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
949        use FromVariantError as E;
950
951        match self {
952            E::Unspecified => write!(f, "unspecified error"),
953            E::Custom(s) => write!(f, "{s}"),
954            E::InvalidNil => write!(f, "expected non-nullable type, got null"),
955            E::InvalidVariantType {
956                variant_type,
957                expected,
958            } => write!(
959                f,
960                "invalid variant type: expected {expected:?}, got {variant_type:?}"
961            ),
962            E::CannotCast { class, to } => {
963                write!(f, "cannot cast object of class {class} to {to}")
964            }
965            E::InvalidLength { len, expected } => {
966                write!(f, "expected collection of length {expected}, got {len}")
967            }
968            E::InvalidEnumRepr { expected, error } => write!(
969                f,
970                "invalid enum representation: expected {expected:?}, {error}"
971            ),
972            E::InvalidStructRepr { expected, error } => write!(
973                f,
974                "invalid struct representation: expected {expected:?}, {error}"
975            ),
976            E::UnknownEnumVariant { variant, expected } => {
977                write!(f, "unknown enum variant {variant}, expected variants are: ")?;
978                let mut first = true;
979                for v in *expected {
980                    if first {
981                        first = false;
982                    } else {
983                        write!(f, ", ")?;
984                    }
985                    write!(f, "{v}")?;
986                }
987                Ok(())
988            }
989            E::InvalidEnumVariant { variant, error } => {
990                write!(f, "invalid value for variant {variant}: {error}")
991            }
992            E::InvalidInstance { expected } => {
993                write!(f, "object is not an instance of `NativeClass` {expected}")
994            }
995            E::InvalidField { field_name, error } => {
996                write!(f, "invalid value for field {field_name}")?;
997
998                let mut next_error = error.as_ref();
999                loop {
1000                    match next_error {
1001                        E::InvalidField { field_name, error } => {
1002                            write!(f, ".{field_name}")?;
1003                            next_error = error.as_ref();
1004                        }
1005                        E::InvalidItem { index, error } => {
1006                            write!(f, "[{index}]")?;
1007                            next_error = error.as_ref();
1008                        }
1009                        _ => {
1010                            write!(f, ": {next_error}")?;
1011                            return Ok(());
1012                        }
1013                    }
1014                }
1015            }
1016            E::InvalidItem { index, error } => {
1017                write!(f, "invalid value for item at index {index}: {error}")
1018            }
1019        }
1020    }
1021}
1022
1023impl std::error::Error for FromVariantError {}
1024
1025impl<T: ToVariant> OwnedToVariant for T {
1026    #[inline]
1027    fn owned_to_variant(self) -> Variant {
1028        self.to_variant()
1029    }
1030}
1031
1032impl ToVariant for () {
1033    #[inline]
1034    fn to_variant(&self) -> Variant {
1035        Variant::nil()
1036    }
1037}
1038impl ToVariantEq for () {}
1039
1040impl FromVariant for () {
1041    #[inline]
1042    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1043        if variant.is_nil() {
1044            return Ok(());
1045        }
1046
1047        Err(FromVariantError::InvalidVariantType {
1048            variant_type: variant.get_type(),
1049            expected: VariantType::Nil,
1050        })
1051    }
1052}
1053
1054impl<'a, T> ToVariant for &'a T
1055where
1056    T: ToVariant + ?Sized,
1057{
1058    #[inline]
1059    fn to_variant(&self) -> Variant {
1060        T::to_variant(*self)
1061    }
1062}
1063impl<'a, T> ToVariantEq for &'a T where T: ToVariantEq + ?Sized {}
1064
1065impl ToVariantEq for Variant {}
1066
1067impl<'a, T> ToVariant for &'a mut T
1068where
1069    T: ToVariant + ?Sized,
1070{
1071    #[inline]
1072    fn to_variant(&self) -> Variant {
1073        T::to_variant(*self)
1074    }
1075}
1076impl<'a, T> ToVariantEq for &'a mut T where T: ToVariantEq + ?Sized {}
1077
1078impl<T: GodotObject> ToVariant for Ref<T, Shared> {
1079    #[inline]
1080    fn to_variant(&self) -> Variant {
1081        unsafe { Variant::from_object_ptr(self.as_ptr()) }
1082    }
1083}
1084
1085impl<T: GodotObject> OwnedToVariant for Ref<T, Unique> {
1086    #[inline]
1087    fn owned_to_variant(self) -> Variant {
1088        unsafe { Variant::from_object_ptr(self.as_ptr()) }
1089    }
1090}
1091
1092impl<'a, T: GodotObject> ToVariant for TRef<'a, T, Shared> {
1093    #[inline]
1094    fn to_variant(&self) -> Variant {
1095        unsafe { Variant::from_object_ptr(self.as_ptr()) }
1096    }
1097}
1098
1099impl<T: GodotObject> FromVariant for Ref<T, Shared> {
1100    #[inline]
1101    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1102        variant.try_to_object::<T>()
1103    }
1104}
1105
1106macro_rules! from_variant_direct {
1107    (
1108        $(
1109            impl FromVariant for $TryType:ident : VariantType :: $VarType:ident => $try_gd_method:ident;
1110        )*
1111    ) => (
1112        $(
1113            impl FromVariant for $TryType {
1114                #[inline]
1115                fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1116                    variant.try_as_sys_of_type(VariantType::$VarType)
1117                        .map(|v| unsafe { (get_api().$try_gd_method)(v) })
1118                }
1119            }
1120        )*
1121    );
1122}
1123
1124from_variant_direct!(
1125    impl FromVariant for f64 : VariantType::F64 => godot_variant_as_real;
1126    impl FromVariant for i64 : VariantType::I64 => godot_variant_as_int;
1127    impl FromVariant for u64 : VariantType::I64 => godot_variant_as_uint;
1128    impl FromVariant for bool : VariantType::Bool => godot_variant_as_bool;
1129);
1130
1131impl ToVariant for i64 {
1132    #[inline]
1133    fn to_variant(&self) -> Variant {
1134        unsafe {
1135            let api = get_api();
1136            let mut dest = sys::godot_variant::default();
1137            (api.godot_variant_new_int)(&mut dest, *self);
1138            Variant(dest)
1139        }
1140    }
1141}
1142impl ToVariantEq for i64 {}
1143
1144impl ToVariant for u64 {
1145    #[inline]
1146    fn to_variant(&self) -> Variant {
1147        unsafe {
1148            let api = get_api();
1149            let mut dest = sys::godot_variant::default();
1150            (api.godot_variant_new_uint)(&mut dest, *self);
1151            Variant(dest)
1152        }
1153    }
1154}
1155impl ToVariantEq for u64 {}
1156
1157impl ToVariant for bool {
1158    #[inline]
1159    fn to_variant(&self) -> Variant {
1160        unsafe {
1161            let api = get_api();
1162            let mut dest = sys::godot_variant::default();
1163            (api.godot_variant_new_bool)(&mut dest, *self);
1164            Variant(dest)
1165        }
1166    }
1167}
1168impl ToVariantEq for bool {}
1169
1170impl ToVariant for f64 {
1171    #[inline]
1172    fn to_variant(&self) -> Variant {
1173        unsafe {
1174            let api = get_api();
1175            let mut ret = sys::godot_variant::default();
1176            (api.godot_variant_new_real)(&mut ret, *self);
1177            Variant(ret)
1178        }
1179    }
1180}
1181
1182macro_rules! impl_to_variant_for_num {
1183    (
1184        $($ty:ty : $src_ty:ty)*
1185    ) => {
1186        $(
1187            impl ToVariant for $ty {
1188                #[inline]
1189                fn to_variant(&self) -> Variant {
1190                    ((*self) as $src_ty).to_variant()
1191                }
1192            }
1193
1194            impl private::Sealed for $ty {}
1195            impl CoerceFromVariant for $ty {
1196                #[inline]
1197                fn coerce_from_variant(variant: &Variant) -> Self {
1198                    <$src_ty>::coerce_from_variant(variant) as Self
1199                }
1200            }
1201
1202            impl FromVariant for $ty {
1203                #[inline]
1204                fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1205                    <$src_ty>::from_variant(variant).map(|i| i as Self)
1206                }
1207            }
1208        )*
1209    };
1210}
1211
1212impl_to_variant_for_num!(
1213    i8: i64
1214    i16: i64
1215    i32: i64
1216    isize: i64
1217    u8: u64
1218    u16: u64
1219    u32: u64
1220    usize: u64
1221    f32: f64
1222);
1223
1224impl ToVariantEq for i8 {}
1225impl ToVariantEq for i16 {}
1226impl ToVariantEq for i32 {}
1227impl ToVariantEq for isize {}
1228impl ToVariantEq for u8 {}
1229impl ToVariantEq for u16 {}
1230impl ToVariantEq for u32 {}
1231impl ToVariantEq for usize {}
1232
1233macro_rules! to_variant_transmute {
1234    (
1235        $(impl ToVariant for $ty:ident: $ctor:ident;)*
1236    ) => {
1237        $(
1238            impl ToVariant for $ty {
1239                #[inline]
1240                fn to_variant(&self) -> Variant {
1241                    unsafe {
1242                        let api = get_api();
1243                        let mut dest = sys::godot_variant::default();
1244                        #[allow(clippy::useless_transmute)]
1245                        (api.$ctor)(&mut dest, transmute(self));
1246                        Variant::from_sys(dest)
1247                    }
1248                }
1249            }
1250        )*
1251    }
1252}
1253
1254to_variant_transmute! {
1255    impl ToVariant for Vector2 : godot_variant_new_vector2;
1256    impl ToVariant for Vector3 : godot_variant_new_vector3;
1257    impl ToVariant for Quat : godot_variant_new_quat;
1258    impl ToVariant for Rect2 : godot_variant_new_rect2;
1259    impl ToVariant for Transform2D : godot_variant_new_transform2d;
1260}
1261
1262macro_rules! to_variant_as_sys {
1263    (
1264        $(impl ToVariant for $ty:ty: $ctor:ident;)*
1265    ) => {
1266        $(
1267            impl ToVariant for $ty {
1268                #[inline]
1269                fn to_variant(&self) -> Variant {
1270                    unsafe {
1271                        let api = get_api();
1272                        let mut dest = sys::godot_variant::default();
1273                        (api.$ctor)(&mut dest, self.sys());
1274                        Variant::from_sys(dest)
1275                    }
1276                }
1277            }
1278        )*
1279    }
1280}
1281
1282to_variant_as_sys! {
1283    impl ToVariant for Plane : godot_variant_new_plane;
1284    impl ToVariant for Transform : godot_variant_new_transform;
1285    impl ToVariant for Basis : godot_variant_new_basis;
1286    impl ToVariant for Color : godot_variant_new_color;
1287    impl ToVariant for Aabb : godot_variant_new_aabb;
1288    impl ToVariant for Rid : godot_variant_new_rid;
1289    impl ToVariant for NodePath : godot_variant_new_node_path;
1290    impl ToVariant for GodotString : godot_variant_new_string;
1291    impl ToVariant for VariantArray<Shared> : godot_variant_new_array;
1292    impl ToVariant for Dictionary<Shared> : godot_variant_new_dictionary;
1293}
1294
1295impl ToVariantEq for Rid {}
1296impl ToVariantEq for NodePath {}
1297impl ToVariantEq for GodotString {}
1298
1299impl OwnedToVariant for Dictionary<Unique> {
1300    #[inline]
1301    fn owned_to_variant(self) -> Variant {
1302        self.into_shared().to_variant()
1303    }
1304}
1305
1306impl OwnedToVariant for VariantArray<Unique> {
1307    #[inline]
1308    fn owned_to_variant(self) -> Variant {
1309        self.into_shared().to_variant()
1310    }
1311}
1312
1313macro_rules! from_variant_transmute {
1314    (
1315        $(
1316            impl FromVariant for $TryType:ident : $try_gd_method:ident;
1317        )*
1318    ) => (
1319        $(
1320            impl FromVariant for $TryType {
1321                #[inline]
1322                fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1323                    unsafe {
1324                        variant.try_as_sys_of_type(VariantType::$TryType)
1325                            .map(|v| (get_api().$try_gd_method)(v))
1326                            .map(|v| transmute(v))
1327                    }
1328                }
1329            }
1330        )*
1331    );
1332}
1333
1334from_variant_transmute!(
1335    impl FromVariant for Vector2 : godot_variant_as_vector2;
1336    impl FromVariant for Vector3 : godot_variant_as_vector3;
1337    impl FromVariant for Quat : godot_variant_as_quat;
1338    impl FromVariant for Rect2 : godot_variant_as_rect2;
1339    impl FromVariant for Transform2D : godot_variant_as_transform2d;
1340);
1341
1342macro_rules! from_variant_from_sys {
1343    (
1344        $(
1345            impl FromVariant for $TryType:ty as $EnumVar:ident : $try_gd_method:ident;
1346        )*
1347    ) => (
1348        $(
1349            impl FromVariant for $TryType {
1350                #[inline]
1351                fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1352                    unsafe {
1353                        variant.try_as_sys_of_type(VariantType::$EnumVar)
1354                            .map(|v| (get_api().$try_gd_method)(v))
1355                            .map(<$TryType>::from_sys)
1356                    }
1357                }
1358            }
1359        )*
1360    );
1361}
1362
1363from_variant_from_sys!(
1364    impl FromVariant for Plane as Plane : godot_variant_as_plane;
1365    impl FromVariant for Transform as Transform : godot_variant_as_transform;
1366    impl FromVariant for Basis as Basis : godot_variant_as_basis;
1367    impl FromVariant for Color as Color : godot_variant_as_color;
1368    impl FromVariant for Aabb as Aabb : godot_variant_as_aabb;
1369    impl FromVariant for NodePath as NodePath : godot_variant_as_node_path;
1370    impl FromVariant for GodotString as GodotString: godot_variant_as_string;
1371    impl FromVariant for Rid as Rid : godot_variant_as_rid;
1372    impl FromVariant for VariantArray<Shared> as VariantArray : godot_variant_as_array;
1373    impl FromVariant for Dictionary<Shared> as Dictionary : godot_variant_as_dictionary;
1374);
1375
1376impl<T: crate::core_types::PoolElement> ToVariant for PoolArray<T> {
1377    #[inline]
1378    fn to_variant(&self) -> Variant {
1379        unsafe {
1380            let api = get_api();
1381            let mut dest = sys::godot_variant::default();
1382            (T::array_to_variant_fn(api))(&mut dest, self.sys());
1383            Variant::from_sys(dest)
1384        }
1385    }
1386}
1387impl<T: crate::core_types::PoolElement + Eq> ToVariantEq for PoolArray<T> {}
1388
1389impl<T: crate::core_types::PoolElement> FromVariant for PoolArray<T> {
1390    #[inline]
1391    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1392        unsafe {
1393            variant
1394                .try_as_sys_of_type(VariantType::from_sys(T::SYS_VARIANT_TYPE))
1395                .map(|v| (T::array_from_variant_fn(get_api()))(v))
1396                .map(Self::from_sys)
1397        }
1398    }
1399}
1400
1401impl ToVariant for str {
1402    #[inline]
1403    fn to_variant(&self) -> Variant {
1404        GodotString::from_str(self).owned_to_variant()
1405    }
1406}
1407impl ToVariantEq for str {}
1408
1409impl ToVariant for String {
1410    #[inline]
1411    fn to_variant(&self) -> Variant {
1412        self.as_str().to_variant()
1413    }
1414}
1415impl ToVariantEq for String {}
1416
1417impl FromVariant for String {
1418    #[inline]
1419    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1420        GodotString::from_variant(variant).map(|s| s.to_string())
1421    }
1422}
1423
1424impl ToVariant for Variant {
1425    #[inline]
1426    fn to_variant(&self) -> Variant {
1427        self.clone()
1428    }
1429}
1430
1431impl FromVariant for Variant {
1432    #[inline]
1433    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1434        Ok(variant.clone())
1435    }
1436}
1437
1438impl<T> ToVariant for std::marker::PhantomData<T> {
1439    #[inline]
1440    fn to_variant(&self) -> Variant {
1441        Variant::nil()
1442    }
1443}
1444impl<T> ToVariantEq for std::marker::PhantomData<T> {}
1445
1446impl<T> FromVariant for std::marker::PhantomData<T> {
1447    #[inline]
1448    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1449        if variant.is_nil() {
1450            return Ok(std::marker::PhantomData);
1451        }
1452
1453        Err(FromVariantError::InvalidVariantType {
1454            variant_type: variant.get_type(),
1455            expected: VariantType::Nil,
1456        })
1457    }
1458}
1459
1460impl<T: ToVariant> ToVariant for Option<T> {
1461    #[inline]
1462    fn to_variant(&self) -> Variant {
1463        match &self {
1464            Some(thing) => thing.to_variant(),
1465            None => Variant::nil(),
1466        }
1467    }
1468}
1469impl<T: ToVariantEq> ToVariantEq for Option<T> {}
1470
1471impl<T: FromVariant> FromVariant for Option<T> {
1472    #[inline]
1473    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1474        T::from_variant(variant).map(Some).or_else(
1475            |e| {
1476                if variant.is_nil() {
1477                    Ok(None)
1478                } else {
1479                    Err(e)
1480                }
1481            },
1482        )
1483    }
1484}
1485
1486/// Wrapper type around a `FromVariant` result that may not be a success
1487#[derive(Clone, Debug)]
1488pub struct MaybeNot<T>(Result<T, Variant>);
1489
1490impl<T: FromVariant> FromVariant for MaybeNot<T> {
1491    #[inline]
1492    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1493        Ok(MaybeNot(
1494            T::from_variant(variant).map_err(|_| variant.clone()),
1495        ))
1496    }
1497}
1498
1499impl<T> MaybeNot<T> {
1500    #[inline]
1501    pub fn into_result(self) -> Result<T, Variant> {
1502        self.0
1503    }
1504
1505    #[inline]
1506    pub fn as_ref(&self) -> Result<&T, &Variant> {
1507        self.0.as_ref()
1508    }
1509
1510    #[inline]
1511    pub fn as_mut(&mut self) -> Result<&mut T, &mut Variant> {
1512        self.0.as_mut()
1513    }
1514
1515    #[inline]
1516    pub fn cloned(&self) -> Result<T, Variant>
1517    where
1518        T: Clone,
1519    {
1520        self.0.clone()
1521    }
1522
1523    #[inline]
1524    pub fn ok(self) -> Option<T> {
1525        self.0.ok()
1526    }
1527}
1528
1529impl<T: ToVariant, E: ToVariant> ToVariant for Result<T, E> {
1530    #[inline]
1531    fn to_variant(&self) -> Variant {
1532        let dict = Dictionary::new();
1533        match &self {
1534            Ok(val) => dict.insert("Ok", val),
1535            Err(err) => dict.insert("Err", err),
1536        }
1537        dict.into_shared().to_variant()
1538    }
1539}
1540
1541impl<T: FromVariant, E: FromVariant> FromVariant for Result<T, E> {
1542    #[inline]
1543    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1544        use FromVariantError as FVE;
1545
1546        let dict = Dictionary::from_variant(variant).map_err(|err| FVE::InvalidEnumRepr {
1547            expected: VariantEnumRepr::ExternallyTagged,
1548            error: Box::new(err),
1549        })?;
1550
1551        if dict.len() != 1 {
1552            return Err(FVE::InvalidEnumRepr {
1553                expected: VariantEnumRepr::ExternallyTagged,
1554                error: Box::new(FVE::InvalidLength {
1555                    expected: 1,
1556                    len: dict.len() as usize,
1557                }),
1558            });
1559        }
1560
1561        let keys = dict.keys();
1562        let key_variant = &keys.get(0);
1563        let key = String::from_variant(key_variant).map_err(|err| FVE::InvalidEnumRepr {
1564            expected: VariantEnumRepr::ExternallyTagged,
1565            error: Box::new(err),
1566        })?;
1567
1568        match key.as_str() {
1569            "Ok" => {
1570                let val = T::from_variant(&dict.get_or_nil(key_variant)).map_err(|err| {
1571                    FVE::InvalidEnumVariant {
1572                        variant: "Ok",
1573                        error: Box::new(err),
1574                    }
1575                })?;
1576                Ok(Ok(val))
1577            }
1578            "Err" => {
1579                let err = E::from_variant(&dict.get_or_nil(key_variant)).map_err(|err| {
1580                    FVE::InvalidEnumVariant {
1581                        variant: "Err",
1582                        error: Box::new(err),
1583                    }
1584                })?;
1585                Ok(Err(err))
1586            }
1587            variant => Err(FVE::UnknownEnumVariant {
1588                variant: variant.to_string(),
1589                expected: &["Ok", "Err"],
1590            }),
1591        }
1592    }
1593}
1594
1595impl<T: ToVariant> ToVariant for &[T] {
1596    #[inline]
1597    fn to_variant(&self) -> Variant {
1598        let array = VariantArray::new();
1599        for val in self.iter() {
1600            // there is no real way to avoid CoW allocations right now, as ptrw isn't exposed
1601            array.push(&val.to_variant());
1602        }
1603        array.into_shared().to_variant()
1604    }
1605}
1606
1607impl<T: ToVariant> ToVariant for Vec<T> {
1608    #[inline]
1609    fn to_variant(&self) -> Variant {
1610        self.as_slice().to_variant()
1611    }
1612}
1613
1614impl<T: FromVariant> FromVariant for Vec<T> {
1615    #[inline]
1616    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1617        let arr = VariantArray::from_variant(variant)?;
1618        let len: usize = arr
1619            .len()
1620            .try_into()
1621            .expect("variant array length should fit in usize");
1622        let mut vec = Vec::with_capacity(len);
1623        for idx in 0..len as i32 {
1624            let item =
1625                T::from_variant(&arr.get(idx)).map_err(|e| FromVariantError::InvalidItem {
1626                    index: idx as usize,
1627                    error: Box::new(e),
1628                })?;
1629            vec.push(item);
1630        }
1631        Ok(vec)
1632    }
1633}
1634
1635/// Converts the hash map to a `Dictionary`, wrapped in a `Variant`.
1636///
1637/// Note that Rust's `HashMap` is non-deterministically ordered for security reasons, meaning that
1638/// the order of the same elements will differ between two program invocations. To provide a
1639/// deterministic output in Godot (e.g. UI elements for properties), the elements are sorted by key.
1640impl<K: ToVariant + Hash + ToVariantEq, V: ToVariant> ToVariant for HashMap<K, V> {
1641    #[inline]
1642    fn to_variant(&self) -> Variant {
1643        // Note: dictionary currently provides neither a sort() function nor random access (or at least bidirectional)
1644        // iterators, making it difficult to sort in-place. Workaround: copy to vector
1645
1646        let mut intermediate: Vec<(Variant, Variant)> = self
1647            .iter()
1648            .map(|(k, v)| (k.to_variant(), v.to_variant()))
1649            .collect();
1650
1651        intermediate.sort();
1652
1653        let dict = Dictionary::new();
1654        for (key, value) in intermediate.into_iter() {
1655            dict.insert(key, value);
1656        }
1657
1658        dict.owned_to_variant()
1659    }
1660}
1661
1662/// Expects a `Variant` populated with a `Dictionary` and tries to convert it into a `HashMap`.
1663///
1664/// Since Rust's `HashMap` is unordered, there is no guarantee about the resulting element order.
1665/// In fact it is possible that two program invocations cause a different output.
1666impl<K: FromVariant + Hash + Eq, V: FromVariant> FromVariant for HashMap<K, V> {
1667    #[inline]
1668    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1669        let dictionary = Dictionary::from_variant(variant)?;
1670        let len: usize = dictionary
1671            .len()
1672            .try_into()
1673            .expect("Dictionary length should fit in usize");
1674
1675        let mut hash_map = HashMap::with_capacity(len);
1676        for (key, value) in dictionary.iter() {
1677            hash_map.insert(K::from_variant(&key)?, V::from_variant(&value)?);
1678        }
1679        Ok(hash_map)
1680    }
1681}
1682
1683/// Converts the hash set to a `VariantArray`, wrapped in a `Variant`.
1684///
1685/// Note that Rust's `HashSet` is non-deterministically ordered for security reasons, meaning that
1686/// the order of the same elements will differ between two program invocations. To provide a
1687/// deterministic output in Godot (e.g. UI elements for properties), the elements are sorted by key.
1688impl<T: ToVariant> ToVariant for HashSet<T> {
1689    #[inline]
1690    fn to_variant(&self) -> Variant {
1691        let array = VariantArray::new();
1692        for value in self {
1693            array.push(value.to_variant());
1694        }
1695
1696        array.sort(); // deterministic order in Godot
1697        array.owned_to_variant()
1698    }
1699}
1700
1701/// Expects a `Variant` populated with a `VariantArray` and tries to convert it into a `HashSet`.
1702///
1703/// Since Rust's `HashSet` is unordered, there is no guarantee about the resulting element order.
1704/// In fact it is possible that two program invocations cause a different output.
1705impl<T: FromVariant + Eq + Hash> FromVariant for HashSet<T> {
1706    #[inline]
1707    fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
1708        let arr = VariantArray::from_variant(variant)?;
1709        let len: usize = arr
1710            .len()
1711            .try_into()
1712            .expect("VariantArray length should fit in usize");
1713
1714        let mut set = HashSet::with_capacity(len);
1715        for idx in 0..len as i32 {
1716            let item =
1717                T::from_variant(&arr.get(idx)).map_err(|e| FromVariantError::InvalidItem {
1718                    index: idx as usize,
1719                    error: Box::new(e),
1720                })?;
1721            set.insert(item);
1722        }
1723        Ok(set)
1724    }
1725}
1726
1727macro_rules! tuple_length {
1728    () => { 0usize };
1729    ($_x:ident, $($xs:ident,)*) => {
1730        1usize + tuple_length!($($xs,)*)
1731    };
1732}
1733
1734macro_rules! impl_variant_for_tuples_next {
1735    ($_x:ident, $($xs:ident,)*) => {
1736        impl_variant_for_tuples!($($xs,)*);
1737    }
1738}
1739
1740macro_rules! impl_variant_for_tuples {
1741    () => {};
1742    ( $($name:ident,)+ ) => {
1743        impl<$($name: ToVariant,)+> ToVariant for ($($name,)+) {
1744            #[allow(non_snake_case)]
1745            #[inline]
1746            fn to_variant(&self) -> Variant {
1747                let array = VariantArray::new();
1748                let ($($name,)+) = self;
1749                $(
1750                    array.push(&$name.to_variant());
1751                )+
1752                array.into_shared().to_variant()
1753            }
1754        }
1755
1756        impl<$($name: FromVariant,)+> FromVariant for ($($name,)+) {
1757            #[allow(non_snake_case, unused_assignments)]
1758            #[inline]
1759            fn from_variant(v: &Variant) -> Result<Self, FromVariantError> {
1760                let array = VariantArray::from_variant(v)?;
1761                let expected = tuple_length!($($name,)+);
1762                let len = array.len() as usize;
1763                if len != expected {
1764                    return Err(FromVariantError::InvalidLength { expected, len });
1765                }
1766
1767                let mut iter = array.iter();
1768                let mut index = 0;
1769                $(
1770                    let $name = $name::from_variant(&iter.next().unwrap())
1771                        .map_err(|err| FromVariantError::InvalidItem {
1772                            index,
1773                            error: Box::new(err),
1774                        })?;
1775                    index += 1;
1776                )+
1777
1778                Ok(($($name,)+))
1779            }
1780        }
1781
1782        impl_variant_for_tuples_next!($($name,)+);
1783    };
1784}
1785
1786impl_variant_for_tuples!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,);
1787
1788mod private {
1789    pub trait Sealed {}
1790}
1791
1792godot_test!(
1793    test_variant_option {
1794        use std::marker::PhantomData;
1795
1796        let variant = Some(42_i64).to_variant();
1797        assert_eq!(Ok(42), variant.try_to::<i64>());
1798
1799        let variant = Option::<bool>::None.to_variant();
1800        assert!(variant.is_nil());
1801
1802        let variant = Variant::nil();
1803        assert_eq!(Ok(None), Option::<i64>::from_variant(&variant));
1804        assert_eq!(Ok(None), Option::<bool>::from_variant(&variant));
1805        assert_eq!(Ok(None), Option::<String>::from_variant(&variant));
1806
1807        let variant = Variant::new(42);
1808        assert_eq!(Ok(Some(42)), Option::<i64>::from_variant(&variant));
1809        assert!(Option::<bool>::from_variant(&variant).is_err());
1810        assert!(Option::<String>::from_variant(&variant).is_err());
1811
1812        let variant = Variant::nil();
1813        assert_eq!(Ok(Some(())), Option::<()>::from_variant(&variant));
1814        assert_eq!(Ok(Some(PhantomData)), Option::<PhantomData<*const u8>>::from_variant(&variant));
1815
1816        let variant = Variant::new(42);
1817        assert!(Option::<PhantomData<*const u8>>::from_variant(&variant).is_err());
1818    }
1819
1820    test_variant_result {
1821        let variant = Result::<i64, ()>::Ok(42_i64).to_variant();
1822        let dict = variant.try_to::<Dictionary>().expect("should be dic");
1823        assert_eq!(Some(42), dict.get("Ok").and_then(|v| v.try_to::<i64>().ok()));
1824
1825        let variant = Result::<(), i64>::Err(54_i64).to_variant();
1826        let dict = variant.try_to::<Dictionary>().expect("should be dic");
1827        assert_eq!(Some(54), dict.get("Err").and_then(|v| v.try_to::<i64>().ok()));
1828
1829        let variant = Variant::new(true);
1830        assert_eq!(
1831            Err(FromVariantError::InvalidEnumRepr {
1832                expected: VariantEnumRepr::ExternallyTagged,
1833                error: Box::new(FromVariantError::InvalidVariantType {
1834                    expected: VariantType::Dictionary,
1835                    variant_type: VariantType::Bool,
1836                }),
1837            }),
1838            Result::<(), i64>::from_variant(&variant),
1839        );
1840
1841        let dict = Dictionary::new();
1842        dict.insert("Ok", 42);
1843        assert_eq!(Ok(Ok(42)), Result::<i64, i64>::from_variant(&dict.into_shared().to_variant()));
1844
1845        let dict = Dictionary::new();
1846        dict.insert("Err", 54);
1847        assert_eq!(Ok(Err(54)), Result::<i64, i64>::from_variant(&dict.into_shared().to_variant()));
1848    }
1849
1850    test_to_variant_iter {
1851        let slice: &[i64] = &[0, 1, 2, 3, 4];
1852        let variant = slice.to_variant();
1853        let array = variant.try_to::<VariantArray>().expect("should be array");
1854        assert_eq!(5, array.len());
1855        for i in 0..5 {
1856            assert_eq!(Ok(i), array.get(i as i32).try_to::<i64>());
1857        }
1858
1859        let vec = Vec::<i64>::from_variant(&variant).expect("should succeed");
1860        assert_eq!(slice, vec.as_slice());
1861
1862        let het_array = VariantArray::new();
1863        het_array.push(&Variant::new(42));
1864        het_array.push(&Variant::nil());
1865
1866        assert_eq!(
1867            Err(FromVariantError::InvalidItem {
1868                index: 1,
1869                error: Box::new(FromVariantError::InvalidVariantType {
1870                    expected: VariantType::I64,
1871                    variant_type: VariantType::Nil,
1872                }),
1873            }),
1874            Vec::<i64>::from_variant(&het_array.duplicate().into_shared().to_variant()),
1875        );
1876
1877        assert_eq!(Ok(vec![Some(42), None]), Vec::<Option<i64>>::from_variant(&het_array.duplicate().into_shared().to_variant()));
1878
1879        het_array.push(&f64::to_variant(&54.0));
1880
1881        assert_eq!(
1882            Err(FromVariantError::InvalidItem {
1883                index: 2,
1884                error: Box::new(FromVariantError::InvalidVariantType {
1885                    expected: VariantType::I64,
1886                    variant_type: VariantType::F64,
1887                }),
1888            }),
1889            Vec::<Option<i64>>::from_variant(&het_array.duplicate().into_shared().to_variant()),
1890        );
1891
1892        let vec_maybe = Vec::<MaybeNot<i64>>::from_variant(&het_array.into_shared().to_variant()).expect("should succeed");
1893        assert_eq!(3, vec_maybe.len());
1894        assert_eq!(Some(&42), vec_maybe[0].as_ref().ok());
1895        assert_eq!(Some(&Variant::nil()), vec_maybe[1].as_ref().err());
1896        assert_eq!(Some(&f64::to_variant(&54.0)), vec_maybe[2].as_ref().err());
1897    }
1898
1899    test_variant_hash_map {
1900        let original_hash_map = HashMap::from([
1901            ("Foo".to_string(), 4u32),
1902            ("Bar".to_string(), 2u32)
1903        ]);
1904        let variant = original_hash_map.to_variant();
1905        let check_hash_map = variant.try_to::<HashMap<String, u32>>().expect("should be hash map");
1906        assert_eq!(original_hash_map, check_hash_map);
1907        // Check conversion of heterogeneous dictionary key types
1908        let non_homogenous_key_dictonary = Dictionary::new();
1909        non_homogenous_key_dictonary.insert("Foo".to_string(), 4u32);
1910        non_homogenous_key_dictonary.insert(7, 2u32);
1911        assert_eq!(
1912            non_homogenous_key_dictonary.owned_to_variant().try_to::<HashMap<String, u32>>(),
1913            Err(FromVariantError::InvalidVariantType {
1914                variant_type: VariantType::I64,
1915                expected: VariantType::GodotString
1916            }),
1917        );
1918        // Check conversion of heterogeneous dictionary value types
1919        let non_homogenous_value_dictonary = Dictionary::new();
1920        non_homogenous_value_dictonary.insert("Foo".to_string(), 4u32);
1921        non_homogenous_value_dictonary.insert("Bar".to_string(), "Unexpected".to_string());
1922        assert_eq!(
1923            non_homogenous_value_dictonary.owned_to_variant().try_to::<HashMap<String, u32>>(),
1924            Err(FromVariantError::InvalidVariantType {
1925                variant_type: VariantType::GodotString,
1926                expected: VariantType::I64
1927            }),
1928        );
1929    }
1930
1931    test_variant_hash_set {
1932        let original_hash_set = HashSet::from([
1933            "Foo".to_string(),
1934            "Bar".to_string(),
1935        ]);
1936        let variant = original_hash_set.to_variant();
1937        let check_hash_set = variant.try_to::<HashSet<String>>().expect("should be hash set");
1938        assert_eq!(original_hash_set, check_hash_set);
1939
1940        let duplicate_variant_set = VariantArray::new();
1941        duplicate_variant_set.push("Foo".to_string());
1942        duplicate_variant_set.push("Bar".to_string());
1943        duplicate_variant_set.push("Bar".to_string());
1944        let duplicate_hash_set = variant.try_to::<HashSet<String>>().expect("should be hash set");
1945        assert_eq!(original_hash_set, duplicate_hash_set);
1946
1947        // Check conversion of heterogeneous set types
1948        let non_homogenous_set = VariantArray::new();
1949        non_homogenous_set.push("Foo".to_string());
1950        non_homogenous_set.push(7);
1951        assert_eq!(
1952            non_homogenous_set.owned_to_variant().try_to::<HashSet<String>>(),
1953            Err(FromVariantError::InvalidItem {
1954                index: 1,
1955                error: Box::new(FromVariantError::InvalidVariantType {
1956                    variant_type: VariantType::I64,
1957                    expected: VariantType::GodotString
1958                })
1959            }),
1960        );
1961    }
1962
1963    test_variant_vec {
1964        let original_vec = Vec::from([
1965            "Foo".to_string(),
1966            "Bar".to_string(),
1967        ]);
1968        let variant = original_vec.to_variant();
1969        let check_vec = variant.try_to::<Vec<String>>().expect("should be hash set");
1970        assert_eq!(original_vec, check_vec);
1971
1972        // Check conversion of heterogeneous vec types
1973        let non_homogenous_vec = VariantArray::new();
1974        non_homogenous_vec.push("Foo".to_string());
1975        non_homogenous_vec.push(7);
1976        assert_eq!(
1977            non_homogenous_vec.owned_to_variant().try_to::<Vec<String>>(),
1978            Err(FromVariantError::InvalidItem {
1979                index: 1,
1980                error: Box::new(FromVariantError::InvalidVariantType {
1981                    variant_type: VariantType::I64,
1982                    expected: VariantType::GodotString
1983                })
1984            }),
1985        );
1986    }
1987
1988    test_variant_tuple {
1989        let variant = (42i64, 54i64).to_variant();
1990        let arr = variant.try_to::<VariantArray>().expect("should be array");
1991        assert_eq!(Ok(42), arr.get(0).try_to::<i64>());
1992        assert_eq!(Ok(54), arr.get(1).try_to::<i64>());
1993
1994        let tuple = <(i64, i64)>::from_variant(&variant);
1995        assert_eq!(Ok((42, 54)), tuple);
1996    }
1997
1998    test_variant_dispatch {
1999        let variant = 42i64.to_variant();
2000        if let VariantDispatch::I64(i) = variant.dispatch() {
2001            assert_eq!(42, i);
2002        } else {
2003            panic!("incorrect dispatch type");
2004        };
2005
2006        let variant = true.to_variant();
2007        if let VariantDispatch::Bool(b) = variant.dispatch() {
2008            assert!(b);
2009        } else {
2010            panic!("incorrect dispatch type");
2011        };
2012
2013        let variant = 42.to_variant();
2014        let number_as_float = match variant.dispatch() {
2015            VariantDispatch::I64(i) => i as f64,
2016            VariantDispatch::F64(f) => f,
2017            _ => panic!("not a number"),
2018        };
2019        approx::assert_relative_eq!(42.0, number_as_float);
2020    }
2021);