Skip to content

Commit

Permalink
Replace Vec and String with FixedArray and FixedString for al…
Browse files Browse the repository at this point in the history
…l models (#2656)

This shrinks type sizes by a lot; however, it makes the user experience slightly
different:

- `FixedString` must be converted to String with `.into()` or `.into_string()`
  before it can be pushed to, but dereferences to `&str` as is.
- `FixedArray` must be converted to `Vec` with `.into()` or `.into_vec()`
  before it can be pushed to, but dereferences to `&[T]` as is.

The crate of these types is currently a Git dependency, but this is fine for
the `next` branch. It needs some basic testing, which Serenity is perfect for,
before a release will be made to crates.io.
  • Loading branch information
GnomedDev committed Mar 11, 2024
1 parent c10359c commit 9760624
Show file tree
Hide file tree
Showing 67 changed files with 547 additions and 489 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dep_time = { version = "0.3.30", package = "time", features = ["formatting", "pa
base64 = { version = "0.21.5" }
secrecy = { version = "0.8.0", features = ["serde"] }
arrayvec = { version = "0.7.4", features = ["serde"] }
small-fixed-array = { git = "https://github.com/GnomedDev/small-fixed-array", features = ["serde", "log_using_tracing"] }
# Optional dependencies
fxhash = { version = "0.2.1", optional = true }
simd-json = { version = "0.13.4", optional = true }
Expand All @@ -48,7 +49,7 @@ mime_guess = { version = "2.0.4", optional = true }
dashmap = { version = "5.5.3", features = ["serde"], optional = true }
parking_lot = { version = "0.12.1", optional = true }
ed25519-dalek = { version = "2.0.0", optional = true }
typesize = { version = "0.1.2", optional = true, features = ["url", "time", "serde_json", "secrecy", "dashmap", "parking_lot", "details"] }
typesize = { version = "0.1.4", optional = true, features = ["url", "time", "serde_json", "secrecy", "dashmap", "parking_lot", "details"] }
# serde feature only allows for serialisation,
# Serenity workspace crates
command_attr = { version = "0.5.1", path = "./command_attr", optional = true }
Expand Down Expand Up @@ -124,6 +125,8 @@ simd_json = ["simd-json", "typesize?/simd_json"]
# Enables temporary caching in functions that retrieve data via the HTTP API.
temp_cache = ["cache", "mini-moka", "typesize?/mini_moka"]

typesize = ["dep:typesize", "small-fixed-array/typesize"]

# Removed feature (https://github.com/serenity-rs/serenity/pull/2246)
absolute_ratelimits = []

Expand Down
2 changes: 1 addition & 1 deletion examples/e04_message_builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl EventHandler for Handler {
// emojis, and more.
let response = MessageBuilder::new()
.push("User ")
.push_bold_safe(&msg.author.name)
.push_bold_safe(msg.author.name.into_string())
.push(" used the 'ping' command in the ")
.mention(&channel)
.push(" channel")
Expand Down
30 changes: 15 additions & 15 deletions src/builder/create_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ impl CreateCommandOption {
) -> Self {
Self(CommandOption {
kind,
name: name.into(),
name: name.into().into(),
name_localizations: None,
description: description.into(),
description: description.into().into(),
description_localizations: None,
required: false,
autocomplete: false,
Expand All @@ -37,7 +37,7 @@ impl CreateCommandOption {
min_length: None,
max_length: None,

channel_types: Vec::new(),
channel_types: FixedArray::default(),
choices: Vec::new(),
options: Vec::new(),
})
Expand All @@ -53,7 +53,7 @@ impl CreateCommandOption {
///
/// **Note**: Must be between 1 and 32 lowercase characters, matching `r"^[\w-]{1,32}$"`.
pub fn name(mut self, name: impl Into<String>) -> Self {
self.0.name = name.into();
self.0.name = name.into().into();
self
}

Expand All @@ -77,7 +77,7 @@ impl CreateCommandOption {
///
/// **Note**: Must be between 1 and 100 characters.
pub fn description(mut self, description: impl Into<String>) -> Self {
self.0.description = description.into();
self.0.description = description.into().into();
self
}
/// Specifies a localized description of the option.
Expand Down Expand Up @@ -114,7 +114,7 @@ impl CreateCommandOption {
/// characters. Value must be between -2^53 and 2^53.
pub fn add_int_choice(self, name: impl Into<String>, value: i32) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::from(value),
name_localizations: None,
})
Expand All @@ -128,7 +128,7 @@ impl CreateCommandOption {
locales: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::from(value),
name_localizations: Some(
locales.into_iter().map(|(l, n)| (l.into(), n.into())).collect(),
Expand All @@ -142,7 +142,7 @@ impl CreateCommandOption {
/// characters. Value must be up to 100 characters.
pub fn add_string_choice(self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::String(value.into()),
name_localizations: None,
})
Expand All @@ -156,7 +156,7 @@ impl CreateCommandOption {
locales: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::String(value.into()),
name_localizations: Some(
locales.into_iter().map(|(l, n)| (l.into(), n.into())).collect(),
Expand All @@ -170,7 +170,7 @@ impl CreateCommandOption {
/// characters. Value must be between -2^53 and 2^53.
pub fn add_number_choice(self, name: impl Into<String>, value: f64) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::from(value),
name_localizations: None,
})
Expand All @@ -184,7 +184,7 @@ impl CreateCommandOption {
locales: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.add_choice(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
value: Value::from(value),
name_localizations: Some(
locales.into_iter().map(|(l, n)| (l.into(), n.into())).collect(),
Expand Down Expand Up @@ -241,7 +241,7 @@ impl CreateCommandOption {
///
/// [`Channel`]: crate::model::application::CommandOptionType::Channel
pub fn channel_types(mut self, channel_types: Vec<ChannelType>) -> Self {
self.0.channel_types = channel_types;
self.0.channel_types = channel_types.into();
self
}

Expand Down Expand Up @@ -300,7 +300,7 @@ impl CreateCommandOption {
#[derive(Clone, Debug, Serialize)]
#[must_use]
pub struct CreateCommand {
name: String,
name: FixedString,
name_localizations: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
Expand All @@ -322,7 +322,7 @@ impl CreateCommand {
Self {
kind: None,

name: name.into(),
name: name.into().into(),
name_localizations: HashMap::new(),
description: None,
description_localizations: HashMap::new(),
Expand All @@ -341,7 +341,7 @@ impl CreateCommand {
/// global commands of the same app cannot have the same name. Two guild-specific commands of
/// the same app cannot have the same name.
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self.name = name.into().into();
self
}

Expand Down
20 changes: 10 additions & 10 deletions src/builder/create_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl CreateButton {
Self(Button {
kind: ComponentType::Button,
data: ButtonKind::Link {
url: url.into(),
url: url.into().into(),
},
label: None,
emoji: None,
Expand All @@ -60,7 +60,7 @@ impl CreateButton {
kind: ComponentType::Button,
data: ButtonKind::NonLink {
style: ButtonStyle::Primary,
custom_id: custom_id.into(),
custom_id: custom_id.into().into(),
},
label: None,
emoji: None,
Expand All @@ -77,7 +77,7 @@ impl CreateButton {
custom_id, ..
} = &mut self.0.data
{
*custom_id = id.into();
*custom_id = id.into().into();
}
self
}
Expand All @@ -97,7 +97,7 @@ impl CreateButton {

/// Sets label of the button.
pub fn label(mut self, label: impl Into<String>) -> Self {
self.0.label = Some(label.into());
self.0.label = Some(label.into().into());
self
}

Expand Down Expand Up @@ -338,8 +338,8 @@ impl CreateInputText {
) -> Self {
Self(InputText {
style: Some(style),
label: Some(label.into()),
custom_id: custom_id.into(),
label: Some(label.into().into()),
custom_id: custom_id.into().into(),

placeholder: None,
min_length: None,
Expand All @@ -359,20 +359,20 @@ impl CreateInputText {

/// Sets the label of this input text. Replaces the current value as set in [`Self::new`].
pub fn label(mut self, label: impl Into<String>) -> Self {
self.0.label = Some(label.into());
self.0.label = Some(label.into().into());
self
}

/// Sets the custom id of the input text, a developer-defined identifier. Replaces the current
/// value as set in [`Self::new`].
pub fn custom_id(mut self, id: impl Into<String>) -> Self {
self.0.custom_id = id.into();
self.0.custom_id = id.into().into();
self
}

/// Sets the placeholder of this input text.
pub fn placeholder(mut self, label: impl Into<String>) -> Self {
self.0.placeholder = Some(label.into());
self.0.placeholder = Some(label.into().into());
self
}

Expand All @@ -390,7 +390,7 @@ impl CreateInputText {

/// Sets the value of this input text.
pub fn value(mut self, value: impl Into<String>) -> Self {
self.0.value = Some(value.into());
self.0.value = Some(value.into().into());
self
}

Expand Down
26 changes: 13 additions & 13 deletions src/builder/create_embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl CreateEmbed {
/// **Note**: This can't be longer than 4096 characters.
#[inline]
pub fn description(mut self, description: impl Into<String>) -> Self {
self.0.description = Some(description.into());
self.0.description = Some(description.into().into());
self
}

Expand Down Expand Up @@ -104,7 +104,7 @@ impl CreateEmbed {
#[inline]
pub fn image(mut self, url: impl Into<String>) -> Self {
self.0.image = Some(EmbedImage {
url: url.into(),
url: url.into().into(),
proxy_url: None,
height: None,
width: None,
Expand All @@ -116,7 +116,7 @@ impl CreateEmbed {
#[inline]
pub fn thumbnail(mut self, url: impl Into<String>) -> Self {
self.0.thumbnail = Some(EmbedThumbnail {
url: url.into(),
url: url.into().into(),
proxy_url: None,
height: None,
width: None,
Expand Down Expand Up @@ -147,14 +147,14 @@ impl CreateEmbed {
/// Set the title of the embed.
#[inline]
pub fn title(mut self, title: impl Into<String>) -> Self {
self.0.title = Some(title.into());
self.0.title = Some(title.into().into());
self
}

/// Set the URL to direct to when clicking on the title.
#[inline]
pub fn url(mut self, url: impl Into<String>) -> Self {
self.0.url = Some(url.into());
self.0.url = Some(url.into().into());
self
}

Expand Down Expand Up @@ -208,7 +208,7 @@ impl Default for CreateEmbed {
description: None,
thumbnail: None,
timestamp: None,
kind: Some("rich".into()),
kind: Some("rich".to_string().into()),
author: None,
colour: None,
footer: None,
Expand Down Expand Up @@ -236,7 +236,7 @@ impl CreateEmbedAuthor {
/// Creates an author object with the given name, leaving all other fields empty.
pub fn new(name: impl Into<String>) -> Self {
Self(EmbedAuthor {
name: name.into(),
name: name.into().into(),
icon_url: None,
url: None,
// Has no builder method because I think this field is only relevant when receiving (?)
Expand All @@ -246,19 +246,19 @@ impl CreateEmbedAuthor {

/// Set the author's name, replacing the current value as set in [`Self::new`].
pub fn name(mut self, name: impl Into<String>) -> Self {
self.0.name = name.into();
self.0.name = name.into().into();
self
}

/// Set the URL of the author's icon.
pub fn icon_url(mut self, icon_url: impl Into<String>) -> Self {
self.0.icon_url = Some(icon_url.into());
self.0.icon_url = Some(icon_url.into().into());
self
}

/// Set the author's URL.
pub fn url(mut self, url: impl Into<String>) -> Self {
self.0.url = Some(url.into());
self.0.url = Some(url.into().into());
self
}
}
Expand All @@ -278,7 +278,7 @@ impl CreateEmbedFooter {
/// Creates a new footer object with the given text, leaving all other fields empty.
pub fn new(text: impl Into<String>) -> Self {
Self(EmbedFooter {
text: text.into(),
text: text.into().into(),
icon_url: None,
// Has no builder method because I think this field is only relevant when receiving (?)
proxy_icon_url: None,
Expand All @@ -287,13 +287,13 @@ impl CreateEmbedFooter {

/// Set the footer's text, replacing the current value as set in [`Self::new`].
pub fn text(mut self, text: impl Into<String>) -> Self {
self.0.text = text.into();
self.0.text = text.into().into();
self
}

/// Set the icon URL's value. This only supports HTTP(S).
pub fn icon_url(mut self, icon_url: impl Into<String>) -> Self {
self.0.icon_url = Some(icon_url.into());
self.0.icon_url = Some(icon_url.into().into());
self
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/builder/create_forum_tag.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::internal::prelude::*;
use crate::model::prelude::*;

/// [Discord docs](https://discord.com/developers/docs/resources/channel#forum-tag-object-forum-tag-structure)
Expand All @@ -6,16 +7,16 @@ use crate::model::prelude::*;
#[must_use]
#[derive(Clone, Debug, Serialize)]
pub struct CreateForumTag {
name: String,
name: FixedString,
moderated: bool,
emoji_id: Option<EmojiId>,
emoji_name: Option<String>,
emoji_name: Option<FixedString>,
}

impl CreateForumTag {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
name: name.into().into(),
moderated: false,
emoji_id: None,
emoji_name: None,
Expand Down
2 changes: 1 addition & 1 deletion src/builder/create_interaction_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ pub struct AutocompleteChoice(CommandOptionChoice);
impl AutocompleteChoice {
pub fn new(name: impl Into<String>, value: impl Into<Value>) -> Self {
Self(CommandOptionChoice {
name: name.into(),
name: name.into().into(),
name_localizations: None,
value: value.into(),
})
Expand Down
2 changes: 1 addition & 1 deletion src/builder/create_scheduled_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<'a> CreateScheduledEvent<'a> {
/// [`External`]: ScheduledEventType::External
pub fn location(mut self, location: impl Into<String>) -> Self {
self.entity_metadata = Some(ScheduledEventMetadata {
location: Some(location.into()),
location: Some(location.into().into()),
});
self
}
Expand Down
Loading

0 comments on commit 9760624

Please sign in to comment.