Skip to content

Commit fce77d6

Browse files
committed
implement mut bindings for match_class
1 parent 47cc8da commit fce77d6

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

godot-core/src/classes/match_class.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
///
3636
/// // More diverse dispatch patterns are also supported.
3737
/// let fancy_dispatch: i32 = match_class! { some_input(),
38-
/// button @ InputEventMouseButton => 1,
38+
/// // Mutable bindings supported:
39+
/// mut button @ InputEventMouseButton => 1,
3940
///
4041
/// // Block syntax for multiple statements:
4142
/// motion @ InputEventMouseMotion => {
@@ -48,6 +49,8 @@
4849
///
4950
/// // Fallback with variable -- retrieves original Gd<InputEvent>.
5051
/// original => 0,
52+
/// // Can also be used with mut:
53+
/// // mut original => 0,
5154
/// };
5255
///
5356
/// // event_type is now 0, 1, 2, or 3
@@ -73,13 +76,24 @@ macro_rules! match_class {
7376
#[macro_export]
7477
macro_rules! match_class_muncher {
7578
/*
76-
// If we want to support `var @ _ => { ... }` syntax, use this branch first (to not match `_` as type).
79+
// If we want to support `variable @ _ => { ... }` syntax, use this branch first (to not match `_` as type).
7780
($subject:ident, $var:ident @ _ => $block:expr $(,)?) => {{
7881
let $var = $subject;
7982
$block
8083
}};
8184
*/
8285

86+
// mut variable @ Class => { ... }.
87+
($subject:ident, mut $var:ident @ $Ty:ty => $block:expr, $($rest:tt)*) => {{
88+
match $subject.try_cast::<$Ty>() {
89+
Ok(mut $var) => $block,
90+
Err(__obj) => {
91+
$crate::match_class_muncher!(__obj, $($rest)*)
92+
}
93+
}
94+
}};
95+
96+
// variable @ Class => { ... }.
8397
($subject:ident, $var:ident @ $Ty:ty => $block:expr, $($rest:tt)*) => {{
8498
match $subject.try_cast::<$Ty>() {
8599
Ok($var) => $block,
@@ -89,11 +103,19 @@ macro_rules! match_class_muncher {
89103
}
90104
}};
91105

106+
// mut variable => { ... }.
107+
($subject:ident, mut $var:ident => $block:expr $(,)?) => {{
108+
let mut $var = $subject;
109+
$block
110+
}};
111+
112+
// variable => { ... }.
92113
($subject:ident, $var:ident => $block:expr $(,)?) => {{
93114
let $var = $subject;
94115
$block
95116
}};
96117

118+
// _ => { ... }.
97119
($subject:ident, _ => $block:expr $(,)?) => {{
98120
$block
99121
}};

itest/rust/src/engine_tests/match_class_test.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ use godot::prelude::*; // Expect match_class! to be in prelude.
1010

1111
// Ensure static types are as expected.
1212
fn require_object(_: &Object) {}
13+
fn require_mut_object(_: &mut Object) {}
1314
fn require_node(_: &Node) {}
1415
fn require_node2d(_: &Node2D) {}
16+
fn require_mut_node2d(_: &mut Node2D) {}
1517

1618
#[itest]
1719
fn match_class_basic_dispatch() {
@@ -35,6 +37,28 @@ fn match_class_basic_dispatch() {
3537
to_free.free();
3638
}
3739

40+
#[itest]
41+
fn match_class_basic_mut_dispatch() {
42+
let node2d = Node2D::new_alloc();
43+
let obj: Gd<Object> = node2d.upcast();
44+
let to_free = obj.clone();
45+
46+
let result = match_class! { obj,
47+
mut node @ Node2D => {
48+
require_mut_node2d(&mut node);
49+
1
50+
},
51+
node @ Node => {
52+
require_node(&node);
53+
2
54+
},
55+
_ => 3 // No comma.
56+
};
57+
58+
assert_eq!(result, 1);
59+
to_free.free();
60+
}
61+
3862
#[itest]
3963
fn match_class_shadowed_by_more_general() {
4064
let node2d = Node2D::new_alloc();
@@ -86,6 +110,25 @@ fn match_class_named_fallback_matched() {
86110
assert_eq!(result, 3);
87111
}
88112

113+
#[itest]
114+
fn match_class_named_mut_fallback_matched() {
115+
let obj: Gd<Object> = Resource::new_gd().upcast();
116+
117+
let result = match_class! { obj,
118+
_node @ Node => 1,
119+
_node @ Node2D => 2,
120+
121+
// Named fallback with access to original object.
122+
mut other => {
123+
require_mut_object(&mut other);
124+
assert_eq!(other.get_class(), "Resource".into());
125+
3
126+
}
127+
};
128+
129+
assert_eq!(result, 3);
130+
}
131+
89132
#[itest]
90133
fn match_class_named_fallback_unmatched() {
91134
// Test complex inline expression.

0 commit comments

Comments
 (0)