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
18pub 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 pub const NAMES: &'static [&'static str] = &[
93 $(stringify!($variant),)*
94 ];
95 }
96
97 #[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)] #[doc(hidden)]
171 #[inline]
172 pub fn from_sys(v: sys::godot_variant_type) -> VariantType {
173 unsafe { transmute(v as u32) }
174 }
175
176 #[inline]
178 pub const fn name(self) -> &'static str {
179 Self::NAMES[self as usize]
183 }
184}
185
186#[allow(clippy::unnecessary_cast)] #[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)] #[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#[allow(clippy::unnecessary_cast)] #[repr(u32)]
238#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
239pub enum VariantOperator {
240 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 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 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 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 In = sys::godot_variant_operator_GODOT_VARIANT_OP_IN as u32,
274}
275
276#[allow(clippy::unnecessary_cast)] impl 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 unsafe { std::mem::transmute(op) }
296 }
297}
298
299#[derive(Copy, Clone, Eq, PartialEq, Hash, Default, Debug)]
301pub struct InvalidOp;
302
303type Bool = bool;
306
307impl Variant {
308 #[inline]
310 pub fn new<T: OwnedToVariant>(from: T) -> Self {
311 from.owned_to_variant()
312 }
313
314 #[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 #[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 #[inline]
360 pub fn to<T: FromVariant>(&self) -> Option<T> {
361 self.try_to().ok()
362 }
363
364 #[inline]
370 pub fn try_to<T: FromVariant>(&self) -> Result<T, FromVariantError> {
371 T::from_variant(self)
372 }
373
374 #[inline]
382 pub fn coerce_to<T: CoerceFromVariant>(&self) -> T {
383 T::coerce_from_variant(self)
384 }
385
386 #[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 #[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 #[inline]
429 pub fn get_type(&self) -> VariantType {
430 unsafe { VariantType::from_sys((get_api().godot_variant_get_type)(&self.0)) }
431 }
432
433 #[inline]
447 pub fn dispatch(&self) -> VariantDispatch {
448 self.into()
449 }
450
451 #[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 #[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 #[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 #[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 #[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 #[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
700pub trait ToVariant {
769 fn to_variant(&self) -> Variant;
770}
771
772pub trait OwnedToVariant {
787 fn owned_to_variant(self) -> Variant;
788}
789
790pub trait ToVariantEq: Eq {}
815
816pub trait FromVariant: Sized {
842 fn from_variant(variant: &Variant) -> Result<Self, FromVariantError>;
843}
844
845pub trait CoerceFromVariant: Sized + private::Sealed {
855 fn coerce_from_variant(variant: &Variant) -> Self;
856}
857
858#[derive(Clone, PartialEq, Eq, Debug)]
859pub enum FromVariantError {
861 Unspecified,
863 Custom(String),
865 InvalidNil,
867 InvalidVariantType {
869 variant_type: VariantType,
870 expected: VariantType,
871 },
872 CannotCast { class: String, to: &'static str },
874 InvalidLength { len: usize, expected: usize },
876 InvalidEnumRepr {
878 expected: VariantEnumRepr,
879 error: Box<FromVariantError>,
880 },
881 InvalidStructRepr {
883 expected: VariantStructRepr,
884 error: Box<FromVariantError>,
885 },
886
887 UnknownEnumVariant {
893 variant: String,
895 expected: &'static [&'static str],
897 },
898
899 InvalidEnumVariant {
908 variant: &'static str,
909 error: Box<FromVariantError>,
910 },
911
912 InvalidInstance { expected: Cow<'static, str> },
914 InvalidField {
916 field_name: &'static str,
917 error: Box<FromVariantError>,
918 },
919 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 #[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#[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 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
1635impl<K: ToVariant + Hash + ToVariantEq, V: ToVariant> ToVariant for HashMap<K, V> {
1641 #[inline]
1642 fn to_variant(&self) -> Variant {
1643 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
1662impl<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
1683impl<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(); array.owned_to_variant()
1698 }
1699}
1700
1701impl<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 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 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 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 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);