diff options
| author | Zeyla Hellyer <[email protected]> | 2018-01-01 15:55:46 -0800 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2018-01-01 15:55:46 -0800 |
| commit | 25dddb6695109eeead9e19593cb85a22096c2c7a (patch) | |
| tree | d68d78d210a2804d10027035163871bf806c7e23 /src/model | |
| parent | Give hyper Response in HTTP errors (diff) | |
| download | serenity-25dddb6695109eeead9e19593cb85a22096c2c7a.tar.xz serenity-25dddb6695109eeead9e19593cb85a22096c2c7a.zip | |
Implement or derive Serialize on all models
Diffstat (limited to 'src/model')
| -rw-r--r-- | src/model/application.rs | 6 | ||||
| -rw-r--r-- | src/model/channel/attachment.rs | 2 | ||||
| -rw-r--r-- | src/model/channel/channel_category.rs | 2 | ||||
| -rw-r--r-- | src/model/channel/embed.rs | 16 | ||||
| -rw-r--r-- | src/model/channel/group.rs | 5 | ||||
| -rw-r--r-- | src/model/channel/guild_channel.rs | 2 | ||||
| -rw-r--r-- | src/model/channel/message.rs | 4 | ||||
| -rw-r--r-- | src/model/channel/mod.rs | 41 | ||||
| -rw-r--r-- | src/model/channel/private_channel.rs | 6 | ||||
| -rw-r--r-- | src/model/channel/reaction.rs | 27 | ||||
| -rw-r--r-- | src/model/event.rs | 163 | ||||
| -rw-r--r-- | src/model/gateway.rs | 36 | ||||
| -rw-r--r-- | src/model/guild/audit_log.rs | 110 | ||||
| -rw-r--r-- | src/model/guild/emoji.rs | 2 | ||||
| -rw-r--r-- | src/model/guild/integration.rs | 4 | ||||
| -rw-r--r-- | src/model/guild/member.rs | 5 | ||||
| -rw-r--r-- | src/model/guild/mod.rs | 20 | ||||
| -rw-r--r-- | src/model/guild/partial_guild.rs | 2 | ||||
| -rw-r--r-- | src/model/guild/role.rs | 2 | ||||
| -rw-r--r-- | src/model/invite.rs | 8 | ||||
| -rw-r--r-- | src/model/misc.rs | 8 | ||||
| -rw-r--r-- | src/model/permissions.rs | 28 | ||||
| -rw-r--r-- | src/model/user.rs | 4 | ||||
| -rw-r--r-- | src/model/utils.rs | 48 | ||||
| -rw-r--r-- | src/model/voice.rs | 4 | ||||
| -rw-r--r-- | src/model/webhook.rs | 2 |
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. /// |