-
-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of EngineBitfield
trait
#524
Conversation
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-524 |
Thanks a lot! The code looks already quite good for being the first codegen one 😊
It would be nice, but I'd maybe do it separately and only later (see below for reasoning). The
Edit: It's actually different, but not really better -- Godot exposes some bitfields as enums and their parameters as ints, e.g. So there's not that big of a type-safety/conciseness advantage of using bit operators on bitfield types vs. integers. |
godot-core/src/obj/traits.rs
Outdated
/// Auto-implemented for all engine-provided bitfields. | ||
pub trait EngineBitfield: Copy { | ||
fn try_from_ord(ord: u64) -> Option<Self>; | ||
|
||
/// Ordinal value of the bitfield, as specified in Godot. | ||
fn ord(self) -> u64; | ||
|
||
fn from_ord(ord: u64) -> Self { | ||
Self::try_from_ord(ord) | ||
.unwrap_or_else(|| panic!("ordinal {ord} does not map to any bitfield")) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs should clarify whether an ord
represents a single bit flag, or possibly a combination thereof.
I assume it's the former, because otherwise it's not so easy to exclude invalid ords.
Also, the unwrap_or_else
error message should be corrected correspondingly; "bitfield" is the type and not the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should definitely represent the single bit flag. 👍
Will change the wording to make sense, sorry about that! :^)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrased the sentences a bit, does this work?
/// Ordinal value of the bit flag, as specified in Godot.`
[...]
.unwrap_or_else(|| panic!("ordinal {ord} does not map to any valid bit flag"))
b134043
to
4afc1ea
Compare
} | ||
} | ||
|
||
impl crate::builtin::meta::FromGodot for #enum_name { | ||
fn try_from_godot(via: Self::Via) -> std::result::Result<Self, crate::builtin::meta::ConvertError> { | ||
<Self as crate::obj::EngineEnum>::try_from_ord(via) | ||
#enum_or_bitfield_self::try_from_ord(via) | ||
.ok_or_else(|| crate::builtin::meta::FromGodotError::InvalidEnum.into_error(via)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some docs to FromGodotError::InvalidEnum
mentioning very briefly that this also includes bitfields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, yeah, makes sense.
Although I'm not quite sure on how we should phrase this, other than: /// InvalidEnum is also used by bitfields.
😅
godot-codegen/src/util.rs
Outdated
.or_else(|| ty.strip_prefix("bitfield::")); | ||
if let Some(bitfield) = ty.strip_prefix("bitfield::") { | ||
return if let Some((class, enum_)) = bitfield.split_once('.') { | ||
// Class-local bitfield |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Class-local bitfield | |
// Class-local bitfield. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should probably also change this for the enum also 😅
godot-codegen/src/util.rs
Outdated
surrounding_class: Some(class.to_string()), | ||
} | ||
} else { | ||
// Global bitfield |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Global bitfield | |
// Global bitfield. |
4afc1ea
to
b4cdc29
Compare
Thanks! 🙂 |
This PR partially concerns issue #503 and implements decoupling of enums and bitfields in codegen, in a way, where they are split into an already existing
EngineEnum
trait and the newly implementedEngineBitfield
trait, where bitfield ords useu64
whereas enum ords usei32
.Since this is my first PR on the subject of codegen, there may be logical errors in my assumptions, weird code style, code that doesn't need to be there, or general noob-ish code. Please do tell me about any such issues, so I may learn and improve, and subsequently correct them. :)
Since this PR is splitting off enums and bitfields in a more explicit way, this introduces breaking changes for those that have used a bitfield in their projects prior to this change. Specifically on the importing side of things. Not a huge issue, since the language server should pick up on where the type lives and therefore users can easily fix this.
This implementation can lead to potentially more flexibility to bitfields. We have the bitwise operation
BitOr
. CouldBitAnd
,BitXor
orBitNot
be useful to implement in some capacity here?It is my understanding that methods that use bitfields already use the type, and therefore don't need any refactoring, I may be completely wrong in that assumption. If there are any such instances, we should change them in this PR.
Thanks for the feedback.