@@ -84,38 +84,89 @@ macro_rules! variant_to_type_from_sys {
84
84
)
85
85
}
86
86
87
- #[ repr( u32 ) ]
88
- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
89
- pub enum VariantType {
90
- Nil = sys:: godot_variant_type_GODOT_VARIANT_TYPE_NIL as u32 ,
91
- Bool = sys:: godot_variant_type_GODOT_VARIANT_TYPE_BOOL as u32 ,
92
- I64 = sys:: godot_variant_type_GODOT_VARIANT_TYPE_INT as u32 ,
93
- F64 = sys:: godot_variant_type_GODOT_VARIANT_TYPE_REAL as u32 ,
94
- GodotString = sys:: godot_variant_type_GODOT_VARIANT_TYPE_STRING as u32 ,
95
- Vector2 = sys:: godot_variant_type_GODOT_VARIANT_TYPE_VECTOR2 as u32 ,
96
- Rect2 = sys:: godot_variant_type_GODOT_VARIANT_TYPE_RECT2 as u32 ,
97
- Vector3 = sys:: godot_variant_type_GODOT_VARIANT_TYPE_VECTOR3 as u32 ,
98
- Transform2D = sys:: godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM2D as u32 ,
99
- Plane = sys:: godot_variant_type_GODOT_VARIANT_TYPE_PLANE as u32 ,
100
- Quat = sys:: godot_variant_type_GODOT_VARIANT_TYPE_QUAT as u32 ,
101
- Aabb = sys:: godot_variant_type_GODOT_VARIANT_TYPE_AABB as u32 ,
102
- Basis = sys:: godot_variant_type_GODOT_VARIANT_TYPE_BASIS as u32 ,
103
- Transform = sys:: godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM as u32 ,
104
- Color = sys:: godot_variant_type_GODOT_VARIANT_TYPE_COLOR as u32 ,
105
- NodePath = sys:: godot_variant_type_GODOT_VARIANT_TYPE_NODE_PATH as u32 ,
106
- Rid = sys:: godot_variant_type_GODOT_VARIANT_TYPE_RID as u32 ,
107
- Object = sys:: godot_variant_type_GODOT_VARIANT_TYPE_OBJECT as u32 ,
108
- Dictionary = sys:: godot_variant_type_GODOT_VARIANT_TYPE_DICTIONARY as u32 ,
109
- VariantArray = sys:: godot_variant_type_GODOT_VARIANT_TYPE_ARRAY as u32 ,
110
- ByteArray = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY as u32 ,
111
- Int32Array = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_INT_ARRAY as u32 ,
112
- Float32Array = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_REAL_ARRAY as u32 ,
113
- StringArray = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_STRING_ARRAY as u32 ,
114
- Vector2Array = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR2_ARRAY as u32 ,
115
- Vector3Array = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR3_ARRAY as u32 ,
116
- ColorArray = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_COLOR_ARRAY as u32 ,
87
+ macro_rules! variant_dispatch_arm {
88
+ ( $v: expr, $variant: ident ( $inner: ty ) ) => {
89
+ VariantDispatch :: $variant( <$inner>:: from_variant( $v) . unwrap( ) )
90
+ } ;
91
+ ( $v: expr, $variant: ident) => {
92
+ VariantDispatch :: $variant
93
+ } ;
117
94
}
118
95
96
+ macro_rules! decl_variant_type {
97
+ (
98
+ pub enum VariantType , VariantDispatch {
99
+ $(
100
+ $variant: ident $( ( $inner: ty) ) ? = $c_const: path,
101
+ ) *
102
+ }
103
+ ) => {
104
+ #[ repr( u32 ) ]
105
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
106
+ pub enum VariantType {
107
+ $(
108
+ $variant = $c_const as u32 ,
109
+ ) *
110
+ }
111
+
112
+ /// Rust enum associating each primitive variant type to its value.
113
+ ///
114
+ /// For `Variant`s containing objects, the original `Variant` is returned unchanged, due to
115
+ /// the limitations of statically-determined memory management.
116
+ #[ repr( u32 ) ]
117
+ pub enum VariantDispatch {
118
+ $(
119
+ $variant $( ( $inner) ) ?,
120
+ ) *
121
+ }
122
+
123
+ impl <' a> From <& ' a Variant > for VariantDispatch {
124
+ #[ inline]
125
+ fn from( v: & ' a Variant ) -> Self {
126
+ match v. get_type( ) {
127
+ $(
128
+ VariantType :: $variant => {
129
+ variant_dispatch_arm!( v, $variant $( ( $inner) ) ?)
130
+ } ,
131
+ ) *
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ decl_variant_type ! (
139
+ pub enum VariantType , VariantDispatch {
140
+ Nil = sys:: godot_variant_type_GODOT_VARIANT_TYPE_NIL,
141
+ Bool ( bool ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_BOOL,
142
+ I64 ( i64 ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_INT,
143
+ F64 ( f64 ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_REAL,
144
+ GodotString ( GodotString ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_STRING,
145
+ Vector2 ( Vector2 ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_VECTOR2,
146
+ Rect2 ( Rect2 ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_RECT2,
147
+ Vector3 ( Vector3 ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_VECTOR3,
148
+ Transform2D ( Transform2D ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM2D,
149
+ Plane ( Plane ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_PLANE,
150
+ Quat ( Quat ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_QUAT,
151
+ Aabb ( Aabb ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_AABB,
152
+ Basis ( Basis ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_BASIS,
153
+ Transform ( Transform ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_TRANSFORM,
154
+ Color ( Color ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_COLOR,
155
+ NodePath ( NodePath ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_NODE_PATH,
156
+ Rid ( Rid ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_RID,
157
+ Object ( Variant ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_OBJECT,
158
+ Dictionary ( Dictionary ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_DICTIONARY,
159
+ VariantArray ( VariantArray ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_ARRAY,
160
+ ByteArray ( ByteArray ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY,
161
+ Int32Array ( Int32Array ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_INT_ARRAY,
162
+ Float32Array ( Float32Array ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_REAL_ARRAY,
163
+ StringArray ( StringArray ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_STRING_ARRAY,
164
+ Vector2Array ( Vector2Array ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR2_ARRAY,
165
+ Vector3Array ( Vector3Array ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_VECTOR3_ARRAY,
166
+ ColorArray ( ColorArray ) = sys:: godot_variant_type_GODOT_VARIANT_TYPE_POOL_COLOR_ARRAY,
167
+ }
168
+ ) ;
169
+
119
170
impl VariantType {
120
171
#[ doc( hidden) ]
121
172
#[ inline]
@@ -674,6 +725,24 @@ impl Variant {
674
725
unsafe { VariantType :: from_sys ( ( get_api ( ) . godot_variant_get_type ) ( & self . 0 ) ) }
675
726
}
676
727
728
+ /// Converts this variant to a primitive value depending on its type.
729
+ ///
730
+ /// # Examples
731
+ ///
732
+ /// ```ignore
733
+ /// let variant = 42.to_variant();
734
+ /// let number_as_float = match variant.dispatch() {
735
+ /// VariantDispatch::I64(i) => i as f64,
736
+ /// VariantDispatch::F64(f) => f,
737
+ /// _ => panic!("not a number"),
738
+ /// };
739
+ /// approx::assert_relative_eq!(42.0, number_as_float);
740
+ /// ```
741
+ #[ inline]
742
+ pub fn dispatch ( & self ) -> VariantDispatch {
743
+ self . into ( )
744
+ }
745
+
677
746
/// Returns true if this is an empty variant.
678
747
#[ inline]
679
748
pub fn is_nil ( & self ) -> bool {
@@ -1928,4 +1997,28 @@ godot_test!(
1928
1997
let tuple = <( i64 , i64 ) >:: from_variant( & variant) ;
1929
1998
assert_eq!( Ok ( ( 42 , 54 ) ) , tuple) ;
1930
1999
}
2000
+
2001
+ test_variant_dispatch {
2002
+ let variant = 42i64 . to_variant( ) ;
2003
+ if let VariantDispatch :: I64 ( i) = variant. dispatch( ) {
2004
+ assert_eq!( 42 , i) ;
2005
+ } else {
2006
+ panic!( "incorrect dispatch type" ) ;
2007
+ } ;
2008
+
2009
+ let variant = true . to_variant( ) ;
2010
+ if let VariantDispatch :: Bool ( b) = variant. dispatch( ) {
2011
+ assert!( b) ;
2012
+ } else {
2013
+ panic!( "incorrect dispatch type" ) ;
2014
+ } ;
2015
+
2016
+ let variant = 42 . to_variant( ) ;
2017
+ let number_as_float = match variant. dispatch( ) {
2018
+ VariantDispatch :: I64 ( i) => i as f64 ,
2019
+ VariantDispatch :: F64 ( f) => f,
2020
+ _ => panic!( "not a number" ) ,
2021
+ } ;
2022
+ approx:: assert_relative_eq!( 42.0 , number_as_float) ;
2023
+ }
1931
2024
) ;
0 commit comments