Skip to content

Commit

Permalink
Convert enum number into wrapper struct to save type sizes (serenity-…
Browse files Browse the repository at this point in the history
…rs#2746)

Saves a couple bytes in each model by replacing the enums with a simpler
and more accurate representation, a newtype with named statics.
https://www.diffchecker.com/ohzayL9Z/
  • Loading branch information
GnomedDev authored and mkrasnitski committed Jan 31, 2025
1 parent 55d248b commit 305d5a2
Show file tree
Hide file tree
Showing 24 changed files with 39 additions and 99 deletions.
1 change: 0 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum Opcode {
/// Dispatches an event.
Expand Down
41 changes: 18 additions & 23 deletions src/internal/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,43 +86,39 @@ macro_rules! status {
macro_rules! enum_number {
(
$(#[$outer:meta])*
$(#[<default> = $default:literal])?
$vis:vis enum $Enum:ident {
$(
$(#[doc = $doc:literal])*
$(#[cfg $($cfg:tt)*])?
$(#[default $($dummy:tt)?])?
$Variant:ident = $value:literal,
)*
_ => Unknown($T:ty),
}
) => {
$(#[$outer])*
$vis enum $Enum {
$vis struct $Enum (pub $T);

$(
impl Default for $Enum {
fn default() -> Self {
Self($default)
}
}
)?

#[allow(non_snake_case, non_upper_case_globals)]
impl $Enum {
$(
$(#[doc = $doc])*
$(#[cfg $($cfg)*])?
$(#[default $($dummy:tt)?])?
$Variant,
$vis const $Variant: Self = Self($value);
)*
/// Variant value is unknown.
Unknown($T),
}

impl From<$T> for $Enum {
fn from(value: $T) -> Self {
match value {
$($(#[cfg $($cfg)*])? $value => Self::$Variant,)*
unknown => Self::Unknown(unknown),
}
}
}

impl From<$Enum> for $T {
fn from(value: $Enum) -> Self {
match value {
$($(#[cfg $($cfg)*])? $Enum::$Variant => $value,)*
$Enum::Unknown(unknown) => unknown,
}
/// Variant value is unknown.
#[must_use]
$vis const fn Unknown(val: $T) -> Self {
Self(val)
}
}
};
Expand Down Expand Up @@ -184,7 +180,6 @@ mod tests {
fn enum_number() {
enum_number! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(from = "u8", into = "u8")]
pub enum T {
/// AAA
A = 1,
Expand Down
4 changes: 0 additions & 4 deletions src/model/application/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandType {
ChatInput = 1,
Expand All @@ -248,7 +247,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-entry-point-command-handler-types)
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum EntryPointHandlerType {
AppHandler = 1,
Expand Down Expand Up @@ -323,7 +321,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandOptionType {
SubCommand = 1,
Expand Down Expand Up @@ -396,7 +393,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permission-type).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum CommandPermissionType {
Role = 1,
Expand Down
2 changes: 1 addition & 1 deletion src/model/application/command_interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ fn option_from_raw(raw: RawCommandDataOption) -> Result<CommandDataOption> {
CommandOptionType::Mentionable => CommandDataOptionValue::Mentionable(value!()),
CommandOptionType::Role => CommandDataOptionValue::Role(value!()),
CommandOptionType::User => CommandDataOptionValue::User(value!()),
CommandOptionType::Unknown(unknown) => CommandDataOptionValue::Unknown(unknown),
CommandOptionType(unknown) => CommandDataOptionValue::Unknown(unknown),
};

Ok(CommandDataOption {
Expand Down
7 changes: 2 additions & 5 deletions src/model/application/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ enum_number! {
/// The type of a component
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ComponentType {
ActionRow = 1,
Expand Down Expand Up @@ -70,7 +69,7 @@ impl<'de> Deserialize<'de> for ActionRowComponent {
ComponentType::ActionRow => {
return Err(DeError::custom("Invalid component type ActionRow"))
},
ComponentType::Unknown(i) => {
ComponentType(i) => {
return Err(DeError::custom(format_args!("Unknown component type {i}")))
},
}
Expand Down Expand Up @@ -146,7 +145,7 @@ impl Serialize for ButtonKind {
custom_id,
style,
} => Helper {
style: (*style).into(),
style: style.0,
url: None,
custom_id: Some(custom_id),
sku_id: None,
Expand Down Expand Up @@ -184,7 +183,6 @@ enum_number! {
/// The style of a button.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ButtonStyle {
Primary = 1,
Expand Down Expand Up @@ -298,7 +296,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/message-components#text-inputs-text-input-styles).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum InputTextStyle {
Short = 1,
Expand Down
2 changes: 1 addition & 1 deletion src/model/application/component_interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,12 @@ impl<'de> Deserialize<'de> for ComponentInteractionDataKind {
ComponentType::ChannelSelect => Self::ChannelSelect {
values: parse_values!(),
},
ComponentType::Unknown(x) => Self::Unknown(x),
x @ (ComponentType::ActionRow | ComponentType::InputText) => {
return Err(D::Error::custom(format_args!(
"invalid message component type in this context: {x:?}",
)));
},
ComponentType(x) => Self::Unknown(x),
})
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/model/application/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ impl<'de> Deserialize<'de> for Interaction {
InteractionType::Autocomplete => from_value(value).map(Interaction::Autocomplete),
InteractionType::Modal => from_value(value).map(Interaction::Modal),
InteractionType::Ping => from_value(value).map(Interaction::Ping),
InteractionType::Unknown(_) => return Err(DeError::custom("Unknown interaction type")),
InteractionType(_) => return Err(DeError::custom("Unknown interaction type")),
}
.map_err(DeError::custom)
}
Expand All @@ -277,7 +277,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-type).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum InteractionType {
Ping = 1,
Expand Down Expand Up @@ -347,7 +346,7 @@ impl<'de> serde::Deserialize<'de> for AuthorizingIntegrationOwners {
let mut out = Vec::new();
while let Some(key_str) = map.next_key::<serde_cow::CowStr<'_>>()? {
let key_int = key_str.0.parse::<u8>().map_err(serde::de::Error::custom)?;
let value = match InstallationContext::from(key_int) {
let value = match InstallationContext(key_int) {
InstallationContext::Guild => {
// GuildId here can be `0`, which signals the command is guild installed
// but invoked in a DM, we have to do this fun deserialisation dance.
Expand Down Expand Up @@ -543,8 +542,8 @@ impl serde::Serialize for MessageInteractionMetadata {
MessageInteractionMetadata::ModalSubmit(val) => {
serialize_with_type(serializer, val, InteractionType::Modal)
},
&MessageInteractionMetadata::Unknown(kind) => {
tracing::warn!("Tried to serialize MessageInteractionMetadata::Unknown({}), serialising null instead", u8::from(kind));
&MessageInteractionMetadata::Unknown(InteractionType(kind)) => {
tracing::warn!("Tried to serialize MessageInteractionMetadata::Unknown({kind}), serialising null instead");
serializer.serialize_none()
},
}
Expand Down
3 changes: 0 additions & 3 deletions src/model/application/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ enum_number! {
/// [interaction contexts](https://discord.com/developers/docs/resources/application#application-object-application-integration-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum InstallationContext {
Guild = 0,
Expand All @@ -121,7 +120,6 @@ enum_number! {
/// [interaction contexts](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum InteractionContext {
/// Interaction can be used within servers
Expand Down Expand Up @@ -184,7 +182,6 @@ pub struct TeamMember {
enum_number! {
/// [Discord docs](https://discord.com/developers/docs/topics/teams#data-models-membership-state-enum).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum MembershipState {
Invited = 1,
Expand Down
2 changes: 0 additions & 2 deletions src/model/channel/guild_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,9 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-forum-layout-types).
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ForumLayoutType {
/// No default has been set for forum channel.
#[default]
NotSet = 0,
/// Display posts as a list.
ListView = 1,
Expand Down
13 changes: 4 additions & 9 deletions src/model/channel/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -958,11 +958,9 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#message-object-message-types).
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum MessageType {
/// A regular message.
#[default]
Regular = 0,
/// An indicator that a recipient was added by the author.
GroupRecipientAddition = 1,
Expand Down Expand Up @@ -1029,7 +1027,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#message-object-message-activity-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum MessageActivityKind {
Join = 1,
Expand Down Expand Up @@ -1078,12 +1075,11 @@ enum_number! {
/// Message Reference Type information
///
/// [Discord docs](https://discord.com/developers/docs/resources/message#message-reference-types)
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
#[<default> = 0]
pub enum MessageReferenceKind {
#[default]
Default = 0,
Forward = 1,
_ => Unknown(u8),
Expand Down Expand Up @@ -1421,12 +1417,11 @@ enum_number! {
/// Currently, there is only the one option.
///
/// [Discord docs](https://discord.com/developers/docs/resources/poll#layout-type)
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
#[<default> = 1]
pub enum PollLayoutType {
#[default]
Default = 1,
_ => Unknown(u8),
}
Expand Down
16 changes: 5 additions & 11 deletions src/model/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,9 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-channel-types).
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ChannelType {
/// An indicator that the channel is a text [`GuildChannel`].
#[default]
Text = 0,
/// An indicator that the channel is a [`PrivateChannel`].
Private = 1,
Expand Down Expand Up @@ -252,8 +250,8 @@ enum_number! {

impl ChannelType {
#[must_use]
pub const fn name(&self) -> &str {
match *self {
pub const fn name(self) -> &'static str {
match self {
Self::Private => "private",
Self::Text => "text",
Self::Voice => "voice",
Expand All @@ -266,7 +264,7 @@ impl ChannelType {
Self::Stage => "stage",
Self::Directory => "directory",
Self::Forum => "forum",
Self::Unknown(_) => "unknown",
Self(_) => "unknown",
}
}
}
Expand Down Expand Up @@ -359,7 +357,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-video-quality-modes).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum VideoQualityMode {
/// An indicator that the video quality is chosen by Discord for optimal
Expand All @@ -375,15 +372,14 @@ enum_number! {
/// See [`StageInstance::privacy_level`].
///
/// [Discord docs](https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level).
#[derive(Clone, Copy, Default, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
#[<default> = 2]
pub enum StageInstancePrivacyLevel {
/// The Stage instance is visible publicly. (deprecated)
Public = 1,
/// The Stage instance is visible to only guild members.
#[default]
GuildOnly = 2,
_ => Unknown(u8),
}
Expand All @@ -395,7 +391,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#thread-metadata-object)
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u16", into = "u16")]
#[non_exhaustive]
pub enum AutoArchiveDuration {
None = 0,
Expand Down Expand Up @@ -556,7 +551,6 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object-sort-order-types).
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum SortOrder {
/// Sort forum posts by activity.
Expand Down
1 change: 0 additions & 1 deletion src/model/channel/reaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ enum_number! {
/// A list of types a reaction can be.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ReactionTypes {
Normal = 0,
Expand Down
1 change: 0 additions & 1 deletion src/model/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ enum_number! {
///
/// [Discord docs](https://discord.com/developers/docs/resources/user#connection-object-visibility-types).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ConnectionVisibility {
/// Invisible to everyone except the user themselves
Expand Down
2 changes: 0 additions & 2 deletions src/model/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,9 @@ enum_number! {
/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types).
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
#[serde(from = "u8", into = "u8")]
#[non_exhaustive]
pub enum ActivityType {
/// An indicator that the user is playing a game.
#[default]
Playing = 0,
/// An indicator that the user is streaming to a service.
Streaming = 1,
Expand Down
Loading

0 comments on commit 305d5a2

Please sign in to comment.