1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Copyright (c) godot-rust; Bromeon and contributors.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/// Dispatches a class to different subclasses.
///
/// Similar to a `match` statement, but with downcasts. Earlier matches dominate, so keep more-derived classes first.
/// The current implementation checks [`Gd::try_cast()`][crate::obj::Gd::try_cast] linearly with the number of branches.
/// This may change in the future.
///
/// When none of the listed classes match, a _fallback branch_ acts as a catch-all and allows to retrieve the original `Gd` pointer.
/// If the type of the `match_class!` expression is `()`, you can omit the fallback branch. For all other types, it is required, even if all
/// direct subclasses are handled. The reason for this is that there may be other subclasses which are not statically known by godot-rust
/// (e.g. from a script or GDExtension).
///
/// The fallback branch can either be `_` (discard object), or `variable` to access the original object inside the fallback arm.
///
/// # Example
/// ```no_run
/// # use godot::prelude::*;
/// # use godot_core::classes::{InputEvent, InputEventAction};
/// # fn some_input() -> Gd<InputEvent> { unimplemented!() }
/// # // Hack to keep amount of SELECTED_CLASSES limited:
/// # type InputEventMouseButton = InputEventAction;
/// # type InputEventMouseMotion = InputEventAction;
/// # type InputEventKey = InputEventAction;
/// // Basic syntax.
/// let event: Gd<InputEvent> = some_input();
///
/// let simple_dispatch: i32 = match_class! { event,
/// button @ InputEventMouseButton => 1,
/// motion @ InputEventMouseMotion => 2,
/// action @ InputEventAction => 3,
/// key @ InputEventKey => 4,
/// _ => 0, // Fallback.
/// };
///
/// // More diverse dispatch patterns are also supported.
/// let fancy_dispatch: i32 = match_class! { some_input(),
/// // Mutable bindings supported:
/// mut button @ InputEventMouseButton => 1,
///
/// // Block syntax for multiple statements:
/// motion @ InputEventMouseMotion => {
/// godot_print!("motion");
/// 2
/// },
///
/// // Qualified types supported:
/// action @ godot::classes::InputEventAction => 3,
///
/// // If you're only interested in the class and not the object,
/// // discard it with either `_` or `_variable`:
/// _ @ InputEventKey => 4,
///
/// // Fallback with variable -- retrieves original Gd<InputEvent>.
/// original => 0,
/// // Can also be used with mut:
/// // mut original => 0,
/// // If the match arms have type (), we can also omit the fallback branch.
/// };
///
/// // event_type is now 0, 1, 2, 3 or 4
/// ```
///
/// # Expression and control flow
/// The `match_class!` macro is an expression, as such it has a type. If that type is not `()`, you typically need to use the expression or
/// end it with a semicolon.
///
/// Control-flow statements like `?`, `return`, `continue`, `break` can be used within the match arms.
// Note: annoyingly shows full implementation in docs. For workarounds, either move impl to a helper macro, or use something like
// https://crates.io/crates/clean-macro-docs.
// Earlier syntax expected curly braces, i.e.: ($subject:expr, { $($tt:tt)* }) => {{ ... }};
};
}