From cf533fe7140cd9ffe11fbbedbfbd78cb30462039 Mon Sep 17 00:00:00 2001 From: Gnome! Date: Sun, 3 Dec 2023 12:43:27 +0000 Subject: [PATCH] Remove temporary `Vec` usage in the `http` module (#2624, #2646) This avoids having to allocate to store fixed length (replaced with normal array) or fixed capacity (replaced with `ArrayVec`) collections as vectors for the purposes of putting them through the `Request` plumbing. Slight behavioral change - before, setting `params` to `Some(vec![])` would still append a question mark to the end of the url. Now, we check if the params array `is_empty` instead of `is_some`, so the question mark won't be appended if the params list is empty. Co-authored-by: Michael Krasnitski <42564254+mkrasnitski@users.noreply.github.com> --- src/http/client.rs | 415 +++++++++++++++++++++------------------ src/http/ratelimiting.rs | 13 +- src/http/request.rs | 37 ++-- 3 files changed, 255 insertions(+), 210 deletions(-) diff --git a/src/http/client.rs b/src/http/client.rs index 4a367088ff2..ef6163ba580 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -5,6 +5,7 @@ use std::num::NonZeroU64; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; +use arrayvec::ArrayVec; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use reqwest::header::{HeaderMap as Headers, HeaderValue}; #[cfg(feature = "utils")] @@ -234,7 +235,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await?; @@ -267,7 +268,7 @@ impl Http { role_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -297,7 +298,7 @@ impl Http { guild_id, user_id, }, - params: Some(vec![("delete_message_days", delete_message_days.to_string())]), + params: [("delete_message_days", delete_message_days.to_string())].into(), }) .await } @@ -318,7 +319,7 @@ impl Http { route: Route::ChannelTyping { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -347,7 +348,7 @@ impl Http { route: Route::GuildChannels { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -364,7 +365,7 @@ impl Http { headers: audit_log_reason.map(reason_into_header), method: LightMethod::Post, route: Route::StageInstances, - params: None, + params: [].into(), }) .await } @@ -388,7 +389,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -410,7 +411,7 @@ impl Http { route: Route::ChannelThreads { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -445,7 +446,7 @@ impl Http { route: Route::ChannelForumPosts { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -471,7 +472,7 @@ impl Http { route: Route::GuildEmojis { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -494,7 +495,7 @@ impl Http { application_id: self.try_application_id()?, token: interaction_token, }, - params: None, + params: [].into(), }; if files.is_empty() { @@ -529,7 +530,7 @@ impl Http { route: Route::Commands { application_id: self.try_application_id()?, }, - params: None, + params: [].into(), }) .await } @@ -547,7 +548,7 @@ impl Http { route: Route::Commands { application_id: self.try_application_id()?, }, - params: None, + params: [].into(), }) .await } @@ -567,7 +568,7 @@ impl Http { application_id: self.try_application_id()?, guild_id, }, - params: None, + params: [].into(), }) .await } @@ -612,7 +613,7 @@ impl Http { headers: None, method: LightMethod::Post, route: Route::Guilds, - params: None, + params: [].into(), }) .await } @@ -638,7 +639,7 @@ impl Http { application_id: self.try_application_id()?, guild_id, }, - params: None, + params: [].into(), }) .await } @@ -667,7 +668,7 @@ impl Http { guild_id, integration_id, }, - params: None, + params: [].into(), }) .await } @@ -694,7 +695,7 @@ impl Http { interaction_id, token: interaction_token, }, - params: None, + params: [].into(), }; if files.is_empty() { @@ -736,7 +737,7 @@ impl Http { route: Route::ChannelInvites { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -760,7 +761,7 @@ impl Http { channel_id, target_id, }, - params: None, + params: [].into(), }) .await } @@ -775,7 +776,7 @@ impl Http { headers: None, method: LightMethod::Post, route: Route::UserMeDmChannels, - params: None, + params: [].into(), }) .await } @@ -797,7 +798,7 @@ impl Http { message_id, reaction: &reaction_type.as_data(), }, - params: None, + params: [].into(), }) .await } @@ -818,7 +819,7 @@ impl Http { route: Route::GuildRoles { guild_id, }, - params: None, + params: [].into(), }) .await?; @@ -851,7 +852,7 @@ impl Http { route: Route::GuildScheduledEvents { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -880,7 +881,7 @@ impl Http { route: Route::GuildStickers { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -957,7 +958,7 @@ impl Http { route: Route::ChannelWebhooks { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -976,7 +977,7 @@ impl Http { route: Route::Channel { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -995,7 +996,7 @@ impl Http { route: Route::StageInstance { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -1018,7 +1019,7 @@ impl Http { guild_id, emoji_id, }, - params: None, + params: [].into(), }) .await } @@ -1039,7 +1040,7 @@ impl Http { token: interaction_token, message_id, }, - params: None, + params: [].into(), }) .await } @@ -1055,7 +1056,7 @@ impl Http { application_id: self.try_application_id()?, command_id, }, - params: None, + params: [].into(), }) .await } @@ -1070,7 +1071,7 @@ impl Http { route: Route::Guild { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1091,7 +1092,7 @@ impl Http { guild_id, command_id, }, - params: None, + params: [].into(), }) .await } @@ -1112,7 +1113,7 @@ impl Http { guild_id, integration_id, }, - params: None, + params: [].into(), }) .await } @@ -1131,7 +1132,7 @@ impl Http { route: Route::Invite { code, }, - params: None, + params: [].into(), }) .await } @@ -1152,7 +1153,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -1172,7 +1173,7 @@ impl Http { route: Route::ChannelMessagesBulkDelete { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -1209,7 +1210,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -1231,7 +1232,7 @@ impl Http { message_id, reaction: &reaction_type.as_data(), }, - params: None, + params: [].into(), }) .await } @@ -1250,7 +1251,7 @@ impl Http { application_id: self.try_application_id()?, token: interaction_token, }, - params: None, + params: [].into(), }) .await } @@ -1271,7 +1272,7 @@ impl Http { channel_id, target_id, }, - params: None, + params: [].into(), }) .await } @@ -1295,7 +1296,7 @@ impl Http { user_id, reaction: &reaction_type.as_data(), }, - params: None, + params: [].into(), }) .await } @@ -1317,7 +1318,7 @@ impl Http { message_id, reaction: &reaction_type.as_data(), }, - params: None, + params: [].into(), }) .await } @@ -1338,7 +1339,7 @@ impl Http { guild_id, role_id, }, - params: None, + params: [].into(), }) .await } @@ -1363,7 +1364,7 @@ impl Http { guild_id, event_id, }, - params: None, + params: [].into(), }) .await } @@ -1386,7 +1387,7 @@ impl Http { guild_id, sticker_id, }, - params: None, + params: [].into(), }) .await } @@ -1440,7 +1441,7 @@ impl Http { route: Route::Webhook { webhook_id, }, - params: None, + params: [].into(), }) .await } @@ -1481,7 +1482,7 @@ impl Http { webhook_id, token, }, - params: None, + params: [].into(), }) .await } @@ -1503,7 +1504,7 @@ impl Http { route: Route::Channel { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -1523,7 +1524,7 @@ impl Http { route: Route::StageInstance { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -1549,7 +1550,7 @@ impl Http { guild_id, emoji_id, }, - params: None, + params: [].into(), }) .await } @@ -1576,7 +1577,7 @@ impl Http { token: interaction_token, message_id, }, - params: None, + params: [].into(), }; if new_attachments.is_empty() { @@ -1612,7 +1613,7 @@ impl Http { token: interaction_token, message_id, }, - params: None, + params: [].into(), }) .await } @@ -1638,7 +1639,7 @@ impl Http { application_id: self.try_application_id()?, command_id, }, - params: None, + params: [].into(), }) .await } @@ -1660,7 +1661,7 @@ impl Http { route: Route::Guild { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1688,7 +1689,7 @@ impl Http { guild_id, command_id, }, - params: None, + params: [].into(), }) .await } @@ -1716,7 +1717,7 @@ impl Http { guild_id, command_id, }, - params: None, + params: [].into(), }) .await } @@ -1737,7 +1738,7 @@ impl Http { route: Route::GuildChannels { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1764,7 +1765,7 @@ impl Http { route: Route::GuildMfa { guild_id, }, - params: None, + params: [].into(), }) .await .map(|mfa: GuildMfaLevel| mfa.level) @@ -1787,7 +1788,7 @@ impl Http { route: Route::GuildWidget { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1809,7 +1810,7 @@ impl Http { route: Route::GuildWelcomeScreen { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1834,7 +1835,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await?; @@ -1864,7 +1865,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }; if new_attachments.is_empty() { @@ -1897,7 +1898,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -1919,7 +1920,7 @@ impl Http { route: Route::GuildMemberMe { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1944,7 +1945,7 @@ impl Http { route: Route::GuildMemberMe { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -1966,7 +1967,7 @@ impl Http { route: Route::ChannelFollowNews { channel_id: news_channel_id, }, - params: None, + params: [].into(), }) .await } @@ -1985,7 +1986,7 @@ impl Http { application_id: self.try_application_id()?, token: interaction_token, }, - params: None, + params: [].into(), }) .await } @@ -2010,7 +2011,7 @@ impl Http { application_id: self.try_application_id()?, token: interaction_token, }, - params: None, + params: [].into(), }; if new_attachments.is_empty() { @@ -2036,7 +2037,7 @@ impl Http { headers: None, method: LightMethod::Patch, route: Route::UserMe, - params: None, + params: [].into(), }) .await } @@ -2059,7 +2060,7 @@ impl Http { guild_id, role_id, }, - params: None, + params: [].into(), }) .await?; @@ -2093,7 +2094,7 @@ impl Http { route: Route::GuildRoles { guild_id, }, - params: None, + params: [].into(), }) .await?; @@ -2130,7 +2131,7 @@ impl Http { guild_id, event_id, }, - params: None, + params: [].into(), }) .await } @@ -2157,7 +2158,7 @@ impl Http { guild_id, sticker_id, }, - params: None, + params: [].into(), }) .await?; @@ -2183,7 +2184,7 @@ impl Http { route: Route::Channel { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -2233,7 +2234,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -2284,7 +2285,7 @@ impl Http { route: Route::GuildVoiceStateMe { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -2335,7 +2336,7 @@ impl Http { route: Route::Webhook { webhook_id, }, - params: None, + params: [].into(), }) .await } @@ -2383,7 +2384,7 @@ impl Http { webhook_id, token, }, - params: None, + params: [].into(), }) .await } @@ -2447,7 +2448,9 @@ impl Http { files: Vec, map: &impl serde::Serialize, ) -> Result> { - let mut params = vec![("wait", wait.to_string())]; + let mut params = ArrayVec::<_, 2>::new(); + + params.push(("wait", wait.to_string())); if let Some(thread_id) = thread_id { params.push(("thread_id", thread_id.to_string())); } @@ -2461,7 +2464,7 @@ impl Http { webhook_id, token, }, - params: Some(params), + params, }; if files.is_empty() { @@ -2491,6 +2494,11 @@ impl Http { token: &str, message_id: MessageId, ) -> Result { + let mut params = ArrayVec::<_, 1>::new(); + if let Some(thread_id) = thread_id { + params.push(("thread_id", thread_id.to_string())); + } + self.fire(Request { body: None, multipart: None, @@ -2501,7 +2509,7 @@ impl Http { token, message_id, }, - params: thread_id.map(|thread_id| vec![("thread_id", thread_id.to_string())]), + params, }) .await } @@ -2516,6 +2524,11 @@ impl Http { map: &impl serde::Serialize, new_attachments: Vec, ) -> Result { + let mut params = ArrayVec::<_, 1>::new(); + if let Some(thread_id) = thread_id { + params.push(("thread_id", thread_id.to_string())); + } + let mut request = Request { body: None, multipart: None, @@ -2526,7 +2539,7 @@ impl Http { token, message_id, }, - params: thread_id.map(|thread_id| vec![("thread_id", thread_id.to_string())]), + params, }; if new_attachments.is_empty() { @@ -2550,6 +2563,11 @@ impl Http { token: &str, message_id: MessageId, ) -> Result<()> { + let mut params = ArrayVec::<_, 1>::new(); + if let Some(thread_id) = thread_id { + params.push(("thread_id", thread_id.to_string())); + } + self.wind(204, Request { body: None, multipart: None, @@ -2560,7 +2578,7 @@ impl Http { token, message_id, }, - params: thread_id.map(|thread_id| vec![("thread_id", thread_id.to_string())]), + params, }) .await } @@ -2582,7 +2600,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::StatusMaintenancesActive, - params: None, + params: [].into(), }) .await?; @@ -2605,7 +2623,7 @@ impl Http { target: Option, limit: Option, ) -> Result> { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(limit) = limit { params.push(("limit", limit.to_string())); @@ -2626,7 +2644,7 @@ impl Http { route: Route::GuildBans { guild_id, }, - params: Some(params), + params, }) .await } @@ -2640,7 +2658,7 @@ impl Http { before: Option, limit: Option, ) -> Result { - let mut params = vec![]; + let mut params = ArrayVec::<_, 4>::new(); if let Some(action_type) = action_type { params.push(("action_type", action_type.num().to_string())); } @@ -2662,7 +2680,7 @@ impl Http { route: Route::GuildAuditLogs { guild_id, }, - params: Some(params), + params, }) .await } @@ -2679,7 +2697,7 @@ impl Http { route: Route::GuildAutomodRules { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -2697,7 +2715,7 @@ impl Http { guild_id, rule_id, }, - params: None, + params: [].into(), }) .await } @@ -2721,7 +2739,7 @@ impl Http { route: Route::GuildAutomodRules { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -2747,7 +2765,7 @@ impl Http { guild_id, rule_id, }, - params: None, + params: [].into(), }) .await } @@ -2770,7 +2788,7 @@ impl Http { guild_id, rule_id, }, - params: None, + params: [].into(), }) .await } @@ -2783,7 +2801,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::GatewayBot, - params: None, + params: [].into(), }) .await } @@ -2798,7 +2816,7 @@ impl Http { route: Route::ChannelInvites { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -2816,7 +2834,7 @@ impl Http { route: Route::ChannelThreadMembers { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -2831,7 +2849,7 @@ impl Http { route: Route::GuildThreadsActive { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -2843,7 +2861,7 @@ impl Http { before: Option, limit: Option, ) -> Result { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(before) = before { params.push(("before", before.to_string())); } @@ -2859,7 +2877,7 @@ impl Http { route: Route::ChannelArchivedPublicThreads { channel_id, }, - params: Some(params), + params, }) .await } @@ -2871,7 +2889,7 @@ impl Http { before: Option, limit: Option, ) -> Result { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(before) = before { params.push(("before", before.to_string())); } @@ -2887,7 +2905,7 @@ impl Http { route: Route::ChannelArchivedPrivateThreads { channel_id, }, - params: Some(params), + params, }) .await } @@ -2899,7 +2917,7 @@ impl Http { before: Option, limit: Option, ) -> Result { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(before) = before { params.push(("before", before.to_string())); } @@ -2915,7 +2933,7 @@ impl Http { route: Route::ChannelJoinedPrivateThreads { channel_id, }, - params: Some(params), + params, }) .await } @@ -2930,7 +2948,7 @@ impl Http { route: Route::ChannelThreadMemberMe { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -2945,7 +2963,7 @@ impl Http { route: Route::ChannelThreadMemberMe { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -2965,7 +2983,7 @@ impl Http { channel_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -2985,7 +3003,7 @@ impl Http { channel_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -3019,7 +3037,7 @@ impl Http { route: Route::ChannelWebhooks { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -3034,7 +3052,7 @@ impl Http { route: Route::Channel { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -3049,7 +3067,7 @@ impl Http { route: Route::GuildChannels { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3064,7 +3082,7 @@ impl Http { route: Route::StageInstance { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -3079,7 +3097,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::Oauth2ApplicationCurrent, - params: None, + params: [].into(), }) .await } @@ -3092,7 +3110,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::UserMe, - params: None, + params: [].into(), }) .await } @@ -3107,7 +3125,7 @@ impl Http { route: Route::GuildEmojis { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3123,7 +3141,7 @@ impl Http { guild_id, emoji_id, }, - params: None, + params: [].into(), }) .await } @@ -3187,7 +3205,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::Gateway, - params: None, + params: [].into(), }) .await } @@ -3202,7 +3220,7 @@ impl Http { route: Route::Commands { application_id: self.try_application_id()?, }, - params: None, + params: [].into(), }) .await } @@ -3217,7 +3235,7 @@ impl Http { route: Route::Commands { application_id: self.try_application_id()?, }, - params: Some(vec![("with_localizations", true.to_string())]), + params: [("with_localizations", String::from("true"))].into(), }) .await } @@ -3233,7 +3251,7 @@ impl Http { application_id: self.try_application_id()?, command_id, }, - params: None, + params: [].into(), }) .await } @@ -3248,7 +3266,7 @@ impl Http { route: Route::Guild { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3263,7 +3281,7 @@ impl Http { route: Route::Guild { guild_id, }, - params: Some(vec![("with_counts", true.to_string())]), + params: [("with_counts", String::from("true"))].into(), }) .await } @@ -3279,7 +3297,7 @@ impl Http { application_id: self.try_application_id()?, guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3299,7 +3317,7 @@ impl Http { application_id: self.try_application_id()?, guild_id, }, - params: Some(vec![("with_localizations", true.to_string())]), + params: [("with_localizations", String::from("true"))].into(), }) .await } @@ -3320,7 +3338,7 @@ impl Http { guild_id, command_id, }, - params: None, + params: [].into(), }) .await } @@ -3339,7 +3357,7 @@ impl Http { application_id: self.try_application_id()?, guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3360,7 +3378,7 @@ impl Http { guild_id, command_id, }, - params: None, + params: [].into(), }) .await } @@ -3377,7 +3395,7 @@ impl Http { route: Route::GuildWidget { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3392,7 +3410,7 @@ impl Http { route: Route::GuildPreview { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3407,7 +3425,7 @@ impl Http { route: Route::GuildWelcomeScreen { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3422,7 +3440,7 @@ impl Http { route: Route::GuildIntegrations { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3437,7 +3455,7 @@ impl Http { route: Route::GuildInvites { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3449,7 +3467,7 @@ impl Http { code: String, } - self.fire::(Request { + self.fire(Request { body: None, multipart: None, headers: None, @@ -3457,10 +3475,10 @@ impl Http { route: Route::GuildVanityUrl { guild_id, }, - params: None, + params: [].into(), }) .await - .map(|x| x.code) + .map(|x: GuildVanityUrl| x.code) } /// Gets the members of a guild. Optionally pass a `limit` and the Id of the user to offset the @@ -3477,8 +3495,8 @@ impl Http { } } - let mut params = - vec![("limit", limit.unwrap_or(constants::MEMBER_FETCH_LIMIT).to_string())]; + let mut params = ArrayVec::<_, 2>::new(); + params.push(("limit", limit.unwrap_or(constants::MEMBER_FETCH_LIMIT).to_string())); if let Some(after) = after { params.push(("after", after.to_string())); } @@ -3492,7 +3510,7 @@ impl Http { route: Route::GuildMembers { guild_id, }, - params: Some(params), + params, }) .await?; @@ -3517,7 +3535,7 @@ impl Http { route: Route::GuildPrune { guild_id, }, - params: Some(vec![("days", days.to_string())]), + params: [("days", days.to_string())].into(), }) .await } @@ -3533,7 +3551,7 @@ impl Http { route: Route::GuildRegions { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3549,7 +3567,7 @@ impl Http { route: Route::GuildRoles { guild_id, }, - params: None, + params: [].into(), }) .await?; @@ -3584,7 +3602,7 @@ impl Http { guild_id, event_id, }, - params: Some(vec![("with_user_count", with_user_count.to_string())]), + params: [("with_user_count", with_user_count.to_string())].into(), }) .await } @@ -3607,7 +3625,7 @@ impl Http { route: Route::GuildScheduledEvents { guild_id, }, - params: Some(vec![("with_user_count", with_user_count.to_string())]), + params: [("with_user_count", with_user_count.to_string())].into(), }) .await } @@ -3636,7 +3654,7 @@ impl Http { target: Option, with_member: Option, ) -> Result> { - let mut params = vec![]; + let mut params = ArrayVec::<_, 3>::new(); if let Some(limit) = limit { params.push(("limit", limit.to_string())); } @@ -3659,7 +3677,7 @@ impl Http { guild_id, event_id, }, - params: Some(params), + params, }) .await } @@ -3675,7 +3693,7 @@ impl Http { route: Route::GuildStickers { guild_id, }, - params: None, + params: [].into(), }) .await?; @@ -3706,7 +3724,7 @@ impl Http { guild_id, sticker_id, }, - params: None, + params: [].into(), }) .await?; @@ -3746,7 +3764,7 @@ impl Http { route: Route::GuildWebhooks { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -3782,7 +3800,7 @@ impl Http { target: Option, limit: Option, ) -> Result> { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(limit) = limit { params.push(("limit", limit.to_string())); } @@ -3799,7 +3817,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::UserMeGuilds, - params: Some(params), + params, }) .await } @@ -3843,7 +3861,7 @@ impl Http { route: Route::UserMeGuildMember { guild_id, }, - params: None, + params: [].into(), }) .await?; @@ -3875,10 +3893,9 @@ impl Http { #[cfg(feature = "utils")] let code = crate::utils::parse_invite(code); - let mut params = vec![ - ("member_counts", member_counts.to_string()), - ("expiration", expiration.to_string()), - ]; + let mut params = ArrayVec::<_, 3>::new(); + params.push(("member_counts", member_counts.to_string())); + params.push(("expiration", expiration.to_string())); if let Some(event_id) = event_id { params.push(("event_id", event_id.to_string())); } @@ -3891,7 +3908,7 @@ impl Http { route: Route::Invite { code, }, - params: Some(params), + params, }) .await } @@ -3908,7 +3925,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await?; @@ -3934,7 +3951,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -3946,7 +3963,7 @@ impl Http { target: Option, limit: Option, ) -> Result> { - let mut params = vec![]; + let mut params = ArrayVec::<_, 2>::new(); if let Some(limit) = limit { params.push(("limit", limit.to_string())); } @@ -3966,7 +3983,7 @@ impl Http { route: Route::ChannelMessages { channel_id, }, - params: Some(params), + params, }) .await } @@ -3978,16 +3995,16 @@ impl Http { sticker_packs: Vec, } - self.fire::(Request { + self.fire(Request { body: None, multipart: None, headers: None, method: LightMethod::Get, route: Route::StickerPacks, - params: None, + params: [].into(), }) .await - .map(|s| s.sticker_packs) + .map(|s: StickerPacks| s.sticker_packs) } /// Gets all pins of a channel. @@ -4000,7 +4017,7 @@ impl Http { route: Route::ChannelPins { channel_id, }, - params: None, + params: [].into(), }) .await } @@ -4014,7 +4031,8 @@ impl Http { limit: u8, after: Option, ) -> Result> { - let mut params = vec![("limit", limit.to_string())]; + let mut params = ArrayVec::<_, 2>::new(); + params.push(("limit", limit.to_string())); if let Some(after) = after { params.push(("after", after.to_string())); } @@ -4028,7 +4046,7 @@ impl Http { message_id, reaction: &reaction_type.as_data(), }, - params: Some(params), + params, }) .await } @@ -4058,7 +4076,7 @@ impl Http { route: Route::Sticker { sticker_id, }, - params: None, + params: [].into(), }) .await } @@ -4080,7 +4098,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::StatusIncidentsUnresolved, - params: None, + params: [].into(), }) .await?; @@ -4104,7 +4122,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::StatusMaintenancesUpcoming, - params: None, + params: [].into(), }) .await?; @@ -4121,7 +4139,7 @@ impl Http { route: Route::User { user_id, }, - params: None, + params: [].into(), }) .await } @@ -4138,7 +4156,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::UserMeConnections, - params: None, + params: [].into(), }) .await } @@ -4151,7 +4169,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::UserMeDmChannels, - params: None, + params: [].into(), }) .await } @@ -4164,7 +4182,7 @@ impl Http { headers: None, method: LightMethod::Get, route: Route::VoiceRegions, - params: None, + params: [].into(), }) .await } @@ -4198,7 +4216,7 @@ impl Http { route: Route::Webhook { webhook_id, }, - params: None, + params: [].into(), }) .await } @@ -4238,7 +4256,7 @@ impl Http { webhook_id, token, }, - params: None, + params: [].into(), }) .await } @@ -4275,7 +4293,7 @@ impl Http { webhook_id, token, }, - params: None, + params: [].into(), }) .await } @@ -4296,7 +4314,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -4311,7 +4329,7 @@ impl Http { route: Route::UserMeGuild { guild_id, }, - params: None, + params: [].into(), }) .await } @@ -4335,7 +4353,7 @@ impl Http { route: Route::ChannelMessages { channel_id, }, - params: None, + params: [].into(), }; if files.is_empty() { @@ -4367,7 +4385,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -4388,7 +4406,7 @@ impl Http { guild_id, user_id, }, - params: None, + params: [].into(), }) .await } @@ -4415,7 +4433,7 @@ impl Http { user_id, role_id, }, - params: None, + params: [].into(), }) .await } @@ -4437,10 +4455,11 @@ impl Http { route: Route::GuildMembersSearch { guild_id, }, - params: Some(vec![ + params: [ ("query", query.to_string()), ("limit", limit.unwrap_or(constants::MEMBER_FETCH_LIMIT).to_string()), - ]), + ] + .into(), }) .await?; @@ -4470,7 +4489,7 @@ impl Http { route: Route::GuildPrune { guild_id, }, - params: Some(vec![("days", days.to_string())]), + params: [("days", days.to_string())].into(), }) .await } @@ -4490,7 +4509,7 @@ impl Http { guild_id, integration_id, }, - params: None, + params: [].into(), }) .await } @@ -4551,7 +4570,7 @@ impl Http { channel_id, message_id, }, - params: None, + params: [].into(), }) .await } @@ -4581,9 +4600,9 @@ impl Http { /// let channel_id = ChannelId::new(381880193700069377); /// let route = Route::ChannelMessages { channel_id }; /// - /// let mut request = Request::new(route, LightMethod::Post).body(Some(bytes)); + /// let mut request = Request::new(route, LightMethod::Post, []).body(Some(bytes)); /// - /// let message = http.fire::(request).await?; + /// let message: Message = http.fire(request).await?; /// /// println!("Message content: {}", message.content); /// # Ok(()) @@ -4593,7 +4612,10 @@ impl Http { /// # Errors /// /// If there is an error, it will be either [`Error::Http`] or [`Error::Json`]. - pub async fn fire(&self, req: Request<'_>) -> Result { + pub async fn fire( + &self, + req: Request<'_, MAX_PARAMS>, + ) -> Result { let response = self.request(req).await?; decode_resp(response).await } @@ -4621,7 +4643,7 @@ impl Http { /// let channel_id = ChannelId::new(381880193700069377); /// let route = Route::ChannelMessages { channel_id }; /// - /// let mut request = Request::new(route, LightMethod::Post).body(Some(bytes)); + /// let mut request = Request::new(route, LightMethod::Post, []).body(Some(bytes)); /// /// let response = http.request(request).await?; /// @@ -4630,7 +4652,10 @@ impl Http { /// # } /// ``` #[instrument] - pub async fn request(&self, req: Request<'_>) -> Result { + pub async fn request( + &self, + req: Request<'_, MAX_PARAMS>, + ) -> Result { let method = req.method.reqwest_method(); let response = if let Some(ratelimiter) = &self.ratelimiter { ratelimiter.perform(req).await? @@ -4653,7 +4678,11 @@ impl Http { /// /// This is a function that performs a light amount of work and returns an empty tuple, so it's /// called "self.wind" to denote that it's lightweight. - pub(super) async fn wind(&self, expected: u16, req: Request<'_>) -> Result<()> { + pub(super) async fn wind( + &self, + expected: u16, + req: Request<'_, MAX_PARAMS>, + ) -> Result<()> { let method = req.method.reqwest_method(); let response = self.request(req).await?; diff --git a/src/http/ratelimiting.rs b/src/http/ratelimiting.rs index cb6904394c5..8fa7928027e 100644 --- a/src/http/ratelimiting.rs +++ b/src/http/ratelimiting.rs @@ -179,7 +179,10 @@ impl Ratelimiter { /// /// Only error kind that may be returned is [`Error::Http`]. #[instrument] - pub async fn perform(&self, req: Request<'_>) -> Result { + pub async fn perform( + &self, + req: Request<'_, MAX_PARAMS>, + ) -> Result { loop { // This will block if another thread hit the global ratelimit. drop(self.global.lock().await); @@ -278,9 +281,9 @@ pub struct Ratelimit { impl Ratelimit { #[instrument(skip(ratelimit_callback))] - pub async fn pre_hook( + pub async fn pre_hook( &mut self, - req: &Request<'_>, + req: &Request<'_, MAX_PARAMS>, ratelimit_callback: &(dyn Fn(RatelimitInfo) + Send + Sync), ) { if self.limit() == 0 { @@ -324,10 +327,10 @@ impl Ratelimit { } #[instrument(skip(ratelimit_callback))] - pub async fn post_hook( + pub async fn post_hook( &mut self, response: &Response, - req: &Request<'_>, + req: &Request<'_, MAX_PARAMS>, ratelimit_callback: &(dyn Fn(RatelimitInfo) + Send + Sync), absolute_ratelimits: bool, ) -> Result { diff --git a/src/http/request.rs b/src/http/request.rs index 0419116fb6b..80235c37928 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -1,5 +1,6 @@ use std::fmt::Write; +use arrayvec::ArrayVec; use reqwest::header::{ HeaderMap as Headers, HeaderValue, @@ -18,28 +19,32 @@ use crate::constants; use crate::internal::prelude::*; #[deprecated = "use Request directly now"] -pub type RequestBuilder<'a> = Request<'a>; +pub type RequestBuilder<'a, const MAX_PARAMS: usize> = Request<'a, MAX_PARAMS>; #[derive(Clone, Debug)] #[must_use] -pub struct Request<'a> { +pub struct Request<'a, const MAX_PARAMS: usize> { pub(super) body: Option>, pub(super) multipart: Option, pub(super) headers: Option, pub(super) method: LightMethod, pub(super) route: Route<'a>, - pub(super) params: Option>, + pub(super) params: ArrayVec<(&'static str, String), MAX_PARAMS>, } -impl<'a> Request<'a> { - pub const fn new(route: Route<'a>, method: LightMethod) -> Self { +impl<'a, const MAX_PARAMS: usize> Request<'a, MAX_PARAMS> { + pub fn new( + route: Route<'a>, + method: LightMethod, + params: [(&'static str, String); MAX_PARAMS], + ) -> Self { Self { body: None, multipart: None, headers: None, method, route, - params: None, + params: params.into(), } } @@ -58,8 +63,8 @@ impl<'a> Request<'a> { self } - pub fn params(mut self, params: Option>) -> Self { - self.params = params; + pub fn params(mut self, params: [(&'static str, String); MAX_PARAMS]) -> Self { + self.params = params.into(); self } @@ -77,9 +82,9 @@ impl<'a> Request<'a> { path = path.replace("https://discord.com", proxy.trim_end_matches('/')); } - if let Some(params) = self.params { + if !self.params.is_empty() { path += "?"; - for (param, value) in params { + for (param, value) in self.params { write!(path, "&{param}={value}").unwrap(); } } @@ -138,11 +143,19 @@ impl<'a> Request<'a> { #[must_use] pub fn params_ref(&self) -> Option<&[(&'static str, String)]> { - self.params.as_deref() + if self.params.is_empty() { + None + } else { + Some(&self.params) + } } #[must_use] pub fn params_mut(&mut self) -> Option<&mut [(&'static str, String)]> { - self.params.as_deref_mut() + if self.params.is_empty() { + None + } else { + Some(&mut self.params) + } } }