diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index b7c42e1..f2de33d 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -10,7 +10,7 @@ use crate::{ }; /// Useful metadata for working with [`types::Reaction`], bundled together nicely. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, PartialOrd, Ord)] pub struct ReactionMeta { pub message_id: types::Snowflake, pub channel_id: types::Snowflake, diff --git a/src/gateway/backends/tungstenite.rs b/src/gateway/backends/tungstenite.rs index 7e00771..34dc825 100644 --- a/src/gateway/backends/tungstenite.rs +++ b/src/gateway/backends/tungstenite.rs @@ -14,7 +14,7 @@ use tokio_tungstenite::{ use crate::gateway::{GatewayMessage, RawGatewayMessage}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct TungsteniteBackend; // These could be made into inherent associated types when that's stabilized diff --git a/src/gateway/handle.rs b/src/gateway/handle.rs index bfaeb17..6bcdba8 100644 --- a/src/gateway/handle.rs +++ b/src/gateway/handle.rs @@ -154,7 +154,7 @@ impl GatewayHandle { /// Sends a call sync to the server pub async fn send_call_sync(&self, to_send: types::CallSync) { - let to_send_value = serde_json::to_value(&to_send).unwrap(); + let to_send_value = serde_json::to_value(to_send).unwrap(); trace!("GW: Sending Call Sync.."); diff --git a/src/gateway/mod.rs b/src/gateway/mod.rs index fcbd125..4550a2f 100644 --- a/src/gateway/mod.rs +++ b/src/gateway/mod.rs @@ -2,7 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use async_trait::async_trait; pub mod backends; pub mod events; @@ -20,7 +19,7 @@ pub use message::*; pub use options::*; use crate::errors::GatewayError; -use crate::types::{Snowflake, WebSocketEvent}; +use crate::types::{Snowflake}; use std::any::Any; use std::collections::HashMap; diff --git a/src/gateway/options.rs b/src/gateway/options.rs index e5c0314..23942b2 100644 --- a/src/gateway/options.rs +++ b/src/gateway/options.rs @@ -2,7 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Debug, Default, Copy)] /// Options passed when initializing the gateway connection. /// /// E.g. compression @@ -17,8 +17,8 @@ /// /// See pub struct GatewayOptions { - pub encoding: GatewayEncoding, - pub transport_compression: GatewayTransportCompression, + pub encoding: GatewayEncoding, + pub transport_compression: GatewayTransportCompression, } impl GatewayOptions { @@ -26,11 +26,10 @@ impl GatewayOptions { /// /// Returns the new url pub(crate) fn add_to_url(&self, url: String) -> String { - let mut url = url; let mut parameters = Vec::with_capacity(2); - + let encoding = self.encoding.to_url_parameter(); parameters.push(encoding); @@ -54,8 +53,7 @@ impl GatewayOptions { if !has_parameters { url = format!("{}?{}", url, parameter); has_parameters = true; - } - else { + } else { url = format!("{}&{}", url, parameter); } } @@ -78,15 +76,15 @@ pub enum GatewayTransportCompression { impl GatewayTransportCompression { /// Returns the option as a url parameter. - /// + /// /// If set to [GatewayTransportCompression::None] returns [None]. /// /// If set to anything else, returns a string like "compress=zlib-stream" pub(crate) fn to_url_parameter(self) -> Option { - match self { - Self::None => None, - Self::ZLibStream => Some(String::from("compress=zlib-stream")) - } + match self { + Self::None => None, + Self::ZLibStream => Some(String::from("compress=zlib-stream")), + } } } @@ -102,17 +100,17 @@ pub enum GatewayEncoding { /// Should be lighter and faster than json. /// /// !! Chorus does not implement ETF yet !! - ETF + ETF, } impl GatewayEncoding { /// Returns the option as a url parameter. - /// + /// /// Returns a string like "encoding=json" pub(crate) fn to_url_parameter(self) -> String { - match self { - Self::Json => String::from("encoding=json"), - Self::ETF => String::from("encoding=etf") - } + match self { + Self::Json => String::from("encoding=json"), + Self::ETF => String::from("encoding=etf"), + } } } diff --git a/src/instance.rs b/src/instance.rs index e6ba5c8..f826ab5 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -35,24 +35,6 @@ pub struct Instance { pub gateway_options: GatewayOptions, } -impl PartialEq for Instance { - fn eq(&self, other: &Self) -> bool { - self.urls == other.urls - && self.instance_info == other.instance_info - && self.limits_information == other.limits_information - } -} - -impl std::hash::Hash for Instance { - fn hash(&self, state: &mut H) { - self.urls.hash(state); - self.instance_info.hash(state); - if let Some(inf) = &self.limits_information { - inf.hash(state); - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq)] pub struct LimitsInformation { pub ratelimits: HashMap, @@ -69,6 +51,7 @@ impl std::hash::Hash for LimitsInformation { } } +#[cfg(not(tarpaulin_include))] impl PartialEq for LimitsInformation { fn eq(&self, other: &Self) -> bool { self.ratelimits.iter().eq(other.ratelimits.iter()) @@ -175,14 +158,6 @@ pub struct ChorusUser { pub gateway: GatewayHandle, } -impl PartialEq for ChorusUser { - fn eq(&self, other: &Self) -> bool { - self.token == other.token - && self.limits == other.limits - && self.gateway.url == other.gateway.url - } -} - impl ChorusUser { pub fn token(&self) -> String { self.token.clone() diff --git a/src/lib.rs b/src/lib.rs index 6ffd8b8..7767480 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,6 @@ This crate uses Semantic Versioning 2.0.0 as its versioning scheme. You can read )] #![allow(clippy::module_inception)] #![deny( - missing_debug_implementations, clippy::extra_unused_lifetimes, clippy::from_over_into, clippy::needless_borrow, @@ -110,7 +109,9 @@ This crate uses Semantic Versioning 2.0.0 as its versioning scheme. You can read clippy::unimplemented, clippy::dbg_macro, clippy::print_stdout, - clippy::print_stderr + clippy::print_stderr, + missing_debug_implementations, + missing_copy_implementations )] #[cfg(all(feature = "rt", feature = "rt_multi_thread"))] compile_error!("feature \"rt\" and feature \"rt_multi_thread\" cannot be enabled at the same time"); diff --git a/src/types/config/types/defaults_configuration.rs b/src/types/config/types/defaults_configuration.rs index e6e0867..f607c9b 100644 --- a/src/types/config/types/defaults_configuration.rs +++ b/src/types/config/types/defaults_configuration.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::types::config::types::subconfigs::defaults::{guild::GuildDefaults, user::UserDefaults}; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Copy)] #[serde(rename_all = "camelCase")] pub struct DefaultsConfiguration { pub guild: GuildDefaults, diff --git a/src/types/config/types/login_configuration.rs b/src/types/config/types/login_configuration.rs index 83125e0..ed797b5 100644 --- a/src/types/config/types/login_configuration.rs +++ b/src/types/config/types/login_configuration.rs @@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord, +)] #[serde(rename_all = "camelCase")] pub struct LoginConfiguration { pub require_captcha: bool, diff --git a/src/types/config/types/metrics_configuration.rs b/src/types/config/types/metrics_configuration.rs index 98d3536..d11644b 100644 --- a/src/types/config/types/metrics_configuration.rs +++ b/src/types/config/types/metrics_configuration.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Copy, Hash)] #[serde(rename_all = "camelCase")] pub struct MetricsConfiguration { pub timeout: u64, diff --git a/src/types/config/types/password_reset_configuration.rs b/src/types/config/types/password_reset_configuration.rs index d1c730e..e7de663 100644 --- a/src/types/config/types/password_reset_configuration.rs +++ b/src/types/config/types/password_reset_configuration.rs @@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord, +)] #[serde(rename_all = "camelCase")] pub struct PasswordResetConfiguration { pub require_captcha: bool, diff --git a/src/types/config/types/subconfigs/defaults/guild.rs b/src/types/config/types/subconfigs/defaults/guild.rs index 8509fe5..f33f279 100644 --- a/src/types/config/types/subconfigs/defaults/guild.rs +++ b/src/types/config/types/subconfigs/defaults/guild.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::types::{ExplicitContentFilterLevel, MessageNotificationLevel}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct GuildDefaults { pub max_presences: u64, diff --git a/src/types/config/types/subconfigs/defaults/user.rs b/src/types/config/types/subconfigs/defaults/user.rs index d7dc7b3..a533b0a 100644 --- a/src/types/config/types/subconfigs/defaults/user.rs +++ b/src/types/config/types/subconfigs/defaults/user.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct UserDefaults { pub premium: bool, diff --git a/src/types/config/types/subconfigs/guild/discovery.rs b/src/types/config/types/subconfigs/guild/discovery.rs index 50738f1..689528b 100644 --- a/src/types/config/types/subconfigs/guild/discovery.rs +++ b/src/types/config/types/subconfigs/guild/discovery.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] #[serde(rename_all = "camelCase")] pub struct DiscoverConfiguration { pub show_all_guilds: bool, diff --git a/src/types/config/types/subconfigs/limits/channel.rs b/src/types/config/types/subconfigs/limits/channel.rs index 2415726..9e03283 100644 --- a/src/types/config/types/subconfigs/limits/channel.rs +++ b/src/types/config/types/subconfigs/limits/channel.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct ChannelLimits { pub max_pins: u16, diff --git a/src/types/config/types/subconfigs/limits/global.rs b/src/types/config/types/subconfigs/limits/global.rs index 0140447..2a23bf4 100644 --- a/src/types/config/types/subconfigs/limits/global.rs +++ b/src/types/config/types/subconfigs/limits/global.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub struct GlobalRateLimit { pub limit: u16, pub window: u64, @@ -21,7 +21,7 @@ impl Default for GlobalRateLimit { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] #[serde(rename_all = "camelCase")] pub struct GlobalRateLimits { pub register: GlobalRateLimit, diff --git a/src/types/config/types/subconfigs/limits/guild.rs b/src/types/config/types/subconfigs/limits/guild.rs index 9ef8f90..4c58404 100644 --- a/src/types/config/types/subconfigs/limits/guild.rs +++ b/src/types/config/types/subconfigs/limits/guild.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct GuildLimits { pub max_roles: u16, diff --git a/src/types/config/types/subconfigs/limits/message.rs b/src/types/config/types/subconfigs/limits/message.rs index 3beb76e..fc2237b 100644 --- a/src/types/config/types/subconfigs/limits/message.rs +++ b/src/types/config/types/subconfigs/limits/message.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] #[serde(rename_all = "camelCase")] pub struct MessageLimits { pub max_characters: u32, diff --git a/src/types/config/types/subconfigs/limits/ratelimits/auth.rs b/src/types/config/types/subconfigs/limits/ratelimits/auth.rs index 78f1908..25adcab 100644 --- a/src/types/config/types/subconfigs/limits/ratelimits/auth.rs +++ b/src/types/config/types/subconfigs/limits/ratelimits/auth.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::types::config::types::subconfigs::limits::ratelimits::RateLimitOptions; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub struct AuthRateLimit { pub login: RateLimitOptions, pub register: RateLimitOptions, diff --git a/src/types/config/types/subconfigs/limits/ratelimits/mod.rs b/src/types/config/types/subconfigs/limits/ratelimits/mod.rs index 501afe9..16106cd 100644 --- a/src/types/config/types/subconfigs/limits/ratelimits/mod.rs +++ b/src/types/config/types/subconfigs/limits/ratelimits/mod.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; pub mod auth; pub mod route; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, PartialOrd, Ord, Copy)] #[serde(rename_all = "camelCase")] pub struct RateLimitOptions { pub bot: Option, diff --git a/src/types/config/types/subconfigs/limits/ratelimits/route.rs b/src/types/config/types/subconfigs/limits/ratelimits/route.rs index 7c70fdc..8379c26 100644 --- a/src/types/config/types/subconfigs/limits/ratelimits/route.rs +++ b/src/types/config/types/subconfigs/limits/ratelimits/route.rs @@ -8,7 +8,7 @@ use crate::types::config::types::subconfigs::limits::ratelimits::{ auth::AuthRateLimit, RateLimitOptions, }; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Copy, PartialOrd, Ord)] pub struct RouteRateLimit { pub guild: RateLimitOptions, pub webhook: RateLimitOptions, diff --git a/src/types/config/types/subconfigs/limits/rates.rs b/src/types/config/types/subconfigs/limits/rates.rs index 4c9b9a1..e837d96 100644 --- a/src/types/config/types/subconfigs/limits/rates.rs +++ b/src/types/config/types/subconfigs/limits/rates.rs @@ -50,14 +50,14 @@ impl Default for RateLimits { impl RateLimits { pub fn to_hash_map(&self) -> HashMap { let mut map = HashMap::new(); - map.insert(LimitType::AuthLogin, self.routes.auth.login.clone()); - map.insert(LimitType::AuthRegister, self.routes.auth.register.clone()); - map.insert(LimitType::ChannelBaseline, self.routes.channel.clone()); - map.insert(LimitType::Error, self.error.clone()); - map.insert(LimitType::Global, self.global.clone()); - map.insert(LimitType::Ip, self.ip.clone()); - map.insert(LimitType::WebhookBaseline, self.routes.webhook.clone()); - map.insert(LimitType::GuildBaseline, self.routes.guild.clone()); + map.insert(LimitType::AuthLogin, self.routes.auth.login); + map.insert(LimitType::AuthRegister, self.routes.auth.register); + map.insert(LimitType::ChannelBaseline, self.routes.channel); + map.insert(LimitType::Error, self.error); + map.insert(LimitType::Global, self.global); + map.insert(LimitType::Ip, self.ip); + map.insert(LimitType::WebhookBaseline, self.routes.webhook); + map.insert(LimitType::GuildBaseline, self.routes.guild); map } } diff --git a/src/types/config/types/subconfigs/limits/user.rs b/src/types/config/types/subconfigs/limits/user.rs index 473535a..4ac0e9d 100644 --- a/src/types/config/types/subconfigs/limits/user.rs +++ b/src/types/config/types/subconfigs/limits/user.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Copy, Hash)] #[serde(rename_all = "camelCase")] pub struct UserLimits { pub max_guilds: u64, diff --git a/src/types/config/types/subconfigs/region/mod.rs b/src/types/config/types/subconfigs/region/mod.rs index 1661c09..42ad564 100644 --- a/src/types/config/types/subconfigs/region/mod.rs +++ b/src/types/config/types/subconfigs/region/mod.rs @@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, PartialOrd, Copy)] pub struct LatLong { pub latitude: f64, pub longitude: f64, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, PartialOrd)] pub struct Region { pub id: String, pub name: String, diff --git a/src/types/config/types/subconfigs/register/date_of_birth.rs b/src/types/config/types/subconfigs/register/date_of_birth.rs index 6689297..961fca4 100644 --- a/src/types/config/types/subconfigs/register/date_of_birth.rs +++ b/src/types/config/types/subconfigs/register/date_of_birth.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub struct DateOfBirthConfiguration { pub required: bool, pub minimum: u8, diff --git a/src/types/config/types/subconfigs/register/password.rs b/src/types/config/types/subconfigs/register/password.rs index 1d380ba..a192dc5 100644 --- a/src/types/config/types/subconfigs/register/password.rs +++ b/src/types/config/types/subconfigs/register/password.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] #[serde(rename_all = "camelCase")] pub struct PasswordConfiguration { pub required: bool, diff --git a/src/types/config/types/subconfigs/security/twofactor.rs b/src/types/config/types/subconfigs/security/twofactor.rs index 1182a45..248ba11 100644 --- a/src/types/config/types/subconfigs/security/twofactor.rs +++ b/src/types/config/types/subconfigs/security/twofactor.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct TwoFactorConfiguration { pub generate_backup_codes: bool, diff --git a/src/types/config/types/template_configuration.rs b/src/types/config/types/template_configuration.rs index 9f370b4..b88fe2e 100644 --- a/src/types/config/types/template_configuration.rs +++ b/src/types/config/types/template_configuration.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] #[serde(rename_all = "camelCase")] pub struct TemplateConfiguration { pub enabled: bool, diff --git a/src/types/entities/application.rs b/src/types/entities/application.rs index ac4cb97..f265f21 100644 --- a/src/types/entities/application.rs +++ b/src/types/entities/application.rs @@ -7,10 +7,13 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::types::Shared; use crate::types::utils::Snowflake; +use crate::types::Shared; use crate::types::{Team, User}; +#[allow(unused_imports)] +use super::{arc_rwlock_ptr_eq, option_arc_rwlock_ptr_eq}; + #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// # Reference @@ -59,6 +62,61 @@ pub struct Application { pub team: Option, } +#[cfg(not(tarpaulin_include))] +impl PartialEq for Application { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.name == other.name + && self.icon == other.icon + && self.description == other.description + && self.summary == other.summary + && self.r#type == other.r#type + && self.hook == other.hook + && self.bot_public == other.bot_public + && self.bot_require_code_grant == other.bot_require_code_grant + && self.verify_key == other.verify_key + && arc_rwlock_ptr_eq(&self.owner, &other.owner) + && self.flags == other.flags + && self.redirect_uris == other.redirect_uris + && self.rpc_application_state == other.rpc_application_state + && self.store_application_state == other.store_application_state + && self.verification_state == other.verification_state + && self.interactions_endpoint_url == other.interactions_endpoint_url + && self.integration_public == other.integration_public + && self.integration_require_code_grant == other.integration_require_code_grant + && self.discoverability_state == other.discoverability_state + && self.discovery_eligibility_flags == other.discovery_eligibility_flags + && self.tags == other.tags + && self.cover_image == other.cover_image + && compare_install_params(&self.install_params, &other.install_params) + && self.terms_of_service_url == other.terms_of_service_url + && self.privacy_policy_url == other.privacy_policy_url + && self.team == other.team + } +} + +#[cfg(not(tarpaulin_include))] +#[cfg(feature = "sqlx")] +fn compare_install_params( + a: &Option>, + b: &Option>, +) -> bool { + match (a, b) { + (Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), + (None, None) => true, + _ => false, + } +} + +#[cfg(not(tarpaulin_include))] +#[cfg(not(feature = "sqlx"))] +fn compare_install_params( + a: &Option>, + b: &Option>, +) -> bool { + option_arc_rwlock_ptr_eq(a, b) +} + impl Default for Application { fn default() -> Self { Self { @@ -207,7 +265,9 @@ pub struct GuildApplicationCommandPermissions { pub permissions: Vec>, } -#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[derive( + Debug, Default, Clone, PartialEq, Serialize, Deserialize, Copy, Eq, Hash, PartialOrd, Ord, +)] /// See pub struct ApplicationCommandPermission { pub id: Snowflake, @@ -217,7 +277,19 @@ pub struct ApplicationCommandPermission { pub permission: bool, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, PartialEq, Eq, Hash)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + PartialEq, + Eq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[repr(u8)] /// See diff --git a/src/types/entities/audit_log.rs b/src/types/entities/audit_log.rs index 48dc9d4..17f3275 100644 --- a/src/types/entities/audit_log.rs +++ b/src/types/entities/audit_log.rs @@ -2,11 +2,16 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#[allow(unused_imports)] +use super::option_vec_arc_rwlock_ptr_eq; + use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::types::{AutoModerationRuleTriggerType, IntegrationType, PermissionOverwriteType, Shared}; use crate::types::utils::Snowflake; +use crate::types::{ + AutoModerationRuleTriggerType, IntegrationType, PermissionOverwriteType, Shared, +}; #[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -27,6 +32,55 @@ pub struct AuditLogEntry { pub reason: Option, } +impl PartialEq for AuditLogEntry { + fn eq(&self, other: &Self) -> bool { + self.target_id == other.target_id + && self.user_id == other.user_id + && self.id == other.id + && self.action_type == other.action_type + && compare_options(&self.options, &other.options) + && self.reason == other.reason + && compare_changes(&self.changes, &other.changes) + } +} + +#[cfg(not(tarpaulin_include))] +#[cfg(feature = "sqlx")] +fn compare_options( + a: &Option>, + b: &Option>, +) -> bool { + match (a, b) { + (Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), + (None, None) => true, + _ => false, + } +} + +#[cfg(not(tarpaulin_include))] +#[cfg(not(feature = "sqlx"))] +fn compare_options(a: &Option, b: &Option) -> bool { + a == b +} + +#[cfg(not(tarpaulin_include))] +#[cfg(feature = "sqlx")] +fn compare_changes( + a: &sqlx::types::Json>>>, + b: &sqlx::types::Json>>>, +) -> bool { + a.encode_to_string() == b.encode_to_string() +} + +#[cfg(not(tarpaulin_include))] +#[cfg(not(feature = "sqlx"))] +fn compare_changes( + a: &Option>>, + b: &Option>>, +) -> bool { + option_vec_arc_rwlock_ptr_eq(a, b) +} + #[derive(Serialize, Deserialize, Debug, Default, Clone)] /// See pub struct AuditLogChange { @@ -35,8 +89,19 @@ pub struct AuditLogChange { pub key: String, } - -#[derive(Default, Serialize_repr, Deserialize_repr, Debug, Clone, Copy)] +#[derive( + Default, + Serialize_repr, + Deserialize_repr, + Debug, + Clone, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, +)] #[repr(u8)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] /// # Reference: @@ -170,10 +235,10 @@ pub enum AuditLogActionType { /// Voice channel status was updated VoiceChannelStatusUpdate = 192, /// Voice channel status was deleted - VoiceChannelStatusDelete = 193 + VoiceChannelStatusDelete = 193, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] pub struct AuditEntryInfo { pub application_id: Option, pub auto_moderation_rule_name: Option, @@ -193,5 +258,5 @@ pub struct AuditEntryInfo { pub role_name: Option, #[serde(rename = "type")] pub overwrite_type: Option, - pub status: Option -} \ No newline at end of file + pub status: Option, +} diff --git a/src/types/entities/auto_moderation.rs b/src/types/entities/auto_moderation.rs index 021185e..3caa16c 100644 --- a/src/types/entities/auto_moderation.rs +++ b/src/types/entities/auto_moderation.rs @@ -2,9 +2,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use crate::types::Shared; #[cfg(feature = "client")] use crate::gateway::Updateable; +use crate::types::Shared; #[cfg(feature = "client")] use chorus_macros::Updateable; @@ -31,7 +31,7 @@ pub struct AutoModerationRule { pub exempt_channels: Vec, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default, Copy)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -40,7 +40,9 @@ pub enum AutoModerationRuleEventType { MessageSend = 1, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] +#[derive( + Serialize_repr, Deserialize_repr, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy, +)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -52,7 +54,7 @@ pub enum AutoModerationRuleTriggerType { MentionSpam = 5, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] #[serde(untagged)] /// See pub enum AutoModerationRuleTriggerMetadata { @@ -63,7 +65,7 @@ pub enum AutoModerationRuleTriggerMetadata { None, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] /// See pub struct AutoModerationRuleTriggerMetadataForKeyword { pub keyword_filter: Vec, @@ -71,14 +73,14 @@ pub struct AutoModerationRuleTriggerMetadataForKeyword { pub allow_list: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] /// See pub struct AutoModerationRuleTriggerMetadataForKeywordPreset { pub presets: Vec, pub allow_list: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy)] /// See pub struct AutoModerationRuleTriggerMetadataForMentionSpam { /// Max 50 @@ -86,7 +88,9 @@ pub struct AutoModerationRuleTriggerMetadataForMentionSpam { pub mention_raid_protection_enabled: bool, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] +#[derive( + Serialize_repr, Deserialize_repr, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy, +)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -105,7 +109,9 @@ pub struct AutoModerationAction { pub metadata: Option>, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] +#[derive( + Serialize_repr, Deserialize_repr, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy, Hash +)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See @@ -116,7 +122,7 @@ pub enum AutoModerationActionType { Timeout = 3, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] #[serde(untagged)] /// See pub enum AutoModerationActionMetadata { @@ -127,19 +133,19 @@ pub enum AutoModerationActionMetadata { None, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] /// See pub struct AutoModerationActionMetadataForBlockMessage { pub custom_message: Option, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy)] /// See pub struct AutoModerationActionMetadataForSendAlertMessage { pub channel_id: Snowflake, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Copy)] /// See pub struct AutoModerationActionMetadataForTimeout { /// Max 2419200 diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index 19bdcef..622f14d 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -9,10 +9,9 @@ use std::fmt::{Debug, Formatter}; use std::str::FromStr; use crate::types::{ - PermissionFlags, Shared, entities::{GuildMember, User}, utils::Snowflake, - serde::string_or_u64 + PermissionFlags, Shared, }; #[cfg(feature = "client")] @@ -28,6 +27,10 @@ use crate::gateway::Updateable; use chorus_macros::{observe_option_vec, Composite, Updateable}; use serde::de::{Error, Visitor}; +#[cfg(feature = "sqlx")] +use sqlx::types::Json; + +use super::{option_arc_rwlock_ptr_eq, option_vec_arc_rwlock_ptr_eq}; #[derive(Default, Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -97,14 +100,22 @@ pub struct Channel { pub video_quality_mode: Option, } +#[cfg(not(tarpaulin_include))] +#[allow(clippy::nonminimal_bool)] impl PartialEq for Channel { fn eq(&self, other: &Self) -> bool { self.application_id == other.application_id + && self.applied_tags == other.applied_tags + && self.applied_tags == other.applied_tags + && self.available_tags == other.available_tags + && self.available_tags == other.available_tags && self.bitrate == other.bitrate && self.channel_type == other.channel_type && self.created_at == other.created_at && self.default_auto_archive_duration == other.default_auto_archive_duration && self.default_forum_layout == other.default_forum_layout + && self.default_reaction_emoji == other.default_reaction_emoji + && self.default_reaction_emoji == other.default_reaction_emoji && self.default_sort_order == other.default_sort_order && self.default_thread_rate_limit_per_user == other.default_thread_rate_limit_per_user && self.flags == other.flags @@ -114,16 +125,23 @@ impl PartialEq for Channel { && self.last_message_id == other.last_message_id && self.last_pin_timestamp == other.last_pin_timestamp && self.managed == other.managed + && self.member == other.member && self.member_count == other.member_count && self.message_count == other.message_count && self.name == other.name && self.nsfw == other.nsfw && self.owner_id == other.owner_id && self.parent_id == other.parent_id + && compare_permission_overwrites( + &self.permission_overwrites, + &other.permission_overwrites, + ) && self.permissions == other.permissions && self.position == other.position && self.rate_limit_per_user == other.rate_limit_per_user + && option_vec_arc_rwlock_ptr_eq(&self.recipients, &other.recipients) && self.rtc_region == other.rtc_region + && self.thread_metadata == other.thread_metadata && self.topic == other.topic && self.total_message_sent == other.total_message_sent && self.user_limit == other.user_limit @@ -131,7 +149,29 @@ impl PartialEq for Channel { } } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[cfg(not(tarpaulin_include))] +#[cfg(feature = "sqlx")] +fn compare_permission_overwrites( + a: &Option>>, + b: &Option>>, +) -> bool { + match (a, b) { + (Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), + (None, None) => true, + _ => false, + } +} + +#[cfg(not(tarpaulin_include))] +#[cfg(not(feature = "sqlx"))] +fn compare_permission_overwrites( + a: &Option>>, + b: &Option>>, +) -> bool { + option_vec_arc_rwlock_ptr_eq(a, b) +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] /// A tag that can be applied to a thread in a [ChannelType::GuildForum] or [ChannelType::GuildMedia] channel. /// /// # Reference @@ -158,8 +198,7 @@ pub struct PermissionOverwrite { pub deny: PermissionFlags, } - -#[derive(Debug, Serialize_repr, Clone, PartialEq, Eq, PartialOrd)] +#[derive(Debug, Serialize_repr, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] #[repr(u8)] /// # Reference /// @@ -200,33 +239,47 @@ impl<'de> Visitor<'de> for PermissionOverwriteTypeVisitor { formatter.write_str("a valid permission overwrite type") } - fn visit_u8(self, v: u8) -> Result where E: Error { + fn visit_u8(self, v: u8) -> Result + where + E: Error, + { Ok(PermissionOverwriteType::from(v)) } - fn visit_u64(self, v: u64) -> Result where E: Error { + fn visit_u64(self, v: u64) -> Result + where + E: Error, + { self.visit_u8(v as u8) } - fn visit_str(self, v: &str) -> Result where E: Error { - PermissionOverwriteType::from_str(v) - .map_err(E::custom) + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + PermissionOverwriteType::from_str(v).map_err(E::custom) } - fn visit_string(self, v: String) -> Result where E: Error { + fn visit_string(self, v: String) -> Result + where + E: Error, + { self.visit_str(v.as_str()) } } impl<'de> Deserialize<'de> for PermissionOverwriteType { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let val = deserializer.deserialize_any(PermissionOverwriteTypeVisitor)?; Ok(val) } } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] /// # Reference /// See pub struct ThreadMetadata { @@ -249,6 +302,17 @@ pub struct ThreadMember { pub member: Option>, } +#[cfg(not(tarpaulin_include))] +impl PartialEq for ThreadMember { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.user_id == other.user_id + && self.join_timestamp == other.join_timestamp + && self.flags == other.flags + && option_arc_rwlock_ptr_eq(&self.member, &other.member) + } +} + #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd)] /// Specifies the emoji to use as the default way to react to a [ChannelType::GuildForum] or [ChannelType::GuildMedia] channel post. /// @@ -329,11 +393,10 @@ pub enum ChannelType { Unhandled = 255, } - /// # Reference /// See -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy, Hash, PartialOrd, Ord)] pub struct FollowedChannel { pub channel_id: Snowflake, - pub webhook_id: Snowflake + pub webhook_id: Snowflake, } diff --git a/src/types/entities/emoji.rs b/src/types/entities/emoji.rs index 23956b5..82f3e37 100644 --- a/src/types/entities/emoji.rs +++ b/src/types/entities/emoji.rs @@ -6,9 +6,9 @@ use std::fmt::Debug; use serde::{Deserialize, Serialize}; -use crate::types::{PartialEmoji, Shared}; use crate::types::entities::User; use crate::types::Snowflake; +use crate::types::{PartialEmoji, Shared}; #[cfg(feature = "client")] use crate::gateway::GatewayHandle; @@ -22,6 +22,8 @@ use crate::gateway::Updateable; #[cfg(feature = "client")] use chorus_macros::{Composite, Updateable}; +use super::option_arc_rwlock_ptr_eq; + #[derive(Debug, Clone, Deserialize, Serialize, Default)] #[cfg_attr(feature = "client", derive(Updateable, Composite))] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -42,35 +44,26 @@ pub struct Emoji { pub available: Option, } -impl std::hash::Hash for Emoji { - fn hash(&self, state: &mut H) { - self.id.hash(state); - self.name.hash(state); - self.roles.hash(state); - self.roles.hash(state); - self.require_colons.hash(state); - self.managed.hash(state); - self.animated.hash(state); - self.available.hash(state); - } -} - +#[cfg(not(tarpaulin_include))] +#[allow(clippy::nonminimal_bool)] impl PartialEq for Emoji { fn eq(&self, other: &Self) -> bool { - !(self.id != other.id - || self.name != other.name - || self.roles != other.roles - || self.require_colons != other.require_colons - || self.managed != other.managed - || self.animated != other.animated - || self.available != other.available) + self.id == other.id + && self.name == other.name + && self.roles == other.roles + && self.roles == other.roles + && option_arc_rwlock_ptr_eq(&self.user, &other.user) + && self.require_colons == other.require_colons + && self.managed == other.managed + && self.animated == other.animated + && self.available == other.available } } impl From for Emoji { fn from(value: PartialEmoji) -> Self { Self { - id: value.id.unwrap_or_default(), // TODO: this should be handled differently + id: value.id.unwrap_or_default(), // TODO: Make this method an impl to TryFrom<> instead name: Some(value.name), roles: None, user: None, @@ -80,4 +73,4 @@ impl From for Emoji { available: None, } } -} \ No newline at end of file +} diff --git a/src/types/entities/guild.rs b/src/types/entities/guild.rs index 72e6a7e..76256c7 100644 --- a/src/types/entities/guild.rs +++ b/src/types/entities/guild.rs @@ -3,21 +3,22 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::fmt::Debug; +use std::hash::Hash; use bitflags::bitflags; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::types::Shared; use crate::types::types::guild_configuration::GuildFeaturesList; +use crate::types::Shared; use crate::types::{ entities::{Channel, Emoji, RoleObject, Sticker, User, VoiceState, Webhook}, interfaces::WelcomeScreenObject, utils::Snowflake, }; -use super::PublicUser; +use super::{option_arc_rwlock_ptr_eq, vec_arc_rwlock_ptr_eq, PublicUser}; #[cfg(feature = "client")] use crate::gateway::Updateable; @@ -126,59 +127,8 @@ pub struct Guild { pub widget_enabled: Option, } -impl std::hash::Hash for Guild { - fn hash(&self, state: &mut H) { - self.afk_channel_id.hash(state); - self.afk_timeout.hash(state); - self.application_id.hash(state); - self.approximate_member_count.hash(state); - self.approximate_presence_count.hash(state); - self.banner.hash(state); - self.bans.hash(state); - self.default_message_notifications.hash(state); - self.description.hash(state); - self.discovery_splash.hash(state); - self.explicit_content_filter.hash(state); - self.features.hash(state); - self.icon.hash(state); - self.icon_hash.hash(state); - self.id.hash(state); - self.invites.hash(state); - self.joined_at.hash(state); - self.large.hash(state); - self.max_members.hash(state); - self.max_presences.hash(state); - self.max_stage_video_channel_users.hash(state); - self.max_video_channel_users.hash(state); - self.mfa_level.hash(state); - self.name.hash(state); - self.nsfw_level.hash(state); - self.owner.hash(state); - self.owner_id.hash(state); - self.permissions.hash(state); - self.preferred_locale.hash(state); - self.premium_progress_bar_enabled.hash(state); - self.premium_subscription_count.hash(state); - self.premium_tier.hash(state); - self.primary_category_id.hash(state); - self.public_updates_channel_id.hash(state); - self.region.hash(state); - self.rules_channel.hash(state); - self.rules_channel_id.hash(state); - self.splash.hash(state); - self.stickers.hash(state); - self.system_channel_flags.hash(state); - self.system_channel_id.hash(state); - self.vanity_url_code.hash(state); - self.verification_level.hash(state); - self.welcome_screen.hash(state); - self.welcome_screen.hash(state); - self.widget_channel_id.hash(state); - self.widget_enabled.hash(state); - } -} - -impl std::cmp::PartialEq for Guild { +#[cfg(not(tarpaulin_include))] +impl PartialEq for Guild { fn eq(&self, other: &Self) -> bool { self.afk_channel_id == other.afk_channel_id && self.afk_timeout == other.afk_timeout @@ -187,14 +137,17 @@ impl std::cmp::PartialEq for Guild { && self.approximate_presence_count == other.approximate_presence_count && self.banner == other.banner && self.bans == other.bans + && vec_arc_rwlock_ptr_eq(&self.channels, &other.channels) && self.default_message_notifications == other.default_message_notifications && self.description == other.description && self.discovery_splash == other.discovery_splash + && vec_arc_rwlock_ptr_eq(&self.emojis, &other.emojis) && self.explicit_content_filter == other.explicit_content_filter && self.features == other.features && self.icon == other.icon && self.icon_hash == other.icon_hash && self.id == other.id + && self.invites == other.invites && self.joined_at == other.joined_at && self.large == other.large && self.max_members == other.max_members @@ -214,6 +167,7 @@ impl std::cmp::PartialEq for Guild { && self.primary_category_id == other.primary_category_id && self.public_updates_channel_id == other.public_updates_channel_id && self.region == other.region + && vec_arc_rwlock_ptr_eq(&self.roles, &other.roles) && self.rules_channel == other.rules_channel && self.rules_channel_id == other.rules_channel_id && self.splash == other.splash @@ -222,6 +176,8 @@ impl std::cmp::PartialEq for Guild { && self.system_channel_id == other.system_channel_id && self.vanity_url_code == other.vanity_url_code && self.verification_level == other.verification_level + && vec_arc_rwlock_ptr_eq(&self.voice_states, &other.voice_states) + && vec_arc_rwlock_ptr_eq(&self.webhooks, &other.webhooks) && self.welcome_screen == other.welcome_screen && self.welcome_screen == other.welcome_screen && self.widget_channel_id == other.widget_channel_id @@ -261,32 +217,36 @@ pub struct GuildInvite { pub vanity_url: Option, } -impl std::hash::Hash for GuildInvite { - fn hash(&self, state: &mut H) { - self.code.hash(state); - self.temporary.hash(state); - self.uses.hash(state); - self.max_uses.hash(state); - self.max_age.hash(state); - self.created_at.hash(state); - self.expires_at.hash(state); - self.guild_id.hash(state); - self.channel_id.hash(state); - self.inviter_id.hash(state); - self.target_user_id.hash(state); - self.target_user.hash(state); - self.target_user_type.hash(state); - self.vanity_url.hash(state); +#[cfg(not(tarpaulin_include))] +impl PartialEq for GuildInvite { + fn eq(&self, other: &Self) -> bool { + self.code == other.code + && self.temporary == other.temporary + && self.uses == other.uses + && self.max_uses == other.max_uses + && self.max_age == other.max_age + && self.created_at == other.created_at + && self.expires_at == other.expires_at + && self.guild_id == other.guild_id + && option_arc_rwlock_ptr_eq(&self.guild, &other.guild) + && self.channel_id == other.channel_id + && option_arc_rwlock_ptr_eq(&self.channel, &other.channel) + && self.inviter_id == other.inviter_id + && option_arc_rwlock_ptr_eq(&self.inviter, &other.inviter) + && self.target_user_id == other.target_user_id + && self.target_user == other.target_user + && self.target_user_type == other.target_user_type + && self.vanity_url == other.vanity_url } } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Hash, Eq, PartialOrd, Ord, Copy)] pub struct UnavailableGuild { pub id: Snowflake, pub unavailable: bool, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] pub struct GuildCreateResponse { pub id: Snowflake, } @@ -312,7 +272,29 @@ pub struct GuildScheduledEvent { pub image: Option, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone)] +#[cfg(not(tarpaulin_include))] +impl PartialEq for GuildScheduledEvent { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.guild_id == other.guild_id + && self.channel_id == other.channel_id + && self.creator_id == other.creator_id + && self.name == other.name + && self.description == other.description + && self.scheduled_start_time == other.scheduled_start_time + && self.scheduled_end_time == other.scheduled_end_time + && self.privacy_level == other.privacy_level + && self.status == other.status + && self.entity_type == other.entity_type + && self.entity_id == other.entity_id + && self.entity_metadata == other.entity_metadata + && option_arc_rwlock_ptr_eq(&self.creator, &other.creator) + && self.user_count == other.user_count + && self.image == other.image + } +} + +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, PartialEq, Copy)] #[repr(u8)] /// See pub enum GuildScheduledEventPrivacyLevel { @@ -320,7 +302,7 @@ pub enum GuildScheduledEventPrivacyLevel { GuildOnly = 2, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, PartialEq, Copy)] #[repr(u8)] /// See pub enum GuildScheduledEventStatus { @@ -331,7 +313,19 @@ pub enum GuildScheduledEventStatus { Canceled = 4, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Copy, + Hash, +)] #[repr(u8)] /// See pub enum GuildScheduledEventEntityType { @@ -341,7 +335,7 @@ pub enum GuildScheduledEventEntityType { External = 3, } -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] /// See pub struct GuildScheduledEventEntityMetadata { pub location: Option, @@ -356,7 +350,19 @@ pub struct VoiceRegion { custom: bool, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -367,7 +373,19 @@ pub enum MessageNotificationLevel { OnlyMentions = 1, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -379,7 +397,19 @@ pub enum ExplicitContentFilterLevel { AllMembers = 2, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -393,7 +423,19 @@ pub enum VerificationLevel { VeryHigh = 4, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -404,7 +446,19 @@ pub enum MFALevel { Elevated = 1, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] @@ -417,7 +471,19 @@ pub enum NSFWLevel { AgeRestricted = 3, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Default, Clone, Eq, PartialEq, Hash, Copy)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Default, + Clone, + Eq, + PartialEq, + Hash, + Copy, + PartialOrd, + Ord, +)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] diff --git a/src/types/entities/guild_member.rs b/src/types/entities/guild_member.rs index 5b1308d..87d94a7 100644 --- a/src/types/entities/guild_member.rs +++ b/src/types/entities/guild_member.rs @@ -5,8 +5,10 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use crate::types::{GuildMemberFlags, PermissionFlags, Shared}; use crate::types::{entities::PublicUser, Snowflake}; +use crate::types::{GuildMemberFlags, PermissionFlags, Shared}; + +use super::option_arc_rwlock_ptr_eq; #[derive(Debug, Deserialize, Default, Serialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -31,3 +33,21 @@ pub struct GuildMember { pub permissions: PermissionFlags, pub communication_disabled_until: Option>, } + +#[cfg(not(tarpaulin_include))] +impl PartialEq for GuildMember { + fn eq(&self, other: &Self) -> bool { + self.nick == other.nick + && self.avatar == other.avatar + && self.roles == other.roles + && self.joined_at == other.joined_at + && self.premium_since == other.premium_since + && self.deaf == other.deaf + && self.mute == other.mute + && self.flags == other.flags + && self.pending == other.pending + && self.permissions == other.permissions + && self.communication_disabled_until == other.communication_disabled_until + && option_arc_rwlock_ptr_eq(&self.user, &other.user) + } +} diff --git a/src/types/entities/integration.rs b/src/types/entities/integration.rs index 4b42f46..16cd991 100644 --- a/src/types/entities/integration.rs +++ b/src/types/entities/integration.rs @@ -6,9 +6,9 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use crate::types::{ - Shared, entities::{Application, User}, utils::Snowflake, + Shared, }; #[derive(Default, Debug, Deserialize, Serialize, Clone)] @@ -44,7 +44,9 @@ pub struct IntegrationAccount { pub name: String, } -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] +#[derive( + Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, +)] #[serde(rename_all = "snake_case")] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[cfg_attr(feature = "sqlx", sqlx(rename_all = "snake_case"))] @@ -54,4 +56,4 @@ pub enum IntegrationType { Youtube, Discord, GuildSubscription, -} \ No newline at end of file +} diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index 0a8169b..dbea3d5 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -8,14 +8,16 @@ use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::{ - Shared, entities::{ Application, Attachment, Channel, Emoji, GuildMember, PublicUser, RoleSubscriptionData, Sticker, StickerItem, User, }, utils::Snowflake, + Shared, }; +use super::option_arc_rwlock_ptr_eq; + #[derive(Debug, Serialize, Deserialize, Default, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a message sent in a channel. @@ -83,6 +85,7 @@ pub struct Message { pub role_subscription_data: Option, } +#[cfg(not(tarpaulin_include))] impl PartialEq for Message { fn eq(&self, other: &Self) -> bool { self.id == other.id @@ -99,26 +102,31 @@ impl PartialEq for Message { && self.attachments == other.attachments && self.embeds == other.embeds && self.embeds == other.embeds + && self.reactions == other.reactions + && self.reactions == other.reactions && self.nonce == other.nonce && self.pinned == other.pinned && self.webhook_id == other.webhook_id && self.message_type == other.message_type && self.activity == other.activity && self.activity == other.activity + && self.application == other.application && self.application_id == other.application_id && self.message_reference == other.message_reference && self.message_reference == other.message_reference && self.flags == other.flags && self.referenced_message == other.referenced_message + && self.interaction == other.interaction && self.thread == other.thread && self.components == other.components + && self.components == other.components && self.sticker_items == other.sticker_items - // && self.position == other.position + && self.stickers == other.stickers && self.role_subscription_data == other.role_subscription_data } } -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Ord, PartialOrd)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Ord, PartialOrd, Copy)] /// # Reference /// See pub struct MessageReference { @@ -130,7 +138,7 @@ pub struct MessageReference { pub fail_if_not_exists: Option, } -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Ord, PartialOrd)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Ord, PartialOrd, Copy)] pub enum MessageReferenceType { /// A standard reference used by replies and system messages Default = 0, @@ -148,7 +156,18 @@ pub struct MessageInteraction { pub member: Option>, } -#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, Eq, PartialOrd, Ord)] +#[cfg(not(tarpaulin_include))] +impl PartialEq for MessageInteraction { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.interaction_type == other.interaction_type + && self.name == other.name + && self.user == other.user + && option_arc_rwlock_ptr_eq(&self.member, &other.member) + } +} + +#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize, Eq, PartialOrd, Ord, Hash)] pub struct AllowedMention { parse: Vec, roles: Vec, @@ -156,7 +175,7 @@ pub struct AllowedMention { replied_user: bool, } -#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq, PartialOrd, Ord, Hash)] #[serde(rename_all = "snake_case")] pub enum AllowedMentionType { Roles, @@ -173,7 +192,7 @@ pub struct ChannelMention { name: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash, Ord)] pub struct Embed { title: Option, #[serde(rename = "type")] @@ -191,7 +210,7 @@ pub struct Embed { fields: Option>, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(rename_all = "snake_case")] pub enum EmbedType { #[deprecated] @@ -206,17 +225,17 @@ pub enum EmbedType { Link, PostPreview, Rich, - Video + Video, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct EmbedFooter { text: String, icon_url: Option, proxy_icon_url: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub struct EmbedImage { url: String, proxy_url: String, @@ -224,7 +243,7 @@ pub struct EmbedImage { width: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub struct EmbedThumbnail { url: String, proxy_url: Option, @@ -232,7 +251,7 @@ pub struct EmbedThumbnail { width: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] struct EmbedVideo { url: Option, proxy_url: Option, @@ -240,13 +259,13 @@ struct EmbedVideo { width: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub struct EmbedProvider { name: Option, url: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub struct EmbedAuthor { name: String, url: Option, @@ -254,7 +273,7 @@ pub struct EmbedAuthor { proxy_icon_url: Option, } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub struct EmbedField { name: String, value: String, @@ -273,7 +292,7 @@ pub struct Reaction { pub emoji: Emoji, #[cfg(feature = "sqlx")] #[serde(skip)] - pub user_ids: Vec + pub user_ids: Vec, } #[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq, PartialOrd, Ord)] @@ -297,7 +316,9 @@ pub struct MessageActivity { pub party_id: Option, } -#[derive(Debug, Default, PartialEq, Clone, Copy, Serialize_repr, Deserialize_repr, Eq, PartialOrd, Ord)] +#[derive( + Debug, Default, PartialEq, Clone, Copy, Serialize_repr, Deserialize_repr, Eq, PartialOrd, Ord, +)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[repr(u8)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] @@ -393,7 +414,7 @@ pub enum MessageType { CustomGift = 41, GuildGamingStatsPrompt = 42, /// A message sent when a user purchases a guild product - PurchaseNotification = 44 + PurchaseNotification = 44, } bitflags! { @@ -437,10 +458,10 @@ pub struct PartialEmoji { pub id: Option, pub name: String, #[serde(default)] - pub animated: bool + pub animated: bool, } -#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, PartialOrd)] +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, PartialOrd, Ord, Eq, Hash)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[repr(u8)] diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index 4227e24..2fec4ca 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -141,3 +141,47 @@ impl IntoShared for T { Arc::new(RwLock::new(self)) } } + +/// Internal function to compare two `Shared`s by comparing their pointers. +#[cfg_attr(not(feature = "client"), allow(unused_variables))] +pub(crate) fn arc_rwlock_ptr_eq(a: &Shared, b: &Shared) -> bool { + #[cfg(feature = "client")] + { + Shared::ptr_eq(a, b) + } + #[cfg(not(feature = "client"))] + { + true + } +} + +/// Internal function to compare two `Vec>`s by comparing their pointers. +pub(crate) fn vec_arc_rwlock_ptr_eq(a: &[Shared], b: &[Shared]) -> bool { + for (a, b) in a.iter().zip(b.iter()) { + if !arc_rwlock_ptr_eq(a, b) { + return false; + } + } + true +} + +/// Internal function to compare two `Option>`s by comparing their pointers. +pub(crate) fn option_arc_rwlock_ptr_eq(a: &Option>, b: &Option>) -> bool { + match (a, b) { + (Some(a), Some(b)) => arc_rwlock_ptr_eq(a, b), + (None, None) => true, + _ => false, + } +} + +/// Internal function to compare two `Option>>`s by comparing their pointers. +pub(crate) fn option_vec_arc_rwlock_ptr_eq( + a: &Option>>, + b: &Option>>, +) -> bool { + match (a, b) { + (Some(a), Some(b)) => vec_arc_rwlock_ptr_eq(a, b), + (None, None) => true, + _ => false, + } +} diff --git a/src/types/entities/ratelimits.rs b/src/types/entities/ratelimits.rs index 1823e76..dc084cf 100644 --- a/src/types/entities/ratelimits.rs +++ b/src/types/entities/ratelimits.rs @@ -11,7 +11,9 @@ use crate::types::Snowflake; /// The different types of ratelimits that can be applied to a request. Includes "Baseline"-variants /// for when the Snowflake is not yet known. /// See for more information. -#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Hash, Serialize, Deserialize)] +#[derive( + Clone, Copy, Eq, PartialEq, Debug, Default, Hash, Serialize, Deserialize, PartialOrd, Ord, +)] pub enum LimitType { AuthRegister, AuthLogin, @@ -29,7 +31,7 @@ pub enum LimitType { /// A struct that represents the current ratelimits, either instance-wide or user-wide. /// See for more information. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)] pub struct Limit { pub bucket: LimitType, pub limit: u64, diff --git a/src/types/entities/relationship.rs b/src/types/entities/relationship.rs index b5e2004..e3276db 100644 --- a/src/types/entities/relationship.rs +++ b/src/types/entities/relationship.rs @@ -8,7 +8,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::{Shared, Snowflake}; -use super::PublicUser; +use super::{arc_rwlock_ptr_eq, PublicUser}; #[derive(Debug, Deserialize, Serialize, Clone, Default)] /// See @@ -21,16 +21,30 @@ pub struct Relationship { pub since: Option>, } +#[cfg(not(tarpaulin_include))] impl PartialEq for Relationship { fn eq(&self, other: &Self) -> bool { self.id == other.id && self.relationship_type == other.relationship_type - && self.since == other.since && self.nickname == other.nickname + && arc_rwlock_ptr_eq(&self.user, &other.user) + && self.since == other.since } } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default, Eq, PartialEq)] +#[derive( + Serialize_repr, + Deserialize_repr, + Debug, + Clone, + Default, + Eq, + PartialEq, + PartialOrd, + Ord, + Copy, + Hash, +)] #[repr(u8)] /// See pub enum RelationshipType { diff --git a/src/types/entities/role.rs b/src/types/entities/role.rs index 8c00b41..20d2fcf 100644 --- a/src/types/entities/role.rs +++ b/src/types/entities/role.rs @@ -51,7 +51,7 @@ pub struct RoleSubscriptionData { pub is_renewal: bool, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)] /// See pub struct RoleTags { #[serde(default)] diff --git a/src/types/entities/stage_instance.rs b/src/types/entities/stage_instance.rs index d48231b..38e2817 100644 --- a/src/types/entities/stage_instance.rs +++ b/src/types/entities/stage_instance.rs @@ -21,7 +21,7 @@ pub struct StageInstance { pub guild_scheduled_event_id: Option, } -#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default)] +#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Default, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(u8)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] /// See diff --git a/src/types/entities/sticker.rs b/src/types/entities/sticker.rs index 22affcb..6fcc708 100644 --- a/src/types/entities/sticker.rs +++ b/src/types/entities/sticker.rs @@ -7,6 +7,8 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::{entities::User, utils::Snowflake, Shared}; +use super::option_arc_rwlock_ptr_eq; + #[derive(Debug, Serialize, Deserialize, Clone, Default)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] /// Represents a sticker that can be sent in messages. @@ -33,22 +35,7 @@ pub struct Sticker { pub sort_value: Option, } -impl std::hash::Hash for Sticker { - fn hash(&self, state: &mut H) { - self.id.hash(state); - self.pack_id.hash(state); - self.name.hash(state); - self.description.hash(state); - self.tags.hash(state); - self.asset.hash(state); - self.sticker_type.hash(state); - self.format_type.hash(state); - self.available.hash(state); - self.guild_id.hash(state); - self.sort_value.hash(state); - } -} - +#[cfg(not(tarpaulin_include))] impl PartialEq for Sticker { fn eq(&self, other: &Self) -> bool { self.id == other.id @@ -61,65 +48,16 @@ impl PartialEq for Sticker { && self.format_type == other.format_type && self.available == other.available && self.guild_id == other.guild_id + && option_arc_rwlock_ptr_eq(&self.user, &other.user) && self.sort_value == other.sort_value } } -impl PartialOrd for Sticker { - fn partial_cmp(&self, other: &Self) -> Option { - match self.id.partial_cmp(&other.id) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.pack_id.partial_cmp(&other.pack_id) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.name.partial_cmp(&other.name) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.description.partial_cmp(&other.description) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.tags.partial_cmp(&other.tags) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.asset.partial_cmp(&other.asset) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.sticker_type.partial_cmp(&other.sticker_type) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.format_type.partial_cmp(&other.format_type) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.available.partial_cmp(&other.available) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - match self.guild_id.partial_cmp(&other.guild_id) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - self.sort_value.partial_cmp(&other.sort_value) - } -} - impl Sticker { pub fn tags(&self) -> Vec { - self.tags - .as_ref() - .map_or(vec![], |s| - s.split(',') - .map(|tag| tag.trim().to_string()) - .collect() - ) + self.tags.as_ref().map_or(vec![], |s| { + s.split(',').map(|tag| tag.trim().to_string()).collect() + }) } } @@ -136,7 +74,9 @@ pub struct StickerItem { pub format_type: StickerFormatType, } -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Serialize_repr, Deserialize_repr)] +#[derive( + Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Serialize_repr, Deserialize_repr, +)] #[repr(u8)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename = "SCREAMING_SNAKE_CASE")] @@ -150,7 +90,9 @@ pub enum StickerType { Guild = 2, } -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Serialize_repr, Deserialize_repr)] +#[derive( + Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Serialize_repr, Deserialize_repr, +)] #[repr(u8)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] /// # Reference @@ -169,7 +111,10 @@ pub enum StickerFormatType { impl StickerFormatType { pub fn is_animated(&self) -> bool { - matches!(self, StickerFormatType::APNG | StickerFormatType::LOTTIE | StickerFormatType::GIF) + matches!( + self, + StickerFormatType::APNG | StickerFormatType::LOTTIE | StickerFormatType::GIF + ) } pub const fn to_mime(&self) -> &'static str { diff --git a/src/types/entities/team.rs b/src/types/entities/team.rs index 8fed819..4748fad 100644 --- a/src/types/entities/team.rs +++ b/src/types/entities/team.rs @@ -5,8 +5,10 @@ use serde::{Deserialize, Serialize}; use crate::types::entities::User; -use crate::types::Snowflake; use crate::types::Shared; +use crate::types::Snowflake; + +use super::arc_rwlock_ptr_eq; #[derive(Debug, Deserialize, Serialize, Clone)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] @@ -19,6 +21,17 @@ pub struct Team { pub owner_user_id: Snowflake, } +#[cfg(not(tarpaulin_include))] +impl PartialEq for Team { + fn eq(&self, other: &Self) -> bool { + self.icon == other.icon + && self.id == other.id + && self.members == other.members + && self.name == other.name + && self.owner_user_id == other.owner_user_id + } +} + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct TeamMember { pub membership_state: u8, @@ -26,3 +39,13 @@ pub struct TeamMember { pub team_id: Snowflake, pub user: Shared, } + +#[cfg(not(tarpaulin_include))] +impl PartialEq for TeamMember { + fn eq(&self, other: &Self) -> bool { + self.membership_state == other.membership_state + && self.permissions == other.permissions + && self.team_id == other.team_id + && arc_rwlock_ptr_eq(&self.user, &other.user) + } +} diff --git a/src/types/entities/user_settings.rs b/src/types/entities/user_settings.rs index fa3433a..395db2d 100644 --- a/src/types/entities/user_settings.rs +++ b/src/types/entities/user_settings.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::types::Shared; use serde_aux::field_attributes::deserialize_option_number_from_string; -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Copy, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "lowercase")] pub enum UserStatus { @@ -26,7 +26,7 @@ impl std::fmt::Display for UserStatus { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Copy, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[serde(rename_all = "lowercase")] pub enum UserTheme { @@ -136,7 +136,7 @@ pub struct CustomStatus { pub text: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub struct FriendSourceFlags { pub all: bool, } diff --git a/src/types/entities/voice_state.rs b/src/types/entities/voice_state.rs index 9953b7b..4491bea 100644 --- a/src/types/entities/voice_state.rs +++ b/src/types/entities/voice_state.rs @@ -25,6 +25,8 @@ use crate::types::{ utils::Snowflake, }; +use super::option_arc_rwlock_ptr_eq; + /// The VoiceState struct. Note, that Discord does not have an `id` field for this, whereas Spacebar /// does. /// @@ -54,6 +56,28 @@ pub struct VoiceState { pub id: Option, // Only exists on Spacebar } +#[cfg(not(tarpaulin_include))] +impl PartialEq for VoiceState { + fn eq(&self, other: &Self) -> bool { + self.guild_id == other.guild_id + && self.guild == other.guild + && self.channel_id == other.channel_id + && self.user_id == other.user_id + && option_arc_rwlock_ptr_eq(&self.member, &other.member) + && self.session_id == other.session_id + && self.token == other.token + && self.deaf == other.deaf + && self.mute == other.mute + && self.self_deaf == other.self_deaf + && self.self_mute == other.self_mute + && self.self_stream == other.self_stream + && self.self_video == other.self_video + && self.suppress == other.suppress + && self.request_to_speak_timestamp == other.request_to_speak_timestamp + && self.id == other.id + } +} + #[cfg(feature = "client")] impl Updateable for VoiceState { #[cfg(not(tarpaulin_include))] diff --git a/src/types/entities/webhook.rs b/src/types/entities/webhook.rs index aea9f41..19f6203 100644 --- a/src/types/entities/webhook.rs +++ b/src/types/entities/webhook.rs @@ -25,6 +25,8 @@ use crate::types::{ utils::Snowflake, }; +use super::option_arc_rwlock_ptr_eq; + /// See #[derive(Serialize, Deserialize, Debug, Default, Clone)] #[cfg_attr(feature = "client", derive(Updateable, Composite))] @@ -36,7 +38,7 @@ pub struct Webhook { pub name: String, pub avatar: String, pub token: String, - pub guild_id: Snowflake, + pub guild_id: Snowflake, pub channel_id: Snowflake, pub application_id: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -49,7 +51,26 @@ pub struct Webhook { pub url: Option, } -#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy)] +#[cfg(not(tarpaulin_include))] +impl PartialEq for Webhook { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + && self.webhook_type == other.webhook_type + && self.name == other.name + && self.avatar == other.avatar + && self.token == other.token + && self.guild_id == other.guild_id + && self.channel_id == other.channel_id + && self.application_id == other.application_id + && option_arc_rwlock_ptr_eq(&self.user, &other.user) + && option_arc_rwlock_ptr_eq(&self.source_guild, &other.source_guild) + && self.url == other.url + } +} + +#[derive( + Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[repr(u8)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] pub enum WebhookType { @@ -57,4 +78,4 @@ pub enum WebhookType { Incoming = 1, ChannelFollower = 2, Application = 3, -} \ No newline at end of file +} diff --git a/src/types/errors.rs b/src/types/errors.rs index f417aef..7e2aa78 100644 --- a/src/types/errors.rs +++ b/src/types/errors.rs @@ -21,18 +21,18 @@ pub enum Error { #[error(transparent)] Guild(#[from] GuildError), - + #[error("Invalid flags value: {0}")] - InvalidFlags(u64) + InvalidFlags(u64), } -#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Debug, PartialEq, Eq, thiserror::Error, Copy, Clone)] pub enum GuildError { #[error("Invalid Guild Feature")] InvalidGuildFeature, } -#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[derive(Debug, PartialEq, Eq, thiserror::Error, Copy, Clone)] pub enum FieldFormatError { #[error("Password must be between 1 and 72 characters.")] PasswordError, diff --git a/src/types/events/call.rs b/src/types/events/call.rs index 5dc5911..7efdce1 100644 --- a/src/types/events/call.rs +++ b/src/types/events/call.rs @@ -39,7 +39,19 @@ pub struct CallUpdate { pub channel_id: Snowflake, } -#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq, WebSocketEvent)] +#[derive( + Debug, + Deserialize, + Serialize, + Default, + Clone, + PartialEq, + Eq, + WebSocketEvent, + Copy, + PartialOrd, + Ord, +)] /// Officially Undocumented; /// Deletes a ringing call; /// Ex: {"t":"CALL_DELETE","s":8,"op":0,"d":{"channel_id":"837609115475771392"}} @@ -47,7 +59,19 @@ pub struct CallDelete { pub channel_id: Snowflake, } -#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq, WebSocketEvent)] +#[derive( + Debug, + Deserialize, + Serialize, + Default, + Clone, + PartialEq, + Eq, + WebSocketEvent, + Copy, + PartialOrd, + Ord, +)] /// Officially Undocumented; /// See ; /// @@ -55,4 +79,3 @@ pub struct CallDelete { pub struct CallSync { pub channel_id: Snowflake, } - diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs index 73d89f6..a51a74b 100644 --- a/src/types/events/channel.rs +++ b/src/types/events/channel.rs @@ -20,7 +20,7 @@ use crate::types::IntoShared; #[cfg(feature = "client")] use crate::types::Guild; -#[derive(Debug, Default, Deserialize, Serialize, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, WebSocketEvent, Copy, PartialEq, Clone, Eq, Hash, PartialOrd, Ord)] /// See pub struct ChannelPinsUpdate { pub guild_id: Option, @@ -86,7 +86,7 @@ pub struct ChannelUnreadUpdate { pub guild_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] /// Contains very few fields from [Channel] /// See also [ChannelUnreadUpdate] pub struct ChannelUnreadUpdateObject { diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index f2cc009..f599d1f 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -9,8 +9,8 @@ use serde::{Deserialize, Serialize}; use crate::types::entities::{Guild, PublicUser, UnavailableGuild}; use crate::types::events::WebSocketEvent; use crate::types::{ - AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, JsonField, RoleObject, - Snowflake, SourceUrlField, Sticker, + AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, JsonField, RoleObject, Snowflake, + SourceUrlField, Sticker, }; use super::PresenceUpdate; @@ -18,11 +18,21 @@ use super::PresenceUpdate; #[cfg(feature = "client")] use super::UpdateMessage; #[cfg(feature = "client")] -use crate::types::Shared; -#[cfg(feature = "client")] use crate::types::IntoShared; +#[cfg(feature = "client")] +use crate::types::Shared; -#[derive(Debug, Deserialize, Serialize, Default, Clone, SourceUrlField, JsonField, WebSocketEvent)] +#[derive( + Debug, + Deserialize, + Serialize, + Default, + Clone, + SourceUrlField, + JsonField, + WebSocketEvent, + PartialEq, +)] /// See ; /// Received to give data about a guild; // This one is particularly painful, it can be a Guild object with an extra field or an unavailable guild object @@ -49,7 +59,7 @@ impl UpdateMessage for GuildCreate { fn update(&mut self, _: Shared) {} } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] #[serde(untagged)] pub enum GuildCreateDataOption { UnavailableGuild(UnavailableGuild), @@ -62,7 +72,31 @@ impl Default for GuildCreateDataOption { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Clone, PartialEq)] +pub enum GuildEvents { + Create(GuildCreate), + Update(GuildUpdate), + Delete(GuildDelete), + BanAdd(GuildBanAdd), + BanRemove(GuildBanRemove), + EmojisUpdate(GuildEmojisUpdate), + StickersUpdate(GuildStickersUpdate), + IntegrationsUpdate(GuildIntegrationsUpdate), + MemberAdd(GuildMemberAdd), + MemberRemove(GuildMemberRemove), + MemberUpdate(GuildMemberUpdate), + MembersChunk(GuildMembersChunk), + RoleCreate(GuildRoleCreate), + RoleUpdate(GuildRoleUpdate), + RoleDelete(GuildRoleDelete), + ScheduledEventCreate(GuildScheduledEventCreate), + ScheduledEventUpdate(GuildScheduledEventUpdate), + ScheduledEventDelete(GuildScheduledEventDelete), + ScheduledEventUserAdd(GuildScheduledEventUserAdd), + ScheduledEventUserRemove(GuildScheduledEventUserRemove), + AuditLogEntryCreate(GuildAuditLogEntryCreate), +} +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to give info about a user being banned from a guild; pub struct GuildBanAdd { @@ -70,7 +104,7 @@ pub struct GuildBanAdd { pub user: PublicUser, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to give info about a user being unbanned from a guild; pub struct GuildBanRemove { @@ -78,7 +112,17 @@ pub struct GuildBanRemove { pub user: PublicUser, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField, WebSocketEvent)] +#[derive( + Debug, + Default, + Deserialize, + Serialize, + Clone, + SourceUrlField, + JsonField, + WebSocketEvent, + PartialEq, +)] /// See ; /// Received to give info about a guild being updated; pub struct GuildUpdate { @@ -98,7 +142,17 @@ impl UpdateMessage for GuildUpdate { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, SourceUrlField, JsonField, WebSocketEvent)] +#[derive( + Debug, + Default, + Deserialize, + Serialize, + Clone, + SourceUrlField, + JsonField, + WebSocketEvent, + PartialEq, +)] /// See ; /// Received to tell the client about a guild being deleted; pub struct GuildDelete { @@ -119,7 +173,7 @@ impl UpdateMessage for GuildDelete { fn update(&mut self, _: Shared) {} } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to the client about an audit log entry being added; pub struct GuildAuditLogEntryCreate { @@ -127,7 +181,7 @@ pub struct GuildAuditLogEntryCreate { pub entry: AuditLogEntry, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to tell the client about a change to a guild's emoji list; pub struct GuildEmojisUpdate { @@ -135,7 +189,7 @@ pub struct GuildEmojisUpdate { pub emojis: Vec, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to tell the client about a change to a guild's sticker list; pub struct GuildStickersUpdate { @@ -143,13 +197,13 @@ pub struct GuildStickersUpdate { pub stickers: Vec, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq, Copy, Eq, Hash, PartialOrd, Ord)] /// See pub struct GuildIntegrationsUpdate { pub guild_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to tell the client about a user joining a guild; pub struct GuildMemberAdd { @@ -158,7 +212,7 @@ pub struct GuildMemberAdd { pub guild_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See ; /// Received to tell the client about a user leaving a guild; pub struct GuildMemberRemove { @@ -166,7 +220,7 @@ pub struct GuildMemberRemove { pub user: PublicUser, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See pub struct GuildMemberUpdate { pub guild_id: Snowflake, @@ -182,7 +236,7 @@ pub struct GuildMemberUpdate { pub communication_disabled_until: Option>, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See pub struct GuildMembersChunk { pub guild_id: Snowflake, @@ -194,7 +248,17 @@ pub struct GuildMembersChunk { pub nonce: Option, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField, WebSocketEvent)] +#[derive( + Debug, + Default, + Deserialize, + Serialize, + Clone, + JsonField, + SourceUrlField, + WebSocketEvent, + PartialEq, +)] /// See pub struct GuildRoleCreate { pub guild_id: Snowflake, @@ -214,13 +278,21 @@ impl UpdateMessage for GuildRoleCreate { fn update(&mut self, object_to_update: Shared) { let mut object_to_update = object_to_update.write().unwrap(); - object_to_update - .roles - .push(self.role.clone().into_shared()); + object_to_update.roles.push(self.role.clone().into_shared()); } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField, SourceUrlField, WebSocketEvent)] +#[derive( + Debug, + Default, + Deserialize, + Serialize, + Clone, + JsonField, + SourceUrlField, + WebSocketEvent, + PartialEq, +)] /// See pub struct GuildRoleUpdate { pub guild_id: Snowflake, @@ -244,35 +316,35 @@ impl UpdateMessage for GuildRoleUpdate { } } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] /// See pub struct GuildRoleDelete { pub guild_id: Snowflake, pub role_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See pub struct GuildScheduledEventCreate { #[serde(flatten)] pub event: GuildScheduledEvent, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See pub struct GuildScheduledEventUpdate { #[serde(flatten)] pub event: GuildScheduledEvent, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq)] /// See pub struct GuildScheduledEventDelete { #[serde(flatten)] pub event: GuildScheduledEvent, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq, Copy, Eq, Hash, PartialOrd, Ord)] /// See pub struct GuildScheduledEventUserAdd { pub guild_scheduled_event_id: Snowflake, @@ -280,7 +352,7 @@ pub struct GuildScheduledEventUserAdd { pub guild_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, PartialEq, Copy, Eq, Hash, PartialOrd, Ord)] /// See pub struct GuildScheduledEventUserRemove { pub guild_scheduled_event_id: Snowflake, diff --git a/src/types/events/heartbeat.rs b/src/types/events/heartbeat.rs index b7a0024..6008ffb 100644 --- a/src/types/events/heartbeat.rs +++ b/src/types/events/heartbeat.rs @@ -5,13 +5,13 @@ use crate::types::events::WebSocketEvent; use serde::{Deserialize, Serialize}; -#[derive(Debug, Default, Deserialize, Serialize, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, WebSocketEvent, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct GatewayHeartbeat { pub op: u8, pub d: Option, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct GatewayHeartbeatAck { pub op: i32, } diff --git a/src/types/events/hello.rs b/src/types/events/hello.rs index f72720b..779b657 100644 --- a/src/types/events/hello.rs +++ b/src/types/events/hello.rs @@ -7,13 +7,13 @@ use chorus_macros::WebSocketEvent; use serde::{Deserialize, Serialize}; /// Received on gateway init, tells the client how often to send heartbeats; -#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, WebSocketEvent, Copy, Hash, PartialOrd, Ord)] pub struct GatewayHello { pub op: i32, pub d: HelloData, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, Copy, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, Copy, WebSocketEvent, Hash, PartialOrd, Ord)] /// Contains info on how often the client should send heartbeats to the server; pub struct HelloData { /// How often a client should send heartbeats, in milliseconds diff --git a/src/types/events/integration.rs b/src/types/events/integration.rs index cf167c9..716cc30 100644 --- a/src/types/events/integration.rs +++ b/src/types/events/integration.rs @@ -23,7 +23,7 @@ pub struct IntegrationUpdate { pub guild_id: Snowflake, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] /// See pub struct IntegrationDelete { pub id: Snowflake, diff --git a/src/types/events/invalid_session.rs b/src/types/events/invalid_session.rs index ee94eeb..12b8fb9 100644 --- a/src/types/events/invalid_session.rs +++ b/src/types/events/invalid_session.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use super::WebSocketEvent; -#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] /// Your session is now invalid. /// /// Either reauthenticate and reidentify or resume if possible. diff --git a/src/types/events/message.rs b/src/types/events/message.rs index 62a9d9d..1b855df 100644 --- a/src/types/events/message.rs +++ b/src/types/events/message.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::types::{ entities::{Emoji, GuildMember, Message, PublicUser}, - Snowflake, WebSocketEvent + Snowflake, WebSocketEvent, }; use chorus_macros::WebSocketEvent; @@ -51,7 +51,20 @@ pub struct MessageUpdate { pub mentions: Option>, } -#[derive(Debug, Serialize, Deserialize, Default, Clone, WebSocketEvent)] +#[derive( + Debug, + Serialize, + Deserialize, + Default, + Clone, + WebSocketEvent, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, +)] /// # Reference /// See pub struct MessageDelete { @@ -60,7 +73,19 @@ pub struct MessageDelete { pub guild_id: Option, } -#[derive(Debug, Serialize, Deserialize, Default, Clone, WebSocketEvent)] +#[derive( + Debug, + Serialize, + Deserialize, + Default, + Clone, + WebSocketEvent, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, +)] /// # Reference /// See pub struct MessageDeleteBulk { @@ -92,7 +117,20 @@ pub struct MessageReactionRemove { pub emoji: Emoji, } -#[derive(Debug, Serialize, Deserialize, Default, Clone, WebSocketEvent)] +#[derive( + Debug, + Serialize, + Deserialize, + Default, + Clone, + WebSocketEvent, + Copy, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, +)] /// # Reference /// See pub struct MessageReactionRemoveAll { @@ -131,4 +169,3 @@ pub struct MessageACK { pub flags: Option, pub channel_id: Snowflake, } - diff --git a/src/types/events/reconnect.rs b/src/types/events/reconnect.rs index 558d953..17381b2 100644 --- a/src/types/events/reconnect.rs +++ b/src/types/events/reconnect.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use super::WebSocketEvent; -#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] /// "The reconnect event is dispatched when a client should reconnect to the Gateway (and resume their existing session, if they have one). This event usually occurs during deploys to migrate sessions gracefully off old hosts" /// /// # Reference diff --git a/src/types/events/relationship.rs b/src/types/events/relationship.rs index b12d73d..eaeea56 100644 --- a/src/types/events/relationship.rs +++ b/src/types/events/relationship.rs @@ -13,7 +13,7 @@ pub struct RelationshipAdd { pub should_notify: bool, } -#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] /// See pub struct RelationshipRemove { pub id: Snowflake, diff --git a/src/types/events/voice_gateway/speaking.rs b/src/types/events/voice_gateway/speaking.rs index 7a505fd..0d50345 100644 --- a/src/types/events/voice_gateway/speaking.rs +++ b/src/types/events/voice_gateway/speaking.rs @@ -13,7 +13,7 @@ use chorus_macros::WebSocketEvent; /// Essentially, what allows us to send UDP data and lights up the green circle around your avatar. /// /// See -#[derive(Debug, Deserialize, Serialize, Clone, Default, WebSocketEvent)] +#[derive(Debug, Deserialize, Serialize, Clone, Default, WebSocketEvent, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] pub struct Speaking { /// Data about the audio we're transmitting. /// diff --git a/src/types/events/webhooks.rs b/src/types/events/webhooks.rs index 3f09492..be39e3d 100644 --- a/src/types/events/webhooks.rs +++ b/src/types/events/webhooks.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use crate::types::{Snowflake, WebSocketEvent}; use chorus_macros::WebSocketEvent; -#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] /// See pub struct WebhooksUpdate { pub guild_id: Snowflake, diff --git a/src/types/interfaces/interaction.rs b/src/types/interfaces/interaction.rs index f88eaf9..1a4bb6a 100644 --- a/src/types/interfaces/interaction.rs +++ b/src/types/interfaces/interaction.rs @@ -20,7 +20,7 @@ pub struct Interaction { pub version: i32, } -#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, Eq, PartialOrd, Ord, Hash, Copy)] pub enum InteractionType { #[default] SelfCommand = 0, @@ -28,7 +28,7 @@ pub enum InteractionType { ApplicationCommand = 2, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Copy, Eq, Hash, PartialOrd, Ord)] pub enum InteractionResponseType { SelfCommandResponse = 0, Pong = 1, @@ -38,7 +38,7 @@ pub enum InteractionResponseType { AcknowledgeWithSource = 5, } -#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, Eq, Hash, PartialOrd, Ord)] pub struct InteractionApplicationCommandCallbackData { pub tts: bool, pub content: String, diff --git a/src/types/schema/apierror.rs b/src/types/schema/apierror.rs index 0dd1f6f..4a242c8 100644 --- a/src/types/schema/apierror.rs +++ b/src/types/schema/apierror.rs @@ -6,7 +6,7 @@ use poem::{http::StatusCode, IntoResponse, Response}; use serde_json::{json, Value}; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Copy, Clone, PartialEq, Eq, Hash)] pub enum APIError { #[error(transparent)] Auth(#[from] AuthError), @@ -20,7 +20,7 @@ impl APIError { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq, Hash)] pub enum AuthError { #[error("INVALID_LOGIN")] InvalidLogin, diff --git a/src/types/schema/audit_log.rs b/src/types/schema/audit_log.rs index ddee832..e5c19e5 100644 --- a/src/types/schema/audit_log.rs +++ b/src/types/schema/audit_log.rs @@ -1,5 +1,8 @@ +use crate::types::{ + ApplicationCommand, AuditLogActionType, AuditLogEntry, AutoModerationRule, Channel, + GuildScheduledEvent, Integration, Snowflake, User, Webhook, +}; use serde::{Deserialize, Serialize}; -use crate::types::{ApplicationCommand, AuditLogActionType, AuditLogEntry, AutoModerationRule, Channel, GuildScheduledEvent, Integration, Snowflake, User, Webhook}; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct AuditLogObject { @@ -13,11 +16,13 @@ pub struct AuditLogObject { pub webhooks: Vec, } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive( + Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default, +)] pub struct GetAuditLogsQuery { pub before: Option, pub after: Option, pub limit: Option, pub user_id: Option, - pub action_type: Option -} \ No newline at end of file + pub action_type: Option, +} diff --git a/src/types/schema/channel.rs b/src/types/schema/channel.rs index c3c02f4..0a3d468 100644 --- a/src/types/schema/channel.rs +++ b/src/types/schema/channel.rs @@ -169,7 +169,7 @@ pub struct AddChannelRecipientSchema { } /// See -#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialOrd, Ord, PartialEq, Eq, Copy, Hash)] pub struct ModifyChannelPositionsSchema { pub id: Snowflake, pub position: Option, @@ -178,7 +178,7 @@ pub struct ModifyChannelPositionsSchema { } /// See -#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialOrd, Ord, PartialEq, Eq, Copy, Hash)] pub struct AddFollowingChannelSchema { pub webhook_channel_id: Snowflake, } diff --git a/src/types/schema/guild.rs b/src/types/schema/guild.rs index 6405d94..f53494e 100644 --- a/src/types/schema/guild.rs +++ b/src/types/schema/guild.rs @@ -2,16 +2,20 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use std::collections::HashMap; use bitflags::bitflags; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use crate::types::entities::Channel; use crate::types::types::guild_configuration::GuildFeatures; -use crate::types::{Emoji, ExplicitContentFilterLevel, GenericSearchQueryWithLimit, MessageNotificationLevel, Snowflake, Sticker, StickerFormatType, SystemChannelFlags, VerificationLevel, WelcomeScreenChannel}; +use crate::types::{ + Emoji, ExplicitContentFilterLevel, GenericSearchQueryWithLimit, MessageNotificationLevel, + Snowflake, Sticker, StickerFormatType, SystemChannelFlags, VerificationLevel, + WelcomeScreenChannel, +}; -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "snake_case")] /// Represents the schema which needs to be sent to create a Guild. /// See: @@ -25,6 +29,19 @@ pub struct GuildCreateSchema { pub rules_channel_id: Option, } +#[cfg(not(tarpaulin_include))] +impl PartialEq for GuildCreateSchema { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + && self.region == other.region + && self.icon == other.icon + && self.channels == other.channels + && self.guild_template_code == other.guild_template_code + && self.system_channel_id == other.system_channel_id + && self.rules_channel_id == other.rules_channel_id + } +} + #[derive(Debug, Deserialize, Serialize, Default, Clone, Copy, Eq, PartialEq)] #[serde(rename_all = "snake_case")] /// Represents the schema which needs to be sent to create a Guild Ban. @@ -77,7 +94,7 @@ pub struct GuildModifySchema { pub premium_progress_bar_enabled: Option, } -#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)] pub struct GetUserGuildSchema { pub before: Option, pub after: Option, @@ -152,7 +169,7 @@ impl Default for GuildMemberSearchSchema { } } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Eq, Ord)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Eq, Ord, Copy, Hash)] pub struct GuildGetMembersQuery { pub limit: Option, pub after: Option, @@ -206,7 +223,7 @@ pub struct ModifyGuildMemberProfileSchema { pub emoji_id: Option, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Eq, Ord)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Eq, Ord, Copy, Hash)] /// The limit argument is a number between 1 and 1000. pub struct GuildBansQuery { pub before: Option, @@ -214,7 +231,6 @@ pub struct GuildBansQuery { pub limit: Option, } - /// Max query length is 32 characters. /// The limit argument is a number between 1 and 10, defaults to 10. pub type GuildBansSearchQuery = GenericSearchQueryWithLimit; @@ -262,7 +278,7 @@ pub struct GuildDiscoveryNsfwProperties { pub description_banned_keywords: Vec, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Copy)] /// Activity metrics are recalculated weekly, as an 8-week rolling average. If they are not yet eligible to be calculated, all fields will be null. /// /// # Reference: @@ -283,7 +299,7 @@ pub struct EmojiCreateSchema { /// See pub image: String, #[serde(default)] - pub roles: Vec + pub roles: Vec, } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] @@ -291,7 +307,7 @@ pub struct EmojiCreateSchema { /// See pub struct EmojiModifySchema { pub name: Option, - pub roles: Option> + pub roles: Option>, } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] @@ -303,10 +319,10 @@ pub struct GuildPruneQuerySchema { #[serde(default, skip_serializing_if = "Option::is_none")] pub compute_prune_count: Option, #[serde(default)] - pub include_roles: Vec + pub include_roles: Vec, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Copy)] /// # Reference: /// See pub struct GuildPruneResult { @@ -325,7 +341,7 @@ pub struct GuildCreateStickerSchema { pub tags: Option, pub file_data: Vec, #[serde(skip)] - pub sticker_format_type: StickerFormatType + pub sticker_format_type: StickerFormatType, } impl GuildCreateStickerSchema { @@ -333,7 +349,10 @@ impl GuildCreateStickerSchema { pub async fn from_multipart(mut multipart: poem::web::Multipart) -> Result { let mut _self = GuildCreateStickerSchema::default(); while let Some(field) = multipart.next_field().await? { - let name = field.name().ok_or(poem::Error::from_string("All fields must be named", poem::http::StatusCode::BAD_REQUEST))?; + let name = field.name().ok_or(poem::Error::from_string( + "All fields must be named", + poem::http::StatusCode::BAD_REQUEST, + ))?; match name { "name" => { _self.name = field.text().await?; @@ -346,17 +365,35 @@ impl GuildCreateStickerSchema { } "file_data" => { if _self.name.is_empty() { - _self.name = field.file_name().map(String::from).ok_or(poem::Error::from_string("File name must be set", poem::http::StatusCode::BAD_REQUEST))?; + _self.name = + field + .file_name() + .map(String::from) + .ok_or(poem::Error::from_string( + "File name must be set", + poem::http::StatusCode::BAD_REQUEST, + ))?; } - _self.sticker_format_type = StickerFormatType::from_mime(field.content_type().ok_or(poem::Error::from_string("Content type must be set", poem::http::StatusCode::BAD_REQUEST))?).ok_or(poem::Error::from_string("Unknown sticker format", poem::http::StatusCode::BAD_REQUEST))?; + _self.sticker_format_type = StickerFormatType::from_mime( + field.content_type().ok_or(poem::Error::from_string( + "Content type must be set", + poem::http::StatusCode::BAD_REQUEST, + ))?, + ) + .ok_or(poem::Error::from_string( + "Unknown sticker format", + poem::http::StatusCode::BAD_REQUEST, + ))?; _self.file_data = field.bytes().await?; } _ => {} } - } if _self.name.is_empty() || _self.file_data.is_empty() { - return Err(poem::Error::from_string("At least the name and file_data are required", poem::http::StatusCode::BAD_REQUEST)); + return Err(poem::Error::from_string( + "At least the name and file_data are required", + poem::http::StatusCode::BAD_REQUEST, + )); } Ok(_self) @@ -366,7 +403,12 @@ impl GuildCreateStickerSchema { pub fn to_multipart(&self) -> reqwest::multipart::Form { let mut form = reqwest::multipart::Form::new() .text("name", self.name.clone()) - .part("file_data", reqwest::multipart::Part::bytes(self.file_data.clone()).mime_str(self.sticker_format_type.to_mime()).unwrap()); + .part( + "file_data", + reqwest::multipart::Part::bytes(self.file_data.clone()) + .mime_str(self.sticker_format_type.to_mime()) + .unwrap(), + ); if let Some(description) = &self.description { form = form.text("description", description.to_owned()); @@ -388,7 +430,7 @@ pub struct GuildModifyStickerSchema { #[serde(default)] pub description: Option, #[serde(default)] - pub tags: Option + pub tags: Option, } #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] @@ -408,5 +450,5 @@ pub struct GuildTemplateCreateSchema { /// Name of the template (1-100 characters) pub name: String, /// Description of the template (max 120 characters) - pub description: Option + pub description: Option, } diff --git a/src/types/schema/message.rs b/src/types/schema/message.rs index 4d50b25..e8d57c7 100644 --- a/src/types/schema/message.rs +++ b/src/types/schema/message.rs @@ -7,7 +7,9 @@ use serde::{Deserialize, Serialize}; use crate::types::entities::{ AllowedMention, Component, Embed, MessageReference, PartialDiscordFileAttachment, }; -use crate::types::{Attachment, EmbedType, Message, MessageFlags, MessageType, ReactionType, Snowflake}; +use crate::types::{ + Attachment, EmbedType, Message, MessageFlags, MessageType, ReactionType, Snowflake, +}; #[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)] #[serde(rename_all = "snake_case")] @@ -25,7 +27,7 @@ pub struct MessageSendSchema { pub attachments: Option>, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum MessageSearchEndpoint { GuildChannel(Snowflake), Channel(Snowflake), @@ -102,7 +104,7 @@ impl std::default::Default for MessageSearchQuery { } } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] #[serde(rename_all = "snake_case")] pub enum AuthorType { User, @@ -116,7 +118,7 @@ pub enum AuthorType { NotWebhook, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] #[serde(rename_all = "snake_case")] pub enum HasType { Image, @@ -148,15 +150,19 @@ pub enum HasType { NotSnapshot, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive( + Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, +)] #[serde(rename_all = "snake_case")] pub enum SortType { #[default] Timestamp, - Relevance + Relevance, } -#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive( + Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Hash, +)] pub enum SortOrder { #[default] #[serde(rename = "desc")] @@ -198,10 +204,10 @@ pub struct MessageModifySchema { pub attachments: Option>, } -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Copy, Eq, Hash, Ord)] pub struct ReactionQuerySchema { pub after: Option, pub limit: Option, #[serde(rename = "type")] - pub reaction_type: Option -} \ No newline at end of file + pub reaction_type: Option, +} diff --git a/src/types/schema/role.rs b/src/types/schema/role.rs index 5dce877..805d026 100644 --- a/src/types/schema/role.rs +++ b/src/types/schema/role.rs @@ -2,10 +2,10 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -use serde::{Deserialize, Serialize}; use crate::types::{PermissionFlags, Snowflake}; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] #[serde(rename_all = "snake_case")] /// Represents the schema which needs to be sent to create or modify a Role. /// See: [https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema](https://docs.spacebar.chat/routes/#cmp--schemas-rolemodifyschema) @@ -20,7 +20,7 @@ pub struct RoleCreateModifySchema { pub position: Option, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[serde(rename_all = "snake_case")] /// Represents the schema which needs to be sent to update a roles' position. /// See: [https://docs.spacebar.chat/routes/#cmp--schemas-rolepositionupdateschema](https://docs.spacebar.chat/routes/#cmp--schemas-rolepositionupdateschema) diff --git a/src/types/schema/voice_state.rs b/src/types/schema/voice_state.rs index d5576ad..3beafa6 100644 --- a/src/types/schema/voice_state.rs +++ b/src/types/schema/voice_state.rs @@ -1,8 +1,8 @@ +use crate::types::Snowflake; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use crate::types::Snowflake; -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Copy)] /// # Reference: /// See pub struct VoiceStateUpdateSchema { @@ -12,4 +12,4 @@ pub struct VoiceStateUpdateSchema { pub suppress: Option, /// The time at which the user requested to speak pub request_to_speak_timestamp: Option>, -} \ No newline at end of file +} diff --git a/src/types/utils/serde.rs b/src/types/utils/serde.rs index 544a305..da41f4a 100644 --- a/src/types/utils/serde.rs +++ b/src/types/utils/serde.rs @@ -1,13 +1,12 @@ -use core::fmt; use chrono::{LocalResult, NaiveDateTime}; -use serde::{de, Deserialize, Deserializer}; +use core::fmt; use serde::de::Error; +use serde::{de, Deserialize, Deserializer}; #[doc(hidden)] -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub struct SecondsStringTimestampVisitor; - /// Ser/de to/from timestamps in seconds /// /// Intended for use with `serde`'s `with` attribute. @@ -37,12 +36,12 @@ pub struct SecondsStringTimestampVisitor; /// ``` pub mod ts_seconds_str { - use core::fmt; - use chrono::{DateTime, LocalResult, Utc}; - use super::SecondsStringTimestampVisitor; - use serde::{de, ser}; - use chrono::TimeZone; use super::serde_from; + use super::SecondsStringTimestampVisitor; + use chrono::TimeZone; + use chrono::{DateTime, LocalResult, Utc}; + use core::fmt; + use serde::{de, ser}; /// Serialize a UTC datetime into an integer number of seconds since the epoch /// @@ -68,8 +67,8 @@ pub mod ts_seconds_str { /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(dt: &DateTime, serializer: S) -> Result - where - S: ser::Serializer, + where + S: ser::Serializer, { serializer.serialize_str(&format!("{}", dt.timestamp())) } @@ -95,8 +94,8 @@ pub mod ts_seconds_str { /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result, D::Error> - where - D: de::Deserializer<'de>, + where + D: de::Deserializer<'de>, { d.deserialize_str(SecondsStringTimestampVisitor) } @@ -110,10 +109,13 @@ pub mod ts_seconds_str { /// Deserialize a timestamp in seconds since the epoch fn visit_str(self, value: &str) -> Result - where - E: de::Error, + where + E: de::Error, { - serde_from(Utc.timestamp_opt(value.parse::().map_err(|e| E::custom(e))?, 0), &value) + serde_from( + Utc.timestamp_opt(value.parse::().map_err(|e| E::custom(e))?, 0), + &value, + ) } } } @@ -146,10 +148,10 @@ pub mod ts_seconds_str { /// # Ok::<(), serde_json::Error>(()) /// ``` pub mod ts_seconds_option_str { - use core::fmt; - use chrono::{DateTime, Utc}; - use serde::{de, ser}; use super::SecondsStringTimestampVisitor; + use chrono::{DateTime, Utc}; + use core::fmt; + use serde::{de, ser}; /// Serialize a UTC datetime into an integer number of seconds since the epoch or none /// @@ -175,8 +177,8 @@ pub mod ts_seconds_option_str { /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn serialize(opt: &Option>, serializer: S) -> Result - where - S: ser::Serializer, + where + S: ser::Serializer, { match *opt { Some(ref dt) => serializer.serialize_some(&dt.timestamp().to_string()), @@ -205,8 +207,8 @@ pub mod ts_seconds_option_str { /// # Ok::<(), serde_json::Error>(()) /// ``` pub fn deserialize<'de, D>(d: D) -> Result>, D::Error> - where - D: de::Deserializer<'de>, + where + D: de::Deserializer<'de>, { d.deserialize_option(OptionSecondsTimestampVisitor) } @@ -222,24 +224,24 @@ pub mod ts_seconds_option_str { /// Deserialize a timestamp in seconds since the epoch fn visit_some(self, d: D) -> Result - where - D: de::Deserializer<'de>, + where + D: de::Deserializer<'de>, { d.deserialize_str(SecondsStringTimestampVisitor).map(Some) } /// Deserialize a timestamp in seconds since the epoch fn visit_none(self) -> Result - where - E: de::Error, + where + E: de::Error, { Ok(None) } /// Deserialize a timestamp in seconds since the epoch fn visit_unit(self) -> Result - where - E: de::Error, + where + E: de::Error, { Ok(None) } @@ -247,17 +249,15 @@ pub mod ts_seconds_option_str { } pub(crate) fn serde_from(me: LocalResult, _ts: &V) -> Result - where - E: de::Error, - V: fmt::Display, - T: fmt::Display, +where + E: de::Error, + V: fmt::Display, + T: fmt::Display, { // TODO: Make actual error type match me { LocalResult::None => Err(E::custom("value is not a legal timestamp")), - LocalResult::Ambiguous(_min, _max) => { - Err(E::custom("value is an ambiguous timestamp")) - } + LocalResult::Ambiguous(_min, _max) => Err(E::custom("value is an ambiguous timestamp")), LocalResult::Single(val) => Ok(val), } } @@ -270,9 +270,11 @@ enum StringOrU64 { } pub fn string_or_u64<'de, D>(d: D) -> Result -where D: Deserializer<'de> { +where + D: Deserializer<'de>, +{ match StringOrU64::deserialize(d)? { StringOrU64::String(s) => s.parse::().map_err(D::Error::custom), - StringOrU64::U64(u) => Ok(u) + StringOrU64::U64(u) => Ok(u), } -} \ No newline at end of file +} diff --git a/src/voice/udp/backends/tokio.rs b/src/voice/udp/backends/tokio.rs index e529a0c..de3ffe5 100644 --- a/src/voice/udp/backends/tokio.rs +++ b/src/voice/udp/backends/tokio.rs @@ -6,7 +6,7 @@ use std::net::SocketAddr; use crate::errors::VoiceUdpError; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct TokioBackend; pub type TokioSocket = tokio::net::UdpSocket; diff --git a/tests/channels.rs b/tests/channels.rs index e00744a..eb1c120 100644 --- a/tests/channels.rs +++ b/tests/channels.rs @@ -168,8 +168,7 @@ async fn create_dm() { dm_channel .recipients .as_ref() - .unwrap() - .get(0) + .unwrap().first() .unwrap() .read() .unwrap() @@ -242,8 +241,7 @@ async fn remove_add_person_from_to_dm() { dm_channel .recipients .as_ref() - .unwrap() - .get(0) + .unwrap().first() .unwrap() .read() .unwrap() diff --git a/tests/gateway.rs b/tests/gateway.rs index b16b3b2..1c8f56a 100644 --- a/tests/gateway.rs +++ b/tests/gateway.rs @@ -206,7 +206,7 @@ async fn test_recursive_self_updating_structs() { let guild = bundle.user.gateway.observe(bundle.guild.clone()).await; let inner_guild = guild.read().unwrap().clone(); let guild_roles = inner_guild.roles; - let guild_role_inner = guild_roles.get(0).unwrap().read().unwrap().clone(); + let guild_role_inner = guild_roles.first().unwrap().read().unwrap().clone(); assert_eq!(guild_role_inner.name, "yippieee".to_string()); common::teardown(bundle).await; } diff --git a/tests/messages.rs b/tests/messages.rs index 3ca6e16..c4ceca5 100644 --- a/tests/messages.rs +++ b/tests/messages.rs @@ -114,7 +114,7 @@ async fn search_messages() { .await .unwrap(); assert!(!query_result.is_empty()); - assert_eq!(query_result.get(0).unwrap().id, message.id); + assert_eq!(query_result.first().unwrap().id, message.id); } #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] @@ -139,8 +139,7 @@ async fn test_stickies() { assert_eq!( Message::get_sticky(channel.id, &mut bundle.user) .await - .unwrap() - .get(0) + .unwrap().first() .unwrap() .id, message.id diff --git a/tests/relationships.rs b/tests/relationships.rs index 2eea5b3..4e57b22 100644 --- a/tests/relationships.rs +++ b/tests/relationships.rs @@ -50,7 +50,7 @@ async fn test_get_relationships() { .unwrap(); let relationships = user.get_relationships().await.unwrap(); assert_eq!( - relationships.get(0).unwrap().id, + relationships.first().unwrap().id, other_user.object.read().unwrap().id ); common::teardown(bundle).await @@ -71,20 +71,20 @@ async fn test_modify_relationship_friends() { .unwrap(); let relationships = user.get_relationships().await.unwrap(); assert_eq!( - relationships.get(0).unwrap().id, + relationships.first().unwrap().id, other_user.object.read().unwrap().id ); assert_eq!( - relationships.get(0).unwrap().relationship_type, + relationships.first().unwrap().relationship_type, RelationshipType::Incoming ); let relationships = other_user.get_relationships().await.unwrap(); assert_eq!( - relationships.get(0).unwrap().id, + relationships.first().unwrap().id, user.object.read().unwrap().id ); assert_eq!( - relationships.get(0).unwrap().relationship_type, + relationships.first().unwrap().relationship_type, RelationshipType::Outgoing ); let _ = user @@ -95,7 +95,7 @@ async fn test_modify_relationship_friends() { .get_relationships() .await .unwrap() - .get(0) + .first() .unwrap() .relationship_type, RelationshipType::Friends @@ -124,11 +124,11 @@ async fn test_modify_relationship_block() { assert_eq!(relationships, Vec::::new()); let relationships = other_user.get_relationships().await.unwrap(); assert_eq!( - relationships.get(0).unwrap().id, + relationships.first().unwrap().id, user.object.read().unwrap().id ); assert_eq!( - relationships.get(0).unwrap().relationship_type, + relationships.first().unwrap().relationship_type, RelationshipType::Blocked ); other_user.remove_relationship(user_id).await.unwrap(); diff --git a/tests/types.rs b/tests/types.rs index 48b132c..27f3239 100644 --- a/tests/types.rs +++ b/tests/types.rs @@ -953,45 +953,7 @@ mod entities { } mod guild { - use std::hash::{Hash, Hasher}; - - use chorus::types::{Guild, GuildInvite}; - - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), test)] - fn guild_hash() { - let id: u64 = 1; - let mut guild1 = Guild::default(); - let mut guild2 = Guild::default(); - guild1.id = id.into(); - guild2.id = id.into(); - let mut hasher1 = std::collections::hash_map::DefaultHasher::new(); - guild1.hash(&mut hasher1); - - let mut hasher2 = std::collections::hash_map::DefaultHasher::new(); - guild2.hash(&mut hasher2); - - assert_eq!(hasher1.finish(), hasher2.finish()); - } - - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), test)] - fn guild_invite_hash() { - let id: u64 = 1; - let mut invite1 = GuildInvite::default(); - let mut invite2 = GuildInvite::default(); - invite1.channel_id = id.into(); - invite2.channel_id = id.into(); - invite1.guild_id = id.into(); - invite2.guild_id = id.into(); - let mut hasher1 = std::collections::hash_map::DefaultHasher::new(); - invite1.hash(&mut hasher1); - - let mut hasher2 = std::collections::hash_map::DefaultHasher::new(); - invite2.hash(&mut hasher2); - - assert_eq!(hasher1.finish(), hasher2.finish()); - } + use chorus::types::Guild; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] @@ -1006,38 +968,6 @@ mod entities { } } - mod relationship { - use chorus::types::{IntoShared, Relationship, User}; - - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), test)] - fn relationship_partial_eq() { - let user = User::default(); - // These 2 users are different, because they do not have the same Snowflake "id". - let user_2 = User::default(); - let relationship_1 = Relationship { - id: 32_u64.into(), - relationship_type: chorus::types::RelationshipType::Friends, - nickname: Some("Xenia".to_string()), - user: user.into_public_user().into_shared(), - since: None, - }; - - let relationship_2 = Relationship { - id: 32_u64.into(), - relationship_type: chorus::types::RelationshipType::Friends, - nickname: Some("Xenia".to_string()), - user: user_2.into_public_user().into_shared(), - since: None, - }; - - // This should succeed, even though the two users' IDs are different. This is because - // `User` is only `PartialEq`, and the actual user object is not checked, since the - // `RwLock` would have to be locked. - assert_eq!(relationship_1, relationship_2); - } - } - mod message { use chorus::types::{Message, Snowflake};