@@ -84,38 +84,89 @@ macro_rules! variant_to_type_from_sys {
8484 )
8585}
8686
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+ } ;
11794}
11895
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+
119170impl VariantType {
120171 #[ doc( hidden) ]
121172 #[ inline]
@@ -674,6 +725,24 @@ impl Variant {
674725 unsafe { VariantType :: from_sys ( ( get_api ( ) . godot_variant_get_type ) ( & self . 0 ) ) }
675726 }
676727
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+
677746 /// Returns true if this is an empty variant.
678747 #[ inline]
679748 pub fn is_nil ( & self ) -> bool {
@@ -1928,4 +1997,28 @@ godot_test!(
19281997 let tuple = <( i64 , i64 ) >:: from_variant( & variant) ;
19291998 assert_eq!( Ok ( ( 42 , 54 ) ) , tuple) ;
19301999 }
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+ }
19312024) ;
0 commit comments