-
Notifications
You must be signed in to change notification settings - Fork 49
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
Improve forwards compatibility of input API #131
Conversation
b006c2d
to
37dc94a
Compare
37dc94a
to
eb7dfb1
Compare
// semantic meaning at compile time. | ||
#[doc(hidden)] | ||
#[num_enum(catch_all)] | ||
__Unknown(u32), |
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.
Hmm, on the ndk
I had to assign a bogus discriminant here.
// What we aim for instead is to have a hidden catch-all variant that | ||
// is considered (practically) unmatchable so code is forced to have | ||
// a `unknown => {}` catch-all pattern match that will cover unknown variants | ||
// either in the form of Rust variants added in future versions or | ||
// in the form of an `__Unknown(u32)` integer that represents an unknown | ||
// variant seen at runtime. |
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 like this idea and I should have done it this way in the ndk
. Because for now we have both:
non_exhaustive
to allow extending enums (mostly formats and error codes) without breaking changes;Unknown
variant that isn't properly hidden with publici32
value, so that missing values are at least properlyDebug
-printed, easing the process of adding unknown members in the future.
// XXX: we use `AInputEvent_getAction` directly since we have our own | ||
// `KeyAction` enum that we share between backends, which may also | ||
// capture unknown variants added in new versions of Android. |
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.
Yikes, none of these enums have really been marked appropriately.
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 guess this works (but haven't really reviewed in too great detail - got a tight schedule and am about to leave), unfortunate that the ndk::event
types are so rigid.
8049355
to
4de6d47
Compare
Thanks for the quick review. Yeah I'm not 100% sure whether we might come up with a better strategy for allowing for this extensibility but for now this feels like a reasonably viable approach. One specific limitation of this approach is that it's not compatible with I.e. Any code that ends up exhaustively matching If we were to implement the Still though, the intent is hopefully quite obvious with the |
4de6d47
to
471b2be
Compare
Not exactly sure what you are referring to, since we have exactly such a setup in the Maybe it had to do with ordering of the attributes? |
By the way having a non-unit enum variant appropriately disallows |
This adds a `#[doc(hidden)]` `__Unknown(u32)` variant to the various enums to keep them extensible without requiring API breaks. We need to consider that most enums that are based on Android SDK enums may be extended across different versions of Android (i.e. effectively at runtime) or extended in new versions of `android-activity` when we pull in the latest NDK/SDK constants. In particular in the case that there is some unknown variant we at least want to be able to preserve the integer value to allow the values to be either passed back into the SDK (it doesn't always matter whether we know the semantics of a variant at compile time) or passed on to something downstream that could be independently updated to know the semantics. We don't want it to be an API break to extend these enums in future releases of `android-activity`. It's not enough to rely on `#[non-exhaustive]` because that only really helps when adding new variants in sync with android-activity releases. On the other hand we also can't rely on a catch-all `Unknown(u32)` that only really helps with unknown variants seen at runtime. (If code were to have an exhaustive match that would include matching on `Unknown(_)` values then they wouldn't be compatible with new versions of android-activity that would promote unknown values to known ones). What we aim for instead is to have a hidden catch-all variant that is considered (practically) unmatchable so code is forced to have a `unknown => {}` catch-all pattern match that will cover unknown variants either in the form of Rust variants added in future versions or in the form of an `__Unknown(u32)` integer that represents an unknown variant seen at runtime. Any `unknown => {}` pattern match can rely on `IntoPrimitive` to convert the `unknown` variant to the integer that comes from the Android SDK in case that values needs to be passed on, even without knowing it's semantic meaning at compile time. Instead of adding an `__Unknown(u32)` variant to the `Class` enum though this enum has been removed in favour of adding methods like `is_button_class()` and `is_pointer_class()` to the `Source` type, since the class flags aren't guaranteed to be mutually exclusive and since they are an attribute of the `Source`. This removes some reliance `try_into().unwrap()` that was put in place anticipating that we would support `into()` via `num_enum`, once we could update our rust-version.
471b2be
to
288ed09
Compare
Yep I think it's reasonable that you have to use It's sort of unfortunate that there's no magic compiler trick for being able to avoid having the separate discriminant / value for this case so we could really have a true |
Yeah I didn't see that it cause any error to use So actually we probably can add |
This was change as meant to be squashed into #131 before landing
This change was meant to be squashed into #131 before landing
This change was meant to be squashed into #131 before landing
That was my main concern with this system/implementation; while "opaque to the user" it just feels ugly to now have to come up with a bogus discriminant (that could possibly be mapped in the future) just to have That said, if there was builtin support for such a In the end I might even like the associated-enum-constants representation from |
This adds a
#[doc(hidden)]
__Unknown(u32)
variant to the various enums to keep them extensible without requiring API breaks.We need to consider that most enums that are based on Android SDK enums may be extended across different versions of Android (i.e. effectively at runtime) or extended in new versions of
android-activity
when we pull in the latest NDK/SDK constants.In particular in the case that there is some unknown variant we at least want to be able to preserve the integer value to allow the values to be either passed back into the SDK (it doesn't always matter whether we know the semantics of a variant at compile time) or passed on to something downstream that could be independently updated to know the semantics.
We don't want it to be an API break to extend these enums in future releases of
android-activity
.It's not enough to rely on
#[non-exhaustive]
because that only really helps when adding new variants in sync with android-activity releases.On the other hand we also can't rely on a catch-all
Unknown(u32)
that only really helps with unknown variants seen at runtime. (If code were to have an exhaustive match that would include matching onUnknown(_)
values then they wouldn't be compatible with new versions of android-activity that would promote unknown values to known ones).What we aim for instead is to have a hidden catch-all variant that is considered (practically) unmatchable so code is forced to have a
unknown => {}
catch-all pattern match that will cover unknown variants either in the form of Rust variants added in future versions or in the form of an__Unknown(u32)
integer that represents an unknown variant seen at runtime.Any
unknown => {}
pattern match can rely onIntoPrimitive
to convert theunknown
variant to the integer that comes from the Android SDK in case that values needs to be passed on, even without knowing it's semantic meaning at compile time.Instead of adding an
__Unknown(u32)
variant to theClass
enum though this enum has been removed in favour of adding methods likeis_button_class()
andis_pointer_class()
to theSource
type, since the class flags aren't guaranteed to be mutually exclusive and since they are an attribute of theSource
.This removes some reliance
try_into().unwrap()
that was put in place anticipating that we would supportinto()
vianum_enum
, once we could update our rust-version.