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

refactor(model, util, validate)!: Convert CommandOptionChoice to a struct with value variants #2081

Merged
Next Next commit
refactor: use struct for option choices
  • Loading branch information
suneettipirneni committed Jan 24, 2023
commit 245784ccc8ccad40bf57a851cfcb27091e96901b
22 changes: 10 additions & 12 deletions twilight-model/src/application/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mod option;
pub use self::{
command_type::CommandType,
option::{
CommandOption, CommandOptionChoice, CommandOptionChoiceData, CommandOptionType,
CommandOption, CommandOptionChoice, CommandOptionChoiceValue, CommandOptionType,
CommandOptionValue,
},
};
Expand Down Expand Up @@ -97,7 +97,7 @@ pub struct Command {
#[cfg(test)]
mod tests {
use super::{
Command, CommandOption, CommandOptionChoice, CommandOptionChoiceData, CommandOptionType,
Command, CommandOption, CommandOptionChoice, CommandOptionChoiceValue, CommandOptionType,
CommandOptionValue, CommandType,
};
use crate::{channel::ChannelType, guild::Permissions, id::Id};
Expand Down Expand Up @@ -251,16 +251,14 @@ mod tests {
CommandOption {
autocomplete: Some(false),
channel_types: None,
choices: Some(Vec::from([CommandOptionChoice::Number(
CommandOptionChoiceData {
name: "number choice".to_owned(),
name_localizations: Some(HashMap::from([(
"en-US".to_owned(),
"number choice (but american)".to_owned(),
)])),
value: 10.0,
},
)])),
choices: Some(Vec::from([CommandOptionChoice {
name: "number choice".to_owned(),
name_localizations: Some(HashMap::from([(
"en-US".to_owned(),
"number choice (but american)".to_owned(),
)])),
value: CommandOptionChoiceValue::Number(10.0),
}])),
description: "number desc".to_owned(),
description_localizations: None,
kind: CommandOptionType::Number,
Expand Down
40 changes: 25 additions & 15 deletions twilight-model/src/application/command/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,7 @@ pub struct CommandOption {
/// Note that the right variant must be selected based on the
/// [`CommandOption`]'s [`CommandOptionType`].
suneettipirneni marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(untagged)]
pub enum CommandOptionChoice {
/// String choice.
String(CommandOptionChoiceData<String>),
/// Integer choice.
Integer(CommandOptionChoiceData<i64>),
/// Number choice.
Number(CommandOptionChoiceData<f64>),
}

/// Data of [`CommandOptionChoice`].
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct CommandOptionChoiceData<T> {
pub struct CommandOptionChoice {
/// Name of the choice. Must be 100 characters or less.
pub name: String,
/// Localization dictionary for the [`name`] field.
Expand All @@ -182,8 +170,30 @@ pub struct CommandOptionChoiceData<T> {
/// [`name`]: Self::name
#[serde(skip_serializing_if = "Option::is_none")]
pub name_localizations: Option<HashMap<String, String>>,
/// Value of the choice. Must be 100 characters or less if it is a string.
pub value: T,

/// Value of the choice.
pub value: CommandOptionChoiceValue,
}

/// The value of a [`CommandOptionChoice`].
///
/// Note that the right variant must be selected based on the
/// [`CommandOption`]'s [`CommandOptionType`].
///
/// See [`CommandOptionChoice`]'s documentation for more info.
suneettipirneni marked this conversation as resolved.
Show resolved Hide resolved
///
/// [`CommandOption`]: crate::model::interactions::application_command::CommandOption
/// [`CommandOptionChoice`]: crate::model::interactions::application_command::CommandOptionChoice
/// [`CommandOptionType`]: crate::model::interactions::application_command::CommandOptionType
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(untagged)]
pub enum CommandOptionChoiceValue {
/// String choice. Must be 100 characters or less.
String(String),
/// Integer choice.
Integer(i64),
/// Number choice.
Number(f64),
}

/// Type used in the `max_value` and `min_value` [`CommandOption`] field.
Expand Down
62 changes: 27 additions & 35 deletions twilight-util/src/builder/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

use twilight_model::{
application::command::{
Command, CommandOption, CommandOptionChoice, CommandOptionChoiceData, CommandOptionType,
Command, CommandOption, CommandOptionChoice, CommandOptionChoiceValue, CommandOptionType,
CommandOptionValue, CommandType,
},
channel::ChannelType,
Expand Down Expand Up @@ -506,9 +506,15 @@ impl IntegerBuilder {
choice_name: &str,
name_localizations: impl IntoIterator<Item = (K, V)>,
) -> Self {
let choice = self.0.choices.as_mut().expect("choices are set").iter_mut().find(
|choice| matches!(choice, CommandOptionChoice::Integer(CommandOptionChoiceData{ name, ..}) if name == choice_name),
);
let choice = self
.0
.choices
.as_mut()
.expect("choices are set")
.iter_mut()
.find(
|choice| matches!(choice, CommandOptionChoice{ name, value: CommandOptionChoiceValue::Integer(_), ..} if name == choice_name),
suneettipirneni marked this conversation as resolved.
Show resolved Hide resolved
);

if let Some(choice) = choice {
set_choice_localizations(choice, name_localizations);
Expand All @@ -529,12 +535,10 @@ impl IntegerBuilder {
self.0.choices = Some(
choices
.into_iter()
.map(|(name, value, ..)| {
CommandOptionChoice::Integer(CommandOptionChoiceData {
name: name.into(),
name_localizations: None,
value,
})
.map(|(name, value, ..)| CommandOptionChoice {
name: name.into(),
name_localizations: None,
value: CommandOptionChoiceValue::Integer(value),
})
.collect(),
);
Expand Down Expand Up @@ -754,7 +758,7 @@ impl NumberBuilder {
name_localizations: impl IntoIterator<Item = (K, V)>,
) -> Self {
let choice = self.0.choices.as_mut().expect("choices are set").iter_mut().find(
|choice| matches!(choice, CommandOptionChoice::Number(CommandOptionChoiceData {name, ..}) if name == choice_name),
|choice| matches!(choice, CommandOptionChoice {name, value: CommandOptionChoiceValue::Number(_), ..} if name == choice_name),
);

if let Some(choice) = choice {
Expand All @@ -776,12 +780,10 @@ impl NumberBuilder {
self.0.choices = Some(
choices
.into_iter()
.map(|(name, value, ..)| {
CommandOptionChoice::Number(CommandOptionChoiceData {
name: name.into(),
name_localizations: None,
value,
})
.map(|(name, value, ..)| CommandOptionChoice {
name: name.into(),
name_localizations: None,
value: CommandOptionChoiceValue::Number(value),
})
.collect(),
);
Expand Down Expand Up @@ -1001,7 +1003,7 @@ impl StringBuilder {
name_localizations: impl IntoIterator<Item = (K, V)>,
) -> Self {
let choice = self.0.choices.as_mut().expect("choices are set").iter_mut().find(
|choice| matches!(choice, CommandOptionChoice::String(CommandOptionChoiceData{name, ..}) if name == choice_name),
|choice| matches!(choice, CommandOptionChoice{name, value: CommandOptionChoiceValue::String(_), ..} if name == choice_name),
);

if let Some(choice) = choice {
Expand All @@ -1026,12 +1028,10 @@ impl StringBuilder {
self.0.choices = Some(
choices
.into_iter()
.map(|(name, value, ..)| {
CommandOptionChoice::String(CommandOptionChoiceData {
name: name.into(),
name_localizations: None,
value: value.into(),
})
.map(|(name, value, ..)| CommandOptionChoice {
name: name.into(),
name_localizations: None,
value: CommandOptionChoiceValue::String(value.into()),
})
.collect(),
);
Expand Down Expand Up @@ -1371,17 +1371,9 @@ fn set_choice_localizations<K: Into<String>, V: Into<String>>(
choice: &mut CommandOptionChoice,
localizations: impl IntoIterator<Item = (K, V)>,
) {
let name_localizations = match choice {
CommandOptionChoice::String(CommandOptionChoiceData {
name_localizations, ..
})
| CommandOptionChoice::Integer(CommandOptionChoiceData {
name_localizations, ..
})
| CommandOptionChoice::Number(CommandOptionChoiceData {
name_localizations, ..
}) => name_localizations,
};
let CommandOptionChoice {
name_localizations, ..
} = choice;

*name_localizations = Some(
localizations
suneettipirneni marked this conversation as resolved.
Show resolved Hide resolved
Expand Down