aboutsummaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2018-01-01 15:55:46 -0800
committerZeyla Hellyer <[email protected]>2018-01-01 15:55:46 -0800
commit25dddb6695109eeead9e19593cb85a22096c2c7a (patch)
treed68d78d210a2804d10027035163871bf806c7e23 /src/model
parentGive hyper Response in HTTP errors (diff)
downloadserenity-25dddb6695109eeead9e19593cb85a22096c2c7a.tar.xz
serenity-25dddb6695109eeead9e19593cb85a22096c2c7a.zip
Implement or derive Serialize on all models
Diffstat (limited to 'src/model')
-rw-r--r--src/model/application.rs6
-rw-r--r--src/model/channel/attachment.rs2
-rw-r--r--src/model/channel/channel_category.rs2
-rw-r--r--src/model/channel/embed.rs16
-rw-r--r--src/model/channel/group.rs5
-rw-r--r--src/model/channel/guild_channel.rs2
-rw-r--r--src/model/channel/message.rs4
-rw-r--r--src/model/channel/mod.rs41
-rw-r--r--src/model/channel/private_channel.rs6
-rw-r--r--src/model/channel/reaction.rs27
-rw-r--r--src/model/event.rs163
-rw-r--r--src/model/gateway.rs36
-rw-r--r--src/model/guild/audit_log.rs110
-rw-r--r--src/model/guild/emoji.rs2
-rw-r--r--src/model/guild/integration.rs4
-rw-r--r--src/model/guild/member.rs5
-rw-r--r--src/model/guild/mod.rs20
-rw-r--r--src/model/guild/partial_guild.rs2
-rw-r--r--src/model/guild/role.rs2
-rw-r--r--src/model/invite.rs8
-rw-r--r--src/model/misc.rs8
-rw-r--r--src/model/permissions.rs28
-rw-r--r--src/model/user.rs4
-rw-r--r--src/model/utils.rs48
-rw-r--r--src/model/voice.rs4
-rw-r--r--src/model/webhook.rs2
26 files changed, 442 insertions, 115 deletions
diff --git a/src/model/application.rs b/src/model/application.rs
index dca8e41..47bbfb8 100644
--- a/src/model/application.rs
+++ b/src/model/application.rs
@@ -6,7 +6,7 @@ use super::utils::default_true;
/// Information about a user's application. An application does not necessarily
/// have an associated bot user.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ApplicationInfo {
/// The bot user associated with the application. See [`BotApplication`] for
/// more information.
@@ -47,7 +47,7 @@ pub struct ApplicationInfo {
}
/// Information about an application with an application's bot user.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BotApplication {
/// The unique Id of the bot user.
pub id: UserId,
@@ -73,7 +73,7 @@ pub struct BotApplication {
}
/// Information about the current application and its owner.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CurrentApplicationInfo {
pub description: String,
pub icon: Option<String>,
diff --git a/src/model/channel/attachment.rs b/src/model/channel/attachment.rs
index a9c625b..0530b6f 100644
--- a/src/model/channel/attachment.rs
+++ b/src/model/channel/attachment.rs
@@ -8,7 +8,7 @@ use std::io::Read;
/// A file uploaded with a message. Not to be confused with [`Embed`]s.
///
/// [`Embed`]: struct.Embed.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Attachment {
/// The unique ID given to this attachment.
pub id: String,
diff --git a/src/model/channel/channel_category.rs b/src/model/channel/channel_category.rs
index 7d6c900..18dbde4 100644
--- a/src/model/channel/channel_category.rs
+++ b/src/model/channel/channel_category.rs
@@ -12,7 +12,7 @@ use utils as serenity_utils;
/// A category of [`GuildChannel`]s.
///
/// [`GuildChannel`]: struct.GuildChannel.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelCategory {
/// Id of this category.
pub id: ChannelId,
diff --git a/src/model/channel/embed.rs b/src/model/channel/embed.rs
index 5359ed5..8837a8d 100644
--- a/src/model/channel/embed.rs
+++ b/src/model/channel/embed.rs
@@ -17,7 +17,7 @@ use utils;
/// 1024 in a field value, and 2048 in a description.
///
/// [slack's attachments]: https://api.slack.com/docs/message-attachments
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Embed {
/// Information about the author of the embed.
pub author: Option<EmbedAuthor>,
@@ -95,7 +95,7 @@ impl Embed {
}
/// An author object in an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedAuthor {
/// The URL of the author icon.
///
@@ -110,7 +110,7 @@ pub struct EmbedAuthor {
}
/// A field object in an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedField {
/// Indicator of whether the field should display as inline.
pub inline: bool,
@@ -143,7 +143,7 @@ impl EmbedField {
}
/// Footer information for an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedFooter {
/// The URL of the footer icon.
///
@@ -156,7 +156,7 @@ pub struct EmbedFooter {
}
/// An image object in an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedImage {
/// The height of the image.
pub height: u64,
@@ -171,7 +171,7 @@ pub struct EmbedImage {
}
/// The provider of an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedProvider {
/// The name of the provider.
pub name: String,
@@ -180,7 +180,7 @@ pub struct EmbedProvider {
}
/// The dimensions and URL of an embed thumbnail.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedThumbnail {
/// The height of the thumbnail in pixels.
pub height: u64,
@@ -195,7 +195,7 @@ pub struct EmbedThumbnail {
}
/// Video information for an embed.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmbedVideo {
/// The height of the video in pixels.
pub height: u64,
diff --git a/src/model/channel/group.rs b/src/model/channel/group.rs
index bff58aa..4a4070a 100644
--- a/src/model/channel/group.rs
+++ b/src/model/channel/group.rs
@@ -17,7 +17,7 @@ use std::fmt::Write as FmtWrite;
///
/// [`Guild`]: struct.Guild.html
/// [`User`]: struct.User.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Group {
/// The Id of the group channel.
#[serde(rename = "id")]
@@ -33,7 +33,8 @@ pub struct Group {
/// The Id of the group owner.
pub owner_id: UserId,
/// A map of the group's recipients.
- #[serde(deserialize_with = "deserialize_users")]
+ #[serde(deserialize_with = "deserialize_users",
+ serialize_with = "serialize_users")]
pub recipients: HashMap<UserId, Arc<RwLock<User>>>,
}
diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs
index c598314..749e72b 100644
--- a/src/model/channel/guild_channel.rs
+++ b/src/model/channel/guild_channel.rs
@@ -18,7 +18,7 @@ use utils as serenity_utils;
/// Represents a guild's text or voice channel. Some methods are available only
/// for voice channels and some are only available for text channels.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildChannel {
/// The unique Id of the channel.
///
diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs
index 87385ac..1bb55ab 100644
--- a/src/model/channel/message.rs
+++ b/src/model/channel/message.rs
@@ -17,7 +17,7 @@ use {constants, http, utils as serenity_utils};
/// A representation of a message over a guild's text channel, a group, or a
/// private channel.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Message {
/// The unique Id of the message. Can be used to calculate the creation date
/// of the message.
@@ -584,7 +584,7 @@ impl<'a> From<&'a Message> for MessageId {
///
/// [`count`]: #structfield.count
/// [reaction type]: enum.ReactionType.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageReaction {
/// The amount of the type of reaction that have been sent for the
/// associated message.
diff --git a/src/model/channel/mod.rs b/src/model/channel/mod.rs
index 7764fea..00fc7f6 100644
--- a/src/model/channel/mod.rs
+++ b/src/model/channel/mod.rs
@@ -23,6 +23,7 @@ pub use self::channel_category::*;
use internal::RwLockExt;
use model::prelude::*;
use serde::de::Error as DeError;
+use serde::ser::{SerializeStruct, Serialize, Serializer};
use serde_json;
use super::utils::deserialize_u64;
@@ -504,6 +505,26 @@ impl<'de> Deserialize<'de> for Channel {
}
}
+impl Serialize for Channel {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ match *self {
+ Channel::Category(ref c) => {
+ ChannelCategory::serialize(&*c.read(), serializer)
+ },
+ Channel::Group(ref c) => {
+ Group::serialize(&*c.read(), serializer)
+ },
+ Channel::Guild(ref c) => {
+ GuildChannel::serialize(&*c.read(), serializer)
+ },
+ Channel::Private(ref c) => {
+ PrivateChannel::serialize(&*c.read(), serializer)
+ },
+ }
+ }
+}
+
#[cfg(feature = "model")]
impl Display for Channel {
/// Formats the channel into a "mentioned" string.
@@ -582,7 +603,7 @@ impl ChannelType {
}
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Serialize)]
struct PermissionOverwriteData {
allow: Permissions,
deny: Permissions,
@@ -617,6 +638,24 @@ impl<'de> Deserialize<'de> for PermissionOverwrite {
}
}
+impl Serialize for PermissionOverwrite {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ let (id, kind) = match self.kind {
+ PermissionOverwriteType::Member(id) => (id.0, "member"),
+ PermissionOverwriteType::Role(id) => (id.0, "role"),
+ };
+
+ let mut state = serializer.serialize_struct("PermissionOverwrite", 4)?;
+ state.serialize_field("allow", &self.allow.bits())?;
+ state.serialize_field("deny", &self.deny.bits())?;
+ state.serialize_field("id", &id)?;
+ state.serialize_field("type", kind)?;
+
+ state.end()
+ }
+}
+
/// The type of edit being made to a Channel's permissions.
///
/// This is for use with methods such as `GuildChannel::create_permission`.
diff --git a/src/model/channel/private_channel.rs b/src/model/channel/private_channel.rs
index c9b6524..877fa13 100644
--- a/src/model/channel/private_channel.rs
+++ b/src/model/channel/private_channel.rs
@@ -11,7 +11,7 @@ use http::AttachmentType;
use internal::RwLockExt;
/// A Direct Message text channel with another user.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PrivateChannel {
/// The unique Id of the private channel.
///
@@ -31,7 +31,9 @@ pub struct PrivateChannel {
#[serde(rename = "type")]
pub kind: ChannelType,
/// The recipient to the private channel.
- #[serde(deserialize_with = "deserialize_single_recipient", rename = "recipients")]
+ #[serde(deserialize_with = "deserialize_single_recipient",
+ rename = "recipients",
+ serialize_with = "serialize_sync_user")]
pub recipient: Arc<RwLock<User>>,
}
diff --git a/src/model/channel/reaction.rs b/src/model/channel/reaction.rs
index 0741cd7..42c3578 100644
--- a/src/model/channel/reaction.rs
+++ b/src/model/channel/reaction.rs
@@ -1,5 +1,6 @@
use model::prelude::*;
use serde::de::{Deserialize, Error as DeError, MapAccess, Visitor};
+use serde::ser::{SerializeMap, Serialize, Serializer};
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult, Write as FmtWrite};
use std::str::FromStr;
@@ -11,7 +12,7 @@ use CACHE;
use http;
/// An emoji reaction to a message.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Reaction {
/// The [`Channel`] of the associated [`Message`].
///
@@ -255,6 +256,30 @@ impl<'de> Deserialize<'de> for ReactionType {
}
}
+impl Serialize for ReactionType {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ match *self {
+ ReactionType::Custom { animated, id, ref name } => {
+ let mut map = serializer.serialize_map(Some(3))?;
+
+ map.serialize_entry("animated", &animated)?;
+ map.serialize_entry("id", &id.0)?;
+ map.serialize_entry("name", &name)?;
+
+ map.end()
+ },
+ ReactionType::Unicode(ref name) => {
+ let mut map = serializer.serialize_map(Some(1))?;
+
+ map.serialize_entry("name", &name)?;
+
+ map.end()
+ },
+ }
+ }
+}
+
#[cfg(any(feature = "model", feature = "http"))]
impl ReactionType {
/// Creates a data-esque display of the type. This is not very useful for
diff --git a/src/model/event.rs b/src/model/event.rs
index e68fa7a..9cab339 100644
--- a/src/model/event.rs
+++ b/src/model/event.rs
@@ -2,6 +2,7 @@
use chrono::{DateTime, FixedOffset};
use serde::de::Error as DeError;
+use serde::ser::{Serialize, SerializeSeq, Serializer};
use serde_json;
use std::collections::HashMap;
use super::utils::deserialize_emojis;
@@ -44,6 +45,13 @@ impl<'de> Deserialize<'de> for ChannelCreateEvent {
}
}
+impl Serialize for ChannelCreateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Channel::serialize(&self.channel, serializer)
+ }
+}
+
#[cfg(feature = "cache")]
impl CacheUpdate for ChannelCreateEvent {
type Output = Channel;
@@ -153,7 +161,14 @@ impl<'de> Deserialize<'de> for ChannelDeleteEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for ChannelDeleteEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Channel::serialize(&self.channel, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelPinsUpdateEvent {
pub channel_id: ChannelId,
pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
@@ -193,7 +208,7 @@ impl CacheUpdate for ChannelPinsUpdateEvent {
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelRecipientAddEvent {
pub channel_id: ChannelId,
pub user: User,
@@ -216,7 +231,7 @@ impl CacheUpdate for ChannelRecipientAddEvent {
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelRecipientRemoveEvent {
pub channel_id: ChannelId,
pub user: User,
@@ -235,8 +250,6 @@ impl CacheUpdate for ChannelRecipientRemoveEvent {
}
}
-
-
#[derive(Clone, Debug)]
pub struct ChannelUpdateEvent {
pub channel: Channel,
@@ -306,14 +319,20 @@ impl<'de> Deserialize<'de> for ChannelUpdateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for ChannelUpdateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Channel::serialize(&self.channel, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildBanAddEvent {
pub guild_id: GuildId,
pub user: User,
}
-
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildBanRemoveEvent {
pub guild_id: GuildId,
pub user: User,
@@ -357,6 +376,13 @@ impl<'de> Deserialize<'de> for GuildCreateEvent {
}
}
+impl Serialize for GuildCreateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Guild::serialize(&self.guild, serializer)
+ }
+}
+
#[derive(Clone, Debug)]
pub struct GuildDeleteEvent {
pub guild: PartialGuild,
@@ -386,7 +412,14 @@ impl<'de> Deserialize<'de> for GuildDeleteEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for GuildDeleteEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ PartialGuild::serialize(&self.guild, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildEmojisUpdateEvent {
#[serde(deserialize_with = "deserialize_emojis")] pub emojis: HashMap<EmojiId, Emoji>,
pub guild_id: GuildId,
@@ -407,12 +440,12 @@ impl CacheUpdate for GuildEmojisUpdateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildIntegrationsUpdateEvent {
pub guild_id: GuildId,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct GuildMemberAddEvent {
pub guild_id: GuildId,
pub member: Member,
@@ -440,7 +473,6 @@ impl CacheUpdate for GuildMemberAddEvent {
}
}
-
impl<'de> Deserialize<'de> for GuildMemberAddEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let map = JsonMap::deserialize(deserializer)?;
@@ -458,7 +490,7 @@ impl<'de> Deserialize<'de> for GuildMemberAddEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildMemberRemoveEvent {
pub guild_id: GuildId,
pub user: User,
@@ -478,7 +510,7 @@ impl CacheUpdate for GuildMemberRemoveEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildMemberUpdateEvent {
pub guild_id: GuildId,
pub nick: Option<String>,
@@ -534,7 +566,7 @@ impl CacheUpdate for GuildMemberUpdateEvent {
}
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct GuildMembersChunkEvent {
pub guild_id: GuildId,
pub members: HashMap<UserId, Member>,
@@ -589,7 +621,7 @@ impl<'de> Deserialize<'de> for GuildMembersChunkEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildRoleCreateEvent {
pub guild_id: GuildId,
pub role: Role,
@@ -611,7 +643,7 @@ impl CacheUpdate for GuildRoleCreateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildRoleDeleteEvent {
pub guild_id: GuildId,
pub role_id: RoleId,
@@ -629,7 +661,7 @@ impl CacheUpdate for GuildRoleDeleteEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildRoleUpdateEvent {
pub guild_id: GuildId,
pub role: Role,
@@ -650,7 +682,7 @@ impl CacheUpdate for GuildRoleUpdateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildUnavailableEvent {
#[serde(rename = "id")] pub guild_id: GuildId,
}
@@ -702,6 +734,13 @@ impl<'de> Deserialize<'de> for GuildUpdateEvent {
}
}
+impl Serialize for GuildUpdateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ PartialGuild::serialize(&self.guild, serializer)
+ }
+}
+
#[derive(Clone, Debug)]
pub struct MessageCreateEvent {
pub message: Message,
@@ -715,19 +754,26 @@ impl<'de> Deserialize<'de> for MessageCreateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for MessageCreateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Message::serialize(&self.message, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageDeleteBulkEvent {
pub channel_id: ChannelId,
pub ids: Vec<MessageId>,
}
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct MessageDeleteEvent {
pub channel_id: ChannelId,
#[serde(rename = "id")] pub message_id: MessageId,
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageUpdateEvent {
pub id: MessageId,
pub channel_id: ChannelId,
@@ -746,7 +792,7 @@ pub struct MessageUpdateEvent {
pub embeds: Option<Vec<Value>>,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct PresenceUpdateEvent {
pub guild_id: Option<GuildId>,
pub presence: Presence,
@@ -849,6 +895,19 @@ impl<'de> Deserialize<'de> for PresencesReplaceEvent {
}
}
+impl Serialize for PresencesReplaceEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ let mut seq = serializer.serialize_seq(Some(self.presences.len()))?;
+
+ for value in &self.presences {
+ seq.serialize_element(value)?;
+ }
+
+ seq.end()
+ }
+}
+
#[derive(Clone, Debug)]
pub struct ReactionAddEvent {
pub reaction: Reaction,
@@ -862,6 +921,13 @@ impl<'de> Deserialize<'de> for ReactionAddEvent {
}
}
+impl Serialize for ReactionAddEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Reaction::serialize(&self.reaction, serializer)
+ }
+}
+
#[derive(Clone, Debug)]
pub struct ReactionRemoveEvent {
pub reaction: Reaction,
@@ -875,7 +941,14 @@ impl<'de> Deserialize<'de> for ReactionRemoveEvent {
}
}
-#[derive(Clone, Copy, Debug, Deserialize)]
+impl Serialize for ReactionRemoveEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Reaction::serialize(&self.reaction, serializer)
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct ReactionRemoveAllEvent {
pub channel_id: ChannelId,
pub message_id: MessageId,
@@ -935,19 +1008,26 @@ impl<'de> Deserialize<'de> for ReadyEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for ReadyEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ Ready::serialize(&self.ready, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ResumedEvent {
#[serde(rename = "_trace")] pub trace: Vec<Option<String>>,
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TypingStartEvent {
pub channel_id: ChannelId,
pub timestamp: u64,
pub user_id: UserId,
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UnknownEvent {
pub kind: String,
pub value: Value,
@@ -975,7 +1055,14 @@ impl<'de> Deserialize<'de> for UserUpdateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+impl Serialize for UserUpdateEvent {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ CurrentUser::serialize(&self.current_user, serializer)
+ }
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceServerUpdateEvent {
pub channel_id: Option<ChannelId>,
pub endpoint: Option<String>,
@@ -983,7 +1070,7 @@ pub struct VoiceServerUpdateEvent {
pub token: String,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct VoiceStateUpdateEvent {
pub guild_id: Option<GuildId>,
pub voice_state: VoiceState,
@@ -1042,14 +1129,15 @@ impl<'de> Deserialize<'de> for VoiceStateUpdateEvent {
}
}
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WebhookUpdateEvent {
pub channel_id: ChannelId,
pub guild_id: GuildId,
}
#[allow(large_enum_variant)]
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize)]
+#[serde(untagged)]
pub enum GatewayEvent {
Dispatch(u64, Event),
Heartbeat(u64),
@@ -1128,7 +1216,7 @@ impl<'de> Deserialize<'de> for GatewayEvent {
/// Event received over a websocket connection
#[allow(large_enum_variant)]
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Event {
/// A [`Channel`] was created.
///
@@ -1668,13 +1756,13 @@ impl<'de> Deserialize<'de> for EventType {
}
#[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct VoiceHeartbeat {
pub heartbeat_interval: u64,
}
#[allow(missing_docs)]
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceHello {
pub heartbeat_interval: u64,
pub ip: String,
@@ -1684,14 +1772,14 @@ pub struct VoiceHello {
}
#[allow(missing_docs)]
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceSessionDescription {
pub mode: String,
pub secret_key: Vec<u8>,
}
#[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct VoiceSpeaking {
pub speaking: bool,
pub ssrc: u32,
@@ -1701,7 +1789,8 @@ pub struct VoiceSpeaking {
/// A representation of data received for [`voice`] events.
///
/// [`voice`]: ../../voice/index.html
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
+#[serde(untagged)]
pub enum VoiceEvent {
/// A voice heartbeat.
Heartbeat(VoiceHeartbeat),
diff --git a/src/model/gateway.rs b/src/model/gateway.rs
index c097c6f..52c8e96 100644
--- a/src/model/gateway.rs
+++ b/src/model/gateway.rs
@@ -2,6 +2,7 @@
use parking_lot::RwLock;
use serde::de::Error as DeError;
+use serde::ser::{SerializeStruct, Serialize, Serializer};
use serde_json;
use std::sync::Arc;
use super::utils::*;
@@ -13,7 +14,7 @@ use super::prelude::*;
/// shards that Discord recommends to use for a bot user.
///
/// This is only applicable to bot users.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BotGateway {
/// The number of shards that is recommended to be used by the current bot
/// user.
@@ -24,9 +25,10 @@ pub struct BotGateway {
/// Representation of a game that a [`User`] is playing -- or streaming in the
/// case that a stream URL is provided.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct Game {
/// The type of game status.
+ #[serde(default, rename = "type")]
pub kind: GameType,
/// The name of the game being played.
pub name: String,
@@ -214,7 +216,7 @@ impl Default for GameType {
/// For the bot-specific gateway, refer to [`BotGateway`].
///
/// [`BotGateway`]: struct.BotGateway.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Gateway {
/// The gateway to connect to.
pub url: String,
@@ -295,8 +297,34 @@ impl<'de> Deserialize<'de> for Presence {
}
}
+impl Serialize for Presence {
+ fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
+ where S: Serializer {
+ #[derive(Serialize)]
+ struct UserId {
+ id: u64,
+ }
+
+ let mut state = serializer.serialize_struct("Presence", 5)?;
+ state.serialize_field("game", &self.game)?;
+ state.serialize_field("last_modified", &self.last_modified)?;
+ state.serialize_field("nick", &self.nick)?;
+ state.serialize_field("status", &self.status)?;
+
+ if let Some(ref user) = self.user {
+ state.serialize_field("user", &*user.read())?;
+ } else {
+ state.serialize_field("user", &UserId {
+ id: self.user_id.0,
+ })?;
+ }
+
+ state.end()
+ }
+}
+
/// An initial set of information given after IDENTIFYing to the gateway.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ready {
pub guilds: Vec<GuildStatus>,
#[serde(default, deserialize_with = "deserialize_presences")]
diff --git a/src/model/guild/audit_log.rs b/src/model/guild/audit_log.rs
index 7437e42..c85bab9 100644
--- a/src/model/guild/audit_log.rs
+++ b/src/model/guild/audit_log.rs
@@ -1,5 +1,6 @@
use internal::prelude::*;
use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
+use serde::ser::Serializer;
use super::super::prelude::*;
use std::collections::HashMap;
use std::mem::transmute;
@@ -32,6 +33,24 @@ pub enum Action {
MessageDelete,
}
+impl Action {
+ pub fn num(&self) -> u8 {
+ use self::Action::*;
+
+ match *self {
+ GuildUpdate => 1,
+ Action::Channel(ref x) => x.num(),
+ Action::ChannelOverwrite(ref x) => x.num(),
+ Action::Member(ref x) => x.num(),
+ Action::Role(ref x) => x.num(),
+ Action::Invite(ref x) => x.num(),
+ Action::Webhook(ref x) => x.num(),
+ Action::Emoji(ref x) => x.num(),
+ Action::MessageDelete => 72,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannel {
@@ -40,6 +59,16 @@ pub enum ActionChannel {
Delete = 12,
}
+impl ActionChannel {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionChannel::Create => 10,
+ ActionChannel::Update => 11,
+ ActionChannel::Delete => 12,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannelOverwrite {
@@ -48,6 +77,16 @@ pub enum ActionChannelOverwrite {
Delete = 15,
}
+impl ActionChannelOverwrite {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionChannelOverwrite::Create => 13,
+ ActionChannelOverwrite::Update => 14,
+ ActionChannelOverwrite::Delete => 15,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionMember {
@@ -59,6 +98,19 @@ pub enum ActionMember {
RoleUpdate = 25,
}
+impl ActionMember {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionMember::Kick => 20,
+ ActionMember::Prune => 21,
+ ActionMember::BanAdd => 22,
+ ActionMember::BanRemove => 23,
+ ActionMember::Update => 24,
+ ActionMember::RoleUpdate => 25,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionRole {
@@ -67,6 +119,16 @@ pub enum ActionRole {
Delete = 32,
}
+impl ActionRole {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionRole::Create => 30,
+ ActionRole::Update => 31,
+ ActionRole::Delete => 32,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionInvite {
@@ -75,6 +137,16 @@ pub enum ActionInvite {
Delete = 42,
}
+impl ActionInvite {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionInvite::Create => 40,
+ ActionInvite::Update => 41,
+ ActionInvite::Delete => 42,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionWebhook {
@@ -83,6 +155,16 @@ pub enum ActionWebhook {
Delete = 52,
}
+impl ActionWebhook {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionWebhook::Create => 50,
+ ActionWebhook::Update => 51,
+ ActionWebhook::Delete => 52,
+ }
+ }
+}
+
#[derive(Debug)]
#[repr(u8)]
pub enum ActionEmoji {
@@ -91,7 +173,17 @@ pub enum ActionEmoji {
Update = 62,
}
-#[derive(Debug, Deserialize)]
+impl ActionEmoji {
+ pub fn num(&self) -> u8 {
+ match *self {
+ ActionEmoji::Create => 60,
+ ActionEmoji::Update => 61,
+ ActionEmoji::Delete => 62,
+ }
+ }
+}
+
+#[derive(Debug, Deserialize, Serialize)]
pub struct Change {
#[serde(rename = "key")] pub name: String,
// TODO: Change these to an actual type.
@@ -106,7 +198,7 @@ pub struct AuditLogs {
pub users: Vec<User>,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Serialize)]
pub struct AuditLogEntry {
/// Determines to what entity an [`action`] was used on.
///
@@ -115,7 +207,9 @@ pub struct AuditLogEntry {
/// Determines what action was done on a [`target`]
///
/// [`target`]: #structfield.target
- #[serde(deserialize_with = "deserialize_action", rename = "action_type")]
+ #[serde(deserialize_with = "deserialize_action",
+ rename = "action_type",
+ serialize_with = "serialize_action")]
pub action: Action,
/// What was the reasoning by doing an action on a target? If there was one.
pub reason: Option<String>,
@@ -129,7 +223,7 @@ pub struct AuditLogEntry {
pub options: Option<Options>,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Serialize)]
pub struct Options {
/// Number of days after which inactive members were kicked.
pub delete_member_days: String,
@@ -145,7 +239,6 @@ pub struct Options {
#[serde(rename = "type")] pub kind: String,
/// Name of the role if type is "role"
pub role_name: String,
-
}
fn deserialize_action<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::Error> {
@@ -177,6 +270,13 @@ fn deserialize_action<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::
de.deserialize_u8(ActionVisitor)
}
+fn serialize_action<S: Serializer>(
+ action: &Action,
+ serializer: S,
+) -> StdResult<S::Ok, S::Error> {
+ serializer.serialize_u8(action.num())
+}
+
impl<'de> Deserialize<'de> for AuditLogs {
fn deserialize<D: Deserializer<'de>>(de: D) -> StdResult<Self, D::Error> {
#[derive(Deserialize)]
diff --git a/src/model/guild/emoji.rs b/src/model/guild/emoji.rs
index 919c29d..a4612f0 100644
--- a/src/model/guild/emoji.rs
+++ b/src/model/guild/emoji.rs
@@ -15,7 +15,7 @@ use {CACHE, http};
/// Represents a custom guild emoji, which can either be created using the API,
/// or via an integration. Emojis created using the API only work within the
/// guild it was created in.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Emoji {
/// Whether the emoji is animated.
#[serde(default)]
diff --git a/src/model/guild/integration.rs b/src/model/guild/integration.rs
index b903a2c..b9d45ac 100644
--- a/src/model/guild/integration.rs
+++ b/src/model/guild/integration.rs
@@ -1,7 +1,7 @@
use super::*;
/// Various information about integrations.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Integration {
pub id: IntegrationId,
pub account: IntegrationAccount,
@@ -22,7 +22,7 @@ impl From<Integration> for IntegrationId {
}
/// Integration account object.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IntegrationAccount {
pub id: String,
pub name: String,
diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs
index f2e798a..c8b0a3b 100644
--- a/src/model/guild/member.rs
+++ b/src/model/guild/member.rs
@@ -49,7 +49,7 @@ impl BanOptions for (u8, String) {
}
/// Information about a member of a guild.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Member {
/// Indicator of whether the member can hear in voice channels.
pub deaf: bool,
@@ -66,7 +66,8 @@ pub struct Member {
/// Vector of Ids of [`Role`]s given to the member.
pub roles: Vec<RoleId>,
/// Attached User struct.
- #[serde(deserialize_with = "deserialize_sync_user")]
+ #[serde(deserialize_with = "deserialize_sync_user",
+ serialize_with = "serialize_sync_user")]
pub user: Arc<RwLock<User>>,
}
diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs
index 44a911c..bc97ba8 100644
--- a/src/model/guild/mod.rs
+++ b/src/model/guild/mod.rs
@@ -34,7 +34,7 @@ use constants::LARGE_THRESHOLD;
use std;
/// A representation of a banning of a user.
-#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash)]
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize)]
pub struct Ban {
/// The reason given for this ban.
pub reason: Option<String>,
@@ -43,7 +43,7 @@ pub struct Ban {
}
/// Information about a Discord guild, such as channels, emojis, etc.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
pub struct Guild {
/// Id of a voice channel that's considered the AFK channel.
pub afk_channel_id: Option<ChannelId>,
@@ -56,11 +56,13 @@ pub struct Guild {
///
/// This contains all channels regardless of permissions (i.e. the ability
/// of the bot to read from or connect to them).
+ #[serde(serialize_with = "serialize_gen_locked_map")]
pub channels: HashMap<ChannelId, Arc<RwLock<GuildChannel>>>,
/// Indicator of whether notifications for all messages are enabled by
/// default in the guild.
pub default_message_notifications: DefaultMessageNotificationLevel,
/// All of the guild's custom emojis.
+ #[serde(serialize_with = "serialize_gen_map")]
pub emojis: HashMap<EmojiId, Emoji>,
/// Default explicit content filter level.
pub explicit_content_filter: ExplicitContentFilter,
@@ -98,6 +100,7 @@ pub struct Guild {
/// the library.
///
/// [`ReadyEvent`]: events/struct.ReadyEvent.html
+ #[serde(serialize_with = "serialize_gen_map")]
pub members: HashMap<UserId, Member>,
/// Indicator of whether the guild requires multi-factor authentication for
/// [`Role`]s or [`User`]s with moderation permissions.
@@ -114,10 +117,12 @@ pub struct Guild {
/// A mapping of [`User`]s' Ids to their current presences.
///
/// [`User`]: struct.User.html
+ #[serde(serialize_with = "serialize_gen_map")]
pub presences: HashMap<UserId, Presence>,
/// The region that the voice servers that the guild uses are located in.
pub region: String,
/// A mapping of the guild's roles.
+ #[serde(serialize_with = "serialize_gen_map")]
pub roles: HashMap<RoleId, Role>,
/// An identifying hash of the guild's splash icon.
///
@@ -133,6 +138,7 @@ pub struct Guild {
/// A mapping of of [`User`]s to their current voice state.
///
/// [`User`]: struct.User.html
+ #[serde(serialize_with = "serialize_gen_map")]
pub voice_states: HashMap<UserId, VoiceState>,
}
@@ -1606,7 +1612,7 @@ pub enum GuildContainer {
}
/// Information relating to a guild's widget embed.
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct GuildEmbed {
/// The Id of the channel to show the embed for.
pub channel_id: ChannelId,
@@ -1616,14 +1622,14 @@ pub struct GuildEmbed {
/// Representation of the number of members that would be pruned by a guild
/// prune operation.
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct GuildPrune {
/// The number of members that would be pruned by the operation.
pub pruned: u64,
}
/// Basic information about a guild.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GuildInfo {
/// The unique Id of the guild.
///
@@ -1674,7 +1680,7 @@ impl InviteGuild {
}
/// Data for an unavailable guild.
-#[derive(Clone, Copy, Debug, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct GuildUnavailable {
/// The Id of the [`Guild`] that is unavailable.
///
@@ -1687,7 +1693,7 @@ pub struct GuildUnavailable {
}
#[allow(large_enum_variant)]
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum GuildStatus {
OnlinePartialGuild(PartialGuild),
diff --git a/src/model/guild/partial_guild.rs b/src/model/guild/partial_guild.rs
index cd51a98..e67ca03 100644
--- a/src/model/guild/partial_guild.rs
+++ b/src/model/guild/partial_guild.rs
@@ -8,7 +8,7 @@ use builder::{EditGuild, EditMember, EditRole};
/// like member data.
///
/// [`Guild`]: struct.Guild.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PartialGuild {
pub id: GuildId,
pub afk_channel_id: Option<ChannelId>,
diff --git a/src/model/guild/role.rs b/src/model/guild/role.rs
index 6215c4e..53ec478 100644
--- a/src/model/guild/role.rs
+++ b/src/model/guild/role.rs
@@ -14,7 +14,7 @@ use {CACHE, http};
/// are unique per guild and do not cross over to other guilds in any way, and
/// can have channel-specific permission overrides in addition to guild-level
/// permissions.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Role {
/// The Id of the role. Can be used to calculate the role's creation date.
pub id: RoleId,
diff --git a/src/model/invite.rs b/src/model/invite.rs
index 5429656..6573e35 100644
--- a/src/model/invite.rs
+++ b/src/model/invite.rs
@@ -15,7 +15,7 @@ use {http, utils};
/// Information about an invite code.
///
/// Information can not be accessed for guilds the current user is banned from.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Invite {
/// The approximate number of [`Member`]s in the related [`Guild`].
///
@@ -152,7 +152,7 @@ impl Invite {
}
/// A inimal information about the channel an invite points to.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteChannel {
pub id: ChannelId,
pub name: String,
@@ -160,7 +160,7 @@ pub struct InviteChannel {
}
/// A minimal amount of information about the guild an invite points to.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteGuild {
pub id: GuildId,
pub icon: Option<String>,
@@ -218,7 +218,7 @@ impl InviteGuild {
///
/// [`Invite`]: struct.Invite.html
/// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RichInvite {
/// A representation of the minimal amount of information needed about the
/// channel being invited to.
diff --git a/src/model/misc.rs b/src/model/misc.rs
index ee048af..183ddc3 100644
--- a/src/model/misc.rs
+++ b/src/model/misc.rs
@@ -220,7 +220,7 @@ impl FromStr for EmojiIdentifier {
/// A component that was affected during a service incident.
///
/// This is pulled from the Discord status page.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AffectedComponent {
pub name: String,
}
@@ -228,7 +228,7 @@ pub struct AffectedComponent {
/// An incident retrieved from the Discord status page.
///
/// This is not necessarily a representation of an ongoing incident.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Incident {
pub created_at: String,
pub id: String,
@@ -247,7 +247,7 @@ pub struct Incident {
///
/// This will typically state what new information has been discovered about an
/// incident.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IncidentUpdate {
pub affected_components: Vec<AffectedComponent>,
pub body: String,
@@ -272,7 +272,7 @@ pub enum IncidentStatus {
/// A Discord status maintenance message. This can be either for active
/// maintenances or for scheduled maintenances.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Maintenance {
pub description: String,
pub id: String,
diff --git a/src/model/permissions.rs b/src/model/permissions.rs
index ef5510b..dbf0b69 100644
--- a/src/model/permissions.rs
+++ b/src/model/permissions.rs
@@ -44,10 +44,9 @@
//! [Manage Roles]: constant.MANAGE_ROLES.html
//! [Manage Webhooks]: constant.MANAGE_WEBHOOKS.html
-use serde::de::{Error as DeError, Visitor};
-use serde::{Deserialize, Deserializer};
-use std::fmt::{Formatter, Result as FmtResult};
-use std::result::Result as StdResult;
+use serde::de::{Deserialize, Deserializer};
+use serde::ser::{Serialize, Serializer};
+use super::utils::U64Visitor;
/// Returns a set of permissions with the original @everyone permissions set
/// to true.
@@ -433,27 +432,16 @@ impl Permissions {
}
impl<'de> Deserialize<'de> for Permissions {
- fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(Permissions::from_bits_truncate(
deserializer.deserialize_u64(U64Visitor)?,
))
}
}
-struct U64Visitor;
-
-impl<'de> Visitor<'de> for U64Visitor {
- type Value = u64;
-
- fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
- formatter.write_str("an unsigned 64-bit integer")
+impl Serialize for Permissions {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where S: Serializer {
+ serializer.serialize_u64(self.bits())
}
-
- fn visit_i32<E: DeError>(self, value: i32) -> StdResult<u64, E> { Ok(value as u64) }
-
- fn visit_i64<E: DeError>(self, value: i64) -> StdResult<u64, E> { Ok(value as u64) }
-
- fn visit_u32<E: DeError>(self, value: u32) -> StdResult<u64, E> { Ok(u64::from(value)) }
-
- fn visit_u64<E: DeError>(self, value: u64) -> StdResult<u64, E> { Ok(value) }
}
diff --git a/src/model/user.rs b/src/model/user.rs
index fc1ec3a..1cedf3e 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -27,7 +27,7 @@ use std::sync::Arc;
use utils;
/// Information about the current user.
-#[derive(Clone, Default, Debug, Deserialize)]
+#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct CurrentUser {
pub id: UserId,
pub avatar: Option<String>,
@@ -337,7 +337,7 @@ impl Default for OnlineStatus {
}
/// Information about a user.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct User {
/// The unique Id of the user. Can be used to calculate the account's
/// creation date.
diff --git a/src/model/utils.rs b/src/model/utils.rs
index 9d4ca88..981b61b 100644
--- a/src/model/utils.rs
+++ b/src/model/utils.rs
@@ -1,6 +1,8 @@
use parking_lot::RwLock;
use serde::de::Error as DeError;
+use serde::ser::{SerializeSeq, Serialize, Serializer};
use std::collections::HashMap;
+use std::hash::Hash;
use std::sync::Arc;
use super::prelude::*;
@@ -121,6 +123,13 @@ pub fn deserialize_sync_user<'de, D>(deserializer: D)
Ok(Arc::new(RwLock::new(User::deserialize(deserializer)?)))
}
+pub fn serialize_sync_user<S: Serializer>(
+ user: &Arc<RwLock<User>>,
+ serializer: S,
+) -> StdResult<S::Ok, S::Error> {
+ User::serialize(&*user.read(), serializer)
+}
+
pub fn deserialize_users<'de, D: Deserializer<'de>>(
deserializer: D)
-> StdResult<HashMap<UserId, Arc<RwLock<User>>>, D::Error> {
@@ -134,6 +143,19 @@ pub fn deserialize_users<'de, D: Deserializer<'de>>(
Ok(users)
}
+pub fn serialize_users<S: Serializer>(
+ users: &HashMap<UserId, Arc<RwLock<User>>>,
+ serializer: S
+) -> StdResult<S::Ok, S::Error> {
+ let mut seq = serializer.serialize_seq(Some(users.len()))?;
+
+ for user in users.values() {
+ seq.serialize_element(&*user.read())?;
+ }
+
+ seq.end()
+}
+
pub fn deserialize_u16<'de, D: Deserializer<'de>>(deserializer: D) -> StdResult<u16, D::Error> {
deserializer.deserialize_any(U16Visitor)
}
@@ -155,6 +177,32 @@ pub fn deserialize_voice_states<'de, D: Deserializer<'de>>(
Ok(voice_states)
}
+pub fn serialize_gen_map<K: Eq + Hash, S: Serializer, V: Serialize>(
+ map: &HashMap<K, V>,
+ serializer: S,
+) -> StdResult<S::Ok, S::Error> {
+ let mut seq = serializer.serialize_seq(Some(map.len()))?;
+
+ for value in map.values() {
+ seq.serialize_element(&value)?;
+ }
+
+ seq.end()
+}
+
+pub fn serialize_gen_locked_map<K: Eq + Hash, S: Serializer, V: Serialize>(
+ map: &HashMap<K, Arc<RwLock<V>>>,
+ serializer: S,
+) -> StdResult<S::Ok, S::Error> {
+ let mut seq = serializer.serialize_seq(Some(map.len()))?;
+
+ for value in map.values() {
+ seq.serialize_element(&*value.read())?;
+ }
+
+ seq.end()
+}
+
#[cfg(all(feature = "cache", feature = "model"))]
pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> {
let cache = CACHE.read();
diff --git a/src/model/voice.rs b/src/model/voice.rs
index 558be4f..3eb968f 100644
--- a/src/model/voice.rs
+++ b/src/model/voice.rs
@@ -3,7 +3,7 @@
use super::id::{ChannelId, UserId};
/// Information about an available voice region.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceRegion {
/// Whether it is a custom voice region, which is used for events.
pub custom: bool,
@@ -24,7 +24,7 @@ pub struct VoiceRegion {
}
/// A user's state within a voice channel.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VoiceState {
pub channel_id: Option<ChannelId>,
pub deaf: bool,
diff --git a/src/model/webhook.rs b/src/model/webhook.rs
index d9a4483..8b9d0f2 100644
--- a/src/model/webhook.rs
+++ b/src/model/webhook.rs
@@ -16,7 +16,7 @@ use {http, utils};
/// A representation of a webhook, which is a low-effort way to post messages to
/// channels. They do not necessarily require a bot user or authentication to
/// use.
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Webhook {
/// The unique Id.
///