Skip to content

Commit

Permalink
Rework manual deserialization implementations (#1938)
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev authored Jun 6, 2022
1 parent ab4d174 commit fee5da4
Show file tree
Hide file tree
Showing 19 changed files with 364 additions and 1,552 deletions.
19 changes: 7 additions & 12 deletions src/cache/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use crate::model::event::{
GuildRoleDeleteEvent,
GuildRoleUpdateEvent,
GuildStickersUpdateEvent,
GuildUnavailableEvent,
GuildUpdateEvent,
MessageCreateEvent,
MessageUpdateEvent,
Expand Down Expand Up @@ -214,6 +213,13 @@ impl CacheUpdate for GuildDeleteEvent {
type Output = Guild;

fn update(&mut self, cache: &Cache) -> Option<Self::Output> {
if self.guild.unavailable {
cache.unavailable_guilds.insert(self.guild.id);
cache.guilds.remove(&self.guild.id);

return None;
}

match cache.guilds.remove(&self.guild.id) {
Some(guild) => {
for (channel_id, channel) in &guild.1.channels {
Expand Down Expand Up @@ -397,17 +403,6 @@ impl CacheUpdate for GuildStickersUpdateEvent {
}
}

impl CacheUpdate for GuildUnavailableEvent {
type Output = ();

fn update(&mut self, cache: &Cache) -> Option<()> {
cache.unavailable_guilds.insert(self.guild_id);
cache.guilds.remove(&self.guild_id);

None
}
}

impl CacheUpdate for GuildUpdateEvent {
type Output = ();

Expand Down
8 changes: 3 additions & 5 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,8 @@ pub struct Cache {
/// A map of channels in [`Guild`]s that the current user has received data
/// for.
///
/// When a [`Event::GuildDelete`] or [`Event::GuildUnavailable`] is
/// received and processed by the cache, the relevant channels are also
/// removed from this map.
/// When a [`Event::GuildDelete`] is received and processed by the cache,
/// the relevant channels are also removed from this map.
pub(crate) channels: DashMap<ChannelId, GuildChannel>,
/// Cache of channels that have been fetched via to_channel.
///
Expand All @@ -182,8 +181,7 @@ pub struct Cache {
pub(crate) private_channels: DashMap<ChannelId, PrivateChannel>,
/// The total number of shards being used by the bot.
pub(crate) shard_count: RwLock<u64>,
/// A list of guilds which are "unavailable". Refer to the documentation for
/// [`Event::GuildUnavailable`] for more information on when this can occur.
/// A list of guilds which are "unavailable".
///
/// Additionally, guilds are always unavailable for bot users when a Ready
/// is received. Guilds are "sent in" over time through the receiving of
Expand Down
4 changes: 1 addition & 3 deletions src/client/bridge/gateway/shard_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use async_tungstenite::tungstenite;
use async_tungstenite::tungstenite::error::Error as TungsteniteError;
use async_tungstenite::tungstenite::protocol::frame::CloseFrame;
use futures::channel::mpsc::{self, UnboundedReceiver as Receiver, UnboundedSender as Sender};
use serde::Deserialize;
use tokio::sync::RwLock;
use tracing::{debug, error, info, instrument, trace, warn};
use typemap_rev::TypeMap;
Expand Down Expand Up @@ -551,8 +550,7 @@ impl ShardRunner {
#[instrument(skip(self))]
async fn recv_event(&mut self) -> Result<(Option<Event>, Option<ShardAction>, bool)> {
let gw_event = match self.shard.client.recv_json().await {
Ok(Some(value)) => GatewayEvent::deserialize(value).map(Some).map_err(From::from),
Ok(None) => Ok(None),
Ok(inner) => Ok(inner),
Err(Error::Tungstenite(TungsteniteError::Io(_))) => {
debug!("Attempting to auto-reconnect");

Expand Down
21 changes: 2 additions & 19 deletions src/client/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::sync::Arc;
use futures::channel::mpsc::UnboundedSender as Sender;
use futures::future::{BoxFuture, FutureExt};
use tokio::sync::RwLock;
use tracing::instrument;
use tracing::{instrument, warn};
use typemap_rev::TypeMap;

#[cfg(feature = "gateway")]
Expand Down Expand Up @@ -117,9 +117,6 @@ impl DispatchEvent {
Self::Model(Event::GuildStickersUpdate(ref mut event)) => {
update(cache_and_http, event);
},
Self::Model(Event::GuildUnavailable(ref mut event)) => {
update(cache_and_http, event);
},
// Already handled by the framework check macro
Self::Model(Event::MessageCreate(_)) => {},
Self::Model(Event::MessageUpdate(ref mut event)) => {
Expand Down Expand Up @@ -598,14 +595,6 @@ async fn handle_event(
event_handler.guild_stickers_update(context, event.guild_id, event.stickers).await;
});
},
DispatchEvent::Model(Event::GuildUnavailable(mut event)) => {
update(&cache_and_http, &mut event);
let event_handler = Arc::clone(event_handler);

spawn_named("dispatch::event_handler::guild_unavailable", async move {
event_handler.guild_unavailable(context, event.guild_id).await;
});
},
DispatchEvent::Model(Event::GuildUpdate(mut event)) => {
let event_handler = Arc::clone(event_handler);

Expand Down Expand Up @@ -732,13 +721,7 @@ async fn handle_event(
event_handler.typing_start(context, event).await;
});
},
DispatchEvent::Model(Event::Unknown(event)) => {
let event_handler = Arc::clone(event_handler);

spawn_named("dispatch::event_handler::unknown", async move {
event_handler.unknown(context, event.kind, event.value).await;
});
},
DispatchEvent::Model(Event::Unknown) => warn!("An unknown event was received"),
DispatchEvent::Model(Event::UserUpdate(mut event)) => {
let _before = update(&cache_and_http, &mut event);
let event_handler = Arc::clone(event_handler);
Expand Down
6 changes: 0 additions & 6 deletions src/client/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use async_trait::async_trait;

use super::context::Context;
use crate::client::bridge::gateway::event::*;
use crate::json::Value;
use crate::model::application::command::CommandPermission;
use crate::model::application::interaction::Interaction;
use crate::model::prelude::*;
Expand Down Expand Up @@ -390,11 +389,6 @@ pub trait EventHandler: Send + Sync {
/// Dispatched when a user starts typing.
async fn typing_start(&self, _ctx: Context, _: TypingStartEvent) {}

/// Dispatched when an unknown event was sent from discord.
///
/// Provides the event's name and its unparsed data.
async fn unknown(&self, _ctx: Context, _name: String, _raw: Value) {}

/// Dispatched when the bot's data is updated.
///
/// Provides the old and new data.
Expand Down
3 changes: 2 additions & 1 deletion src/gateway/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::client::bridge::gateway::ChunkGuildFilter;
use crate::constants::{self, OpCode};
use crate::gateway::{CurrentPresence, GatewayError};
use crate::json::{from_str, json, to_string, Value};
use crate::model::event::GatewayEvent;
use crate::model::gateway::GatewayIntents;
use crate::model::id::GuildId;
use crate::{Error, Result};
Expand All @@ -38,7 +39,7 @@ impl WsClient {
Ok(Self(stream))
}

pub(crate) async fn recv_json(&mut self) -> Result<Option<Value>> {
pub(crate) async fn recv_json(&mut self) -> Result<Option<GatewayEvent>> {
let message = match timeout(TIMEOUT, self.0.next()).await {
Ok(Some(Ok(msg))) => msg,
Ok(Some(Err(e))) => return Err(e.into()),
Expand Down
46 changes: 18 additions & 28 deletions src/model/application/component.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};

use crate::json::{from_value, JsonMap, Value};
use crate::internal::prelude::*;
use crate::json::from_value;
use crate::model::channel::ReactionType;
use crate::model::utils::deserialize_val;

/// The type of a component
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
Expand Down Expand Up @@ -44,39 +46,27 @@ pub enum ActionRowComponent {
}

impl<'de> Deserialize<'de> for ActionRowComponent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let map = JsonMap::deserialize(deserializer)?;

let kind = map
.get("type")
.ok_or_else(|| DeError::custom("expected type"))
.and_then(ComponentType::deserialize)
.map_err(DeError::custom)?;

match kind {
ComponentType::Button => from_value::<Button>(Value::from(map))
.map(ActionRowComponent::Button)
.map_err(DeError::custom),
ComponentType::SelectMenu => from_value::<SelectMenu>(Value::from(map))
.map(ActionRowComponent::SelectMenu)
.map_err(DeError::custom),
ComponentType::InputText => from_value::<InputText>(Value::from(map))
.map(ActionRowComponent::InputText)
.map_err(DeError::custom),
_ => Err(DeError::custom("Unknown component type")),
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Self, D::Error> {
let value = Value::deserialize(deserializer)?;
let map = value.as_object().ok_or_else(|| DeError::custom("expected JsonMap"))?;

let raw_kind = map.get("type").ok_or_else(|| DeError::missing_field("type"))?;
match deserialize_val(raw_kind.clone())? {
ComponentType::Button => from_value(value).map(ActionRowComponent::Button),
ComponentType::InputText => from_value(value).map(ActionRowComponent::InputText),
ComponentType::SelectMenu => from_value(value).map(ActionRowComponent::SelectMenu),
_ => return Err(DeError::custom("Unknown component type")),
}
.map_err(DeError::custom)
}
}

impl Serialize for ActionRowComponent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
match self {
ActionRowComponent::Button(c) => Button::serialize(c, serializer),
ActionRowComponent::SelectMenu(c) => SelectMenu::serialize(c, serializer),
ActionRowComponent::InputText(c) => InputText::serialize(c, serializer),
ActionRowComponent::Button(c) => c.serialize(serializer),
ActionRowComponent::InputText(c) => c.serialize(serializer),
ActionRowComponent::SelectMenu(c) => c.serialize(serializer),
}
}
}
Expand Down
Loading

0 comments on commit fee5da4

Please sign in to comment.