Skip to content
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

feat(model)!: preserve unknown bitflag values #2089

Draft
wants to merge 6 commits into
base: next
Choose a base branch
from

Conversation

zeylahellyer
Copy link
Member

@zeylahellyer zeylahellyer commented Jan 25, 2023

Bitflags received from the Discord API are truncated when deserialized. However, we have recently taken a model of accepting "unknown information", with our recent reworks of enums the shining example. Instead of failing to deserialize / ignore "unknown variants" we have taken the step to treat unknown data as "first class", in that Twilight not necessarily registering known values is okay and users can manually handle variants as they need. We should apply the same logic to bitflags and not trim unknown data.

This unfortunately makes use of unsafe code for constructing bitflags in tests and the Deserializer implementation for Permissions, because bitflags has an unorthodox definition of what "unsafe" is for its Bitflags::from_bits_unchecked function. bitflags treats unknown bits as being "unsafe", and so the function to construct bitflags with possibly unknown variants is unsafe. I have added notes detailing this. Funnily enough, bitflags' Deserialize implementation itself actually just throws the raw integer into the bitflag, effectively doing what Bitflags::from_bits_unchecked does. So this way of going about things is, unfortunately, expected.

As a side-effect, this allows us to remove our custom Deserialize and Serialize and derive them for all model bitflags except Permissions .

This is a breaking change because unknown bits are no longer truncated. This blocks on PR #2088 because it changes tests introduced in it, but will actually target next once #2088 is merged.

Add static assertions for bitflag implementations and constant values,
as well as tests for the serde implementations. The serde tests include
a test for the (de)serialization of a variant and that unknown bits are
truncated on deserialization.
Bitflags received from the Discord API are truncated when deserialized.
However, we have recently taken a model of accepting "unknown
information", with our recent reworks of enums the shining example.
Instead of failing to deserialize / ignore "unknown variants" we have
taken the step to treat unknown data as "first class", in that Twilight
not necessarily registering known values is okay and users can manually
handle variants as they need. We should apply the same logic to bitflags
and not trim unknown data.

This unfortunately makes use of unsafe code for constructing bitflags in
tests, because `bitflags` has an unorthodox definition of what "unsafe"
is for its `Bitflags::from_bits_unchecked` function. `bitflags` treats
unknown bits as being "unsafe", and so the function to construct
bitflags with possibly unknown variants is unsafe. I have added notes
detailing this.

This is a breaking change because unknown bits are no longer truncated.

Blocks on PR #2088.
@github-actions github-actions bot added c-model Affects the model crate m-breaking change Breaks the public API. t-feature Addition of a new feature labels Jan 25, 2023
@zeylahellyer zeylahellyer changed the title feat(model)!: don't truncate bitflags feat(model)!: preserve unknown bitflag values Jan 25, 2023
Copy link
Member

@Erk- Erk- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small nit, but looks good

twilight-model/src/gateway/presence/activity_flags.rs Outdated Show resolved Hide resolved
Base automatically changed from zeyla/test-model-bitflags to main January 28, 2023 19:22
@zeylahellyer zeylahellyer added the w-do-not-merge PR is blocked or deferred label Feb 4, 2023
@7596ff 7596ff changed the base branch from main to next February 5, 2023 01:27
// <https://github.com/bitflags/bitflags/issues/262>
#[allow(unsafe_code)]
let value = unsafe { ChannelFlags::from_bits_unchecked(1 << 63) };
serde_test::assert_de_tokens(&value, &[Token::U64(1 << 63)]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
serde_test::assert_de_tokens(&value, &[Token::U64(1 << 63)]);
serde_test::assert_tokens(&value, &[Token::U64(1 << 63)]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c-model Affects the model crate m-breaking change Breaks the public API. t-feature Addition of a new feature w-do-not-merge PR is blocked or deferred
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants