Skip to content

Commit 370ac19

Browse files
committed
Add 'with' and 'without' methods to EngineEnum.
1 parent 403aa97 commit 370ac19

4 files changed

Lines changed: 90 additions & 1 deletion

File tree

godot-codegen/src/generator/enums.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,12 @@ fn make_enum_as_str(enum_: &Enum) -> TokenStream {
485485

486486
/// Creates implementations for bitwise operators for the given enum.
487487
///
488-
/// Currently, this is just [`BitOr`](std::ops::BitOr) for bitfields but that could be expanded in the future.
488+
/// Currently, for bitfields this is the following:
489+
/// - [`BitOr`][std::ops::BitOr]
490+
/// - [`BitOrAssign`][std::ops::BitOrAssign]
491+
///
492+
/// While it would be possible to expand these with additional bitwise operations such as `BitAnd` and `Not`, the preferred way to manipulate
493+
/// flags is to use the `with` and `without` methods rather than using the bitwise operators themselves.
489494
fn make_enum_bitwise_operators(enum_: &Enum, enum_bitmask: Option<&RustTy>) -> TokenStream {
490495
let name = &enum_.name;
491496

godot-core/src/obj/traits.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,16 @@ pub trait EngineBitfield: Copy + 'static {
285285
/// }
286286
/// ```
287287
fn all_constants() -> &'static [EnumConstant<Self>];
288+
289+
/// Returns the flags from `self` combined with the flag(s) from `add_flags` arg.
290+
fn with(self, add_flags: Self) -> Self {
291+
Self::from_ord(self.ord() | add_flags.ord())
292+
}
293+
294+
/// Returns the flags from `self`, except for any that were present in the `remove_flags` arg.
295+
fn without(self, remove_flags: Self) -> Self {
296+
Self::from_ord(self.ord() & (!remove_flags.ord()))
297+
}
288298
}
289299

290300
/// Trait for enums that can be used as indices in arrays.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
use godot::classes::node::DuplicateFlags;
9+
use godot::obj::EngineBitfield;
10+
11+
use crate::framework::itest;
12+
13+
/// Necessarily since `from_ord` is not `const`.
14+
fn no_flags() -> DuplicateFlags {
15+
// Could use `Default::default()` here. Until it is broken by `!1630`, funnily enough.
16+
DuplicateFlags::from_ord(0)
17+
}
18+
19+
const SIGNALS: DuplicateFlags = DuplicateFlags::SIGNALS;
20+
const GROUPS: DuplicateFlags = DuplicateFlags::GROUPS;
21+
const USE_INSTANTIATION: DuplicateFlags = DuplicateFlags::USE_INSTANTIATION;
22+
23+
#[itest]
24+
fn bitfield_ops_with() {
25+
let no_flags = no_flags();
26+
27+
assert_eq!(no_flags.with(USE_INSTANTIATION), USE_INSTANTIATION);
28+
29+
assert_eq!(
30+
GROUPS.with(SIGNALS),
31+
DuplicateFlags::from_ord(GROUPS.ord() | SIGNALS.ord())
32+
);
33+
34+
assert_eq!(GROUPS.with(GROUPS), GROUPS);
35+
36+
assert_eq!(GROUPS.with(GROUPS.with(SIGNALS)), GROUPS.with(SIGNALS));
37+
38+
let with_then_with = GROUPS.with(SIGNALS).with(USE_INSTANTIATION);
39+
assert!(with_then_with.is_set(GROUPS));
40+
assert!(with_then_with.is_set(SIGNALS));
41+
assert!(with_then_with.is_set(USE_INSTANTIATION));
42+
43+
assert_eq!(GROUPS.with(no_flags), GROUPS);
44+
}
45+
46+
#[itest]
47+
fn bitfield_ops_without() {
48+
let no_flags = no_flags();
49+
50+
assert_eq!(USE_INSTANTIATION.without(USE_INSTANTIATION), no_flags);
51+
52+
assert_eq!(SIGNALS.with(GROUPS).without(SIGNALS), GROUPS);
53+
54+
assert_eq!(GROUPS.without(SIGNALS), GROUPS);
55+
56+
assert_eq!(
57+
SIGNALS
58+
.with(GROUPS)
59+
.without(SIGNALS.with(USE_INSTANTIATION)),
60+
GROUPS
61+
);
62+
63+
let without_then_without = GROUPS
64+
.with(SIGNALS)
65+
.with(USE_INSTANTIATION)
66+
.without(SIGNALS)
67+
.without(USE_INSTANTIATION);
68+
assert!(without_then_without.is_set(GROUPS));
69+
assert!(!without_then_without.is_set(SIGNALS));
70+
assert!(!without_then_without.is_set(USE_INSTANTIATION));
71+
72+
assert_eq!(GROUPS.without(no_flags), GROUPS);
73+
}

itest/rust/src/object_tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
mod base_test;
9+
mod bitfield_ops_test;
910
mod call_deferred_test;
1011
mod class_id_test;
1112
mod class_rename_test;

0 commit comments

Comments
 (0)