Skip to content

Commit

Permalink
Remove serde_json::Value from Http (serenity-rs#2806)
Browse files Browse the repository at this point in the history
This avoids allocating instances of `serde_json::Value`s.
  • Loading branch information
GnomedDev committed Oct 7, 2024
1 parent 033dfc1 commit b78b405
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 58 deletions.
4 changes: 3 additions & 1 deletion src/builder/edit_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ impl<'a> EditRole<'a> {
};

if let Some(position) = self.position {
http.edit_role_position(guild_id, role.id, position, self.audit_log_reason).await?;
guild_id
.edit_role_position_with_reason(http, role.id, position, self.audit_log_reason)
.await?;
}
Ok(role)
}
Expand Down
40 changes: 15 additions & 25 deletions src/http/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ impl Http {
pub async fn create_emoji(
&self,
guild_id: GuildId,
map: &Value,
map: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<Emoji> {
self.fire(Request {
Expand Down Expand Up @@ -639,7 +639,7 @@ impl Http {
/// over a [`Shard`], if at least one is running.
///
/// [`Shard`]: crate::gateway::Shard
pub async fn create_guild(&self, map: &Value) -> Result<PartialGuild> {
pub async fn create_guild(&self, map: &impl serde::Serialize) -> Result<PartialGuild> {
self.fire(Request {
body: Some(to_vec(map)?),
multipart: None,
Expand Down Expand Up @@ -678,7 +678,7 @@ impl Http {
&self,
guild_id: GuildId,
integration_id: IntegrationId,
map: &Value,
map: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<()> {
self.wind(204, Request {
Expand Down Expand Up @@ -775,7 +775,10 @@ impl Http {
}

/// Creates a private channel with a user.
pub async fn create_private_channel(&self, map: &Value) -> Result<PrivateChannel> {
pub async fn create_private_channel(
&self,
map: &impl serde::Serialize,
) -> Result<PrivateChannel> {
let body = to_vec(map)?;

self.fire(Request {
Expand Down Expand Up @@ -1481,7 +1484,7 @@ impl Http {
&self,
guild_id: GuildId,
emoji_id: EmojiId,
map: &Value,
map: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<Emoji> {
let body = to_vec(map)?;
Expand Down Expand Up @@ -1690,7 +1693,7 @@ impl Http {
pub async fn edit_guild_mfa_level(
&self,
guild_id: GuildId,
value: &Value,
value: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<MfaLevel> {
#[derive(Deserialize)]
Expand Down Expand Up @@ -1874,14 +1877,11 @@ impl Http {
pub async fn edit_nickname(
&self,
guild_id: GuildId,
new_nickname: Option<&str>,
map: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<()> {
let map = json!({ "nick": new_nickname });
let body = to_vec(&map)?;

self.wind(200, Request {
body: Some(body),
body: Some(to_vec(&map)?),
multipart: None,
headers: audit_log_reason.map(reason_into_header),
method: LightMethod::Patch,
Expand All @@ -1897,13 +1897,10 @@ impl Http {
pub async fn follow_news_channel(
&self,
news_channel_id: ChannelId,
target_channel_id: ChannelId,
map: &impl serde::Serialize,
) -> Result<FollowedChannel> {
let map = json!({ "webhook_channel_id": target_channel_id });
let body = to_vec(&map)?;

self.fire(Request {
body: Some(body),
body: Some(to_vec(&map)?),
multipart: None,
headers: None,
method: LightMethod::Post,
Expand Down Expand Up @@ -2014,19 +2011,12 @@ impl Http {
pub async fn edit_role_position(
&self,
guild_id: GuildId,
role_id: RoleId,
position: i16,
map: &impl serde::Serialize,
audit_log_reason: Option<&str>,
) -> Result<Vec<Role>> {
let map = json!([{
"id": role_id,
"position": position,
}]);
let body = to_vec(&map)?;

let mut value: Value = self
.fire(Request {
body: Some(body),
body: Some(to_vec(&map)?),
multipart: None,
headers: audit_log_reason.map(reason_into_header),
method: LightMethod::Patch,
Expand Down
11 changes: 10 additions & 1 deletion src/model/channel/channel_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,16 @@ impl ChannelId {
http: &Http,
target_channel_id: ChannelId,
) -> Result<FollowedChannel> {
http.follow_news_channel(self, target_channel_id).await
#[derive(serde::Serialize)]
struct FollowChannel {
webhook_channel_id: ChannelId,
}

let map = FollowChannel {
webhook_channel_id: target_channel_id,
};

http.follow_news_channel(self, &map).await
}

/// First attempts to retrieve the channel from the `temp_cache` if enabled, otherwise performs
Expand Down
98 changes: 78 additions & 20 deletions src/model/guild/guild_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::fmt;
#[cfg(feature = "model")]
use futures::stream::Stream;
use nonmax::{NonMaxU16, NonMaxU8};
use serde_json::json;

#[cfg(feature = "model")]
use crate::builder::{
Expand Down Expand Up @@ -362,12 +361,18 @@ impl GuildId {
/// [`EditProfile::avatar`]: crate::builder::EditProfile::avatar
/// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
pub async fn create_emoji(self, http: &Http, name: &str, image: &str) -> Result<Emoji> {
let map = json!({
"name": name,
"image": image,
});
#[derive(serde::Serialize)]
struct CreateEmoji<'a> {
name: &'a str,
image: &'a str,
}

http.create_emoji(self, &map, None).await
let body = CreateEmoji {
name,
image,
};

http.create_emoji(self, &body, None).await
}

/// Creates an integration for the guild.
Expand All @@ -385,12 +390,19 @@ impl GuildId {
integration_id: IntegrationId,
kind: &str,
) -> Result<()> {
let map = json!({
"id": integration_id,
"type": kind,
});
#[derive(serde::Serialize)]
struct CreateIntegration<'a> {
id: IntegrationId,
#[serde(rename = "type")]
kind: &'a str,
}

http.create_guild_integration(self, integration_id, &map, None).await
let body = CreateIntegration {
id: integration_id,
kind,
};

http.create_guild_integration(self, integration_id, &body, None).await
}

/// Creates a new role in the guild with the data set, if any.
Expand Down Expand Up @@ -578,9 +590,14 @@ impl GuildId {
/// [Create Guild Expressions]: Permissions::CREATE_GUILD_EXPRESSIONS
/// [Manage Guild Expressions]: Permissions::MANAGE_GUILD_EXPRESSIONS
pub async fn edit_emoji(self, http: &Http, emoji_id: EmojiId, name: &str) -> Result<Emoji> {
let map = json!({
"name": name,
});
#[derive(serde::Serialize)]
struct EditEmoji<'a> {
name: &'a str,
}

let map = EditEmoji {
name,
};

http.edit_emoji(self, emoji_id, &map, None).await
}
Expand Down Expand Up @@ -635,10 +652,16 @@ impl GuildId {
mfa_level: MfaLevel,
audit_log_reason: Option<&str>,
) -> Result<MfaLevel> {
let value = json!({
"level": mfa_level,
});
http.edit_guild_mfa_level(self, &value, audit_log_reason).await
#[derive(serde::Serialize)]
struct EditMfaModel {
level: MfaLevel,
}

let map = EditMfaModel {
level: mfa_level,
};

http.edit_guild_mfa_level(self, &map, audit_log_reason).await
}

/// Edits the current user's nickname for the guild.
Expand All @@ -653,7 +676,16 @@ impl GuildId {
///
/// [Change Nickname]: Permissions::CHANGE_NICKNAME
pub async fn edit_nickname(self, http: &Http, new_nickname: Option<&str>) -> Result<()> {
http.edit_nickname(self, new_nickname, None).await
#[derive(serde::Serialize)]
struct EditNickname<'a> {
nick: Option<&'a str>,
}

let map = EditNickname {
nick: new_nickname,
};

http.edit_nickname(self, &map, None).await
}

/// Edits a [`Role`], optionally setting its new fields.
Expand Down Expand Up @@ -778,7 +810,33 @@ impl GuildId {
role_id: RoleId,
position: i16,
) -> Result<Vec<Role>> {
http.edit_role_position(self, role_id, position, None).await
self.edit_role_position_with_reason(http, role_id, position, None).await
}

/// Edit the position of a [`Role`] relative to all others in the [`Guild`].
///
/// # Errors
///
/// See [`GuildId::edit_role_position`] for more details.
pub async fn edit_role_position_with_reason(
self,
http: &Http,
role_id: RoleId,
position: i16,
reason: Option<&str>,
) -> Result<Vec<Role>> {
#[derive(serde::Serialize)]
struct EditRole {
id: RoleId,
position: i16,
}

let map = EditRole {
id: role_id,
position,
};

http.edit_role_position(self, &map, reason).await
}

/// Edits the guild's welcome screen.
Expand Down
16 changes: 11 additions & 5 deletions src/model/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,18 @@ impl Guild {
/// [`Shard`]: crate::gateway::Shard
/// [whitelist]: https://discord.com/developers/docs/resources/guild#create-guild
pub async fn create(http: &Http, name: &str, icon: Option<ImageHash>) -> Result<PartialGuild> {
let map = serde_json::json!({
"icon": icon,
"name": name,
});
#[derive(serde::Serialize)]
struct CreateGuild<'a> {
name: &'a str,
icon: Option<ImageHash>,
}

let body = CreateGuild {
name,
icon,
};

http.create_guild(&map).await
http.create_guild(&body).await
}

/// Creates a new [`Channel`] in the guild.
Expand Down
15 changes: 9 additions & 6 deletions src/model/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ use std::num::NonZeroU16;
use std::ops::{Deref, DerefMut};

use serde::{Deserialize, Serialize};
#[cfg(feature = "model")]
use serde_json::json;

use super::prelude::*;
#[cfg(feature = "model")]
Expand Down Expand Up @@ -621,18 +619,23 @@ impl UserId {
///
/// [current user]: CurrentUser
pub async fn create_dm_channel(self, cache_http: impl CacheHttp) -> Result<PrivateChannel> {
#[derive(serde::Serialize)]
struct CreateDmChannel {
recipient_id: UserId,
}

#[cfg(feature = "temp_cache")]
if let Some(cache) = cache_http.cache() {
if let Some(private_channel) = cache.temp_private_channels.get(&self) {
return Ok(PrivateChannel::clone(&private_channel));
}
}

let map = json!({
"recipient_id": self,
});
let body = CreateDmChannel {
recipient_id: self,
};

let channel = cache_http.http().create_private_channel(&map).await?;
let channel = cache_http.http().create_private_channel(&body).await?;

#[cfg(feature = "temp_cache")]
if let Some(cache) = cache_http.cache() {
Expand Down

0 comments on commit b78b405

Please sign in to comment.