-
-
Notifications
You must be signed in to change notification settings - Fork 130
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
[RFC] Handling unknown enum variants #759
Comments
I'd like to propose a 4th option: separate the incoming and outgoing payloads:
This way we eliminate both the data loss potential on the incoming payloads as well as keep it ergonomic to work with for downstream users. In addition if discord does add something new that the lib doesn't know about the user can compare it to an own const or enum to work with it (so they are not forced to do several major twilight upgrades just to access a new channel type) going with the only sending validated payloads to the discord api to avoid 400 errors twilight uses we should keep using enums there to enforce this. |
a few implementation options:
|
i like the |
Looks like this has now been addressed, but we should figure out what is left to do here. |
When a new API feature is released involving a new enum variant the deserialization of any parent struct will fail due to the unknown variant. This can be seen with the release of stage channels which caused the deserialization of any guild with one to fail. This needed a hotfix and quick release as more stage channels were being seen, causing users to experience an increasing number of failures.
There's a few routes we can go to handle this but they all have their drawbacks.
Ignoring failed optional or list element deserializations
When the deserialization of an optional field fails we could simply ignore it from the parent type. Consider this example:
Due to a new
BType
being published in the API the deserialization ofFoo
fails. This is similar to a newChannelType
enum variant causing the failure of the deserialization of the parentGuildChannel
cascading into the failure of the deserialization ofGuild
s.We could instead simply ignore the failure of the deserialization of
Foo::b
and log the error. This could be applied similarly to individual failing elements within a list. The benefit of this is that the user will still get the rest ofFoo
. The drawback is that this basically silently ignores errors and throws away information, thus not giving the user all of the information from the raw API response.Unknown
variantAnother option is an
Unknown
variant at the maximum of the u8 spectrum when the deserialization of an enum otherwise fails. This allows users to be able to tell that the variant isn't supported. See this example:As stated above the benefit is that the deserialization of any parents continues while the user can know that the variant is unknown. The downside is that the actual value is lost and this is more of a "hack".
Parent wrapping enum
Lastly, we could wrap the type in an enum as part of the parent type. This enum could have a variant containing the deserialized enum or an "unknown" variant containing the number. This allows the user to still have the type safety of the enum when deserialization was successful while also being able to know and retrieve the raw numeric value when the numeric value is unknown. This is easier to show in code:
The benefit is that the type safety of
Foo
remains while the unknown value is concisely represented, preventing deserialization failures. The downside is that this requires an additional method access or pattern match to retrieve either value.Notes
This is all pseudo-code and untested. Personally I'd go with the
TypeWrapper
implementation because I see this as having the least drawbacks, is not a hack unlike the second option, and doesn't throw away information unlike the first.The text was updated successfully, but these errors were encountered: