-
Notifications
You must be signed in to change notification settings - Fork 30
Support (fieldless) enums in Config::Input
#41
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
Conversation
I: Copy | ||
+ Clone | ||
+ PartialEq | ||
+ bytemuck::NoUninit | ||
+ bytemuck::CheckedBitPattern | ||
+ bytemuck::Zeroable, |
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.
Not sure PlayerInput needs all those type constraints, as tests are passing without. I think it would fail before when setting the Config::Input
. That said, it makes sense to have the same constraints so I'm ok with 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.
@@ -11,9 +11,9 @@ pub(crate) struct InputQueue<T> | |||
where | |||
T: Config, | |||
{ | |||
/// The head of the queue. The newest `GameInput` is saved here | |||
/// The head of the queue. The newest `PlayerInput` is saved here |
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.
Added renames from GameInput to PlayerInput (could be slit in another PR..)
tests/enum_input.rs
Outdated
pub enum EnumInput { | ||
Val1, | ||
Val2, | ||
} |
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.
For now, it only supports fieldless enums, because NoUninit doesn't support fields, it might be technically possible to add this support upstream in bytemuck ?
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'm wondering if NoUninit is actually needed, and if yes, could MaybeUninit replace it ? 🤔 I'm gonna explore this idea.
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.
Please do! Sounds exciting! :)
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 gave it a small attempt, I think it's a good direction, but our problem is bytes_of used here
Line 54 in 0d70f45
let size = bytemuck::bytes_of(&zeroed.input).len() * num_players; |
I'm gonna start a discussion with bytemuck and see where it goes from there.
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.
Since I was reading thru this PR anyway, just a small note: bytes_of
is used elsewhere so this doesn't solve the problem, but instead of creating a zeroed
object just to call bytes_of(&zeroed).len() * num_players
here, you could forego all of that and simply call core::mem::size_of::<PlayerInput<T::Input>>() * num_players
to get the size
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.
thanks for the comment! good catch, that definitely seems like a smarter solution.
@@ -86,7 +86,7 @@ impl InputBytes { | |||
for p in 0..num_players { | |||
let start = p * size; | |||
let end = start + size; | |||
let input = *bytemuck::try_from_bytes::<T::Input>(&self.bytes[start..end]) | |||
let input = *bytemuck::checked::try_from_bytes::<T::Input>(&self.bytes[start..end]) |
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.
That's an important change.
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.
Can you elaborate what is actually checked here?
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.
Sure, first, we need to understand the behaviour before this change:
With the restriction "AnyBitValid", enums could not work because an enum cannot have "any" bits ; mainly because its type flag, but probably other types are concerned (references, bool...)
Nothing is really checked if the type is "AnyBitPattern" though
the "checked" prefixed leads to:
https://github.com/Lokathor/bytemuck/blob/6b1b7cecd32902b240a8e8593534600a09269d14/src/checked.rs#L209 ; where there is additional checks in case there are not valid bit patterns 😅.
All "AnyBitPatterns" implement "CheckedBitPattern" though, so no additional checks are performed for most types :). (https://github.com/Lokathor/bytemuck/blob/6b1b7cecd32902b240a8e8593534600a09269d14/src/checked.rs#L143)
I like this. @Vrixyz what do you think: Is there anything else you want to add/change before we merge this? |
I'd like to make tests code quality better, I duplicated a lot of code and there may even be dead code. A first step could be to:
|
remove dead code add enum prefix to 'duplicated' structs separated enum tests from non-enum
@@ -115,7 +115,7 @@ fn test_advance_frame_p2p_sessions() -> Result<(), GGRSError> { | |||
assert!(sess1.current_state() == SessionState::Synchronizing); | |||
assert!(sess2.current_state() == SessionState::Synchronizing); | |||
|
|||
for _ in 0..10 { | |||
for _ in 0..50 { |
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.
@gschup I would be happy to revert that, but on a 2015 macos, even 0..30
lead to sometimes failures. I figured it's a small price to pay to make the tests a little bit more stable. Eventually we would probably want a timeout, but it's too far from this Pull Request scope.
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 find this to be very odd. This never was an issue for me, but network packets are mysterious :D
use ggrs::{GGRSError, SessionBuilder}; | ||
|
||
#[test] | ||
fn test_enum_advance_frames_with_delayed_input() -> Result<(), GGRSError> { |
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.
as said in comment, I would have like to provide more tests, but it's creating a lot of duplicated code, so I figured we could merge minimal tests, and then discuss a better test strategy:
- I tried a generic
GameStub
, but all the data structures are quite tied, and the hardest to make generic is theConfig
implementation. - macros could be another idea, but they can be controversial.
@@ -21,7 +21,7 @@ rand = "0.8" | |||
bitfield-rle = "0.2" | |||
parking_lot = "0.11" | |||
instant = "0.1" | |||
bytemuck = {version = "1.7", features = ["derive"]} | |||
bytemuck = {version = "1.9", features = ["derive"]} |
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.
Pod trait was split in multiple traits in release 1.9.0 https://github.com/Lokathor/bytemuck/blob/main/changelog.md#190
I'm done with this Pull Request, I'll address feedbacks only now :) |
Thanks to fu5ha from gschup#41 (comment)
Improves #40.
Pod
trait was split in multiple traits in release 1.9.0 https://github.com/Lokathor/bytemuck/blob/main/changelog.md#190