aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-06-10 21:55:33 -0700
committerZeyla Hellyer <[email protected]>2017-06-10 21:55:33 -0700
commitd0b64cd64a18a6116267fa09a837d62c19cced42 (patch)
treefc68a0891ea0ddd8187c38f289c8a9ccddc07e8c
parentFix voice compilation (diff)
downloadserenity-d0b64cd64a18a6116267fa09a837d62c19cced42.tar.xz
serenity-d0b64cd64a18a6116267fa09a837d62c19cced42.zip
Fix negative nonces failing to deserialize
Negative message nonces caused deserialization errors, as serde would not deserialize integers into strings. To fix this, change `Message::nonce` into an `Option<Snowflake>` from an `Option<String>`. This new `Snowflake` is a wrapper around an `i64`. Use a new `I64Visitor` to deserialize i64s, u64s, and strs into the wanted i64.
-rw-r--r--src/model/channel/message.rs2
-rw-r--r--src/model/mod.rs53
-rw-r--r--src/model/utils.rs31
-rw-r--r--tests/resources/message_create_2.json23
-rw-r--r--tests/test_deser.rs4
5 files changed, 110 insertions, 3 deletions
diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs
index e092703..930c046 100644
--- a/src/model/channel/message.rs
+++ b/src/model/channel/message.rs
@@ -48,7 +48,7 @@ pub struct Message {
/// Array of users mentioned in the message.
pub mentions: Vec<User>,
/// Non-repeating number used for ensuring message order.
- pub nonce: Option<String>,
+ pub nonce: Option<Snowflake>,
/// Indicator of whether the message is pinned.
pub pinned: bool,
/// Array of reactions performed on the message.
diff --git a/src/model/mod.rs b/src/model/mod.rs
index bc414c7..ace5969 100644
--- a/src/model/mod.rs
+++ b/src/model/mod.rs
@@ -53,7 +53,51 @@ use ::utils::Colour;
fn default_true() -> bool { true }
-macro_rules! id {
+macro_rules! id_i64 {
+ ($(#[$attr:meta] $name:ident;)*) => {
+ $(
+ #[$attr]
+ #[derive(Copy, Clone, Debug, Eq, Hash, PartialOrd, Ord, Serialize)]
+ #[allow(derive_hash_xor_eq)]
+ pub struct $name(pub i64);
+
+ impl $name {
+ /// Retrieves the time that the Id was created at.
+ pub fn created_at(&self) -> NaiveDateTime {
+ let offset = (self.0 >> 22) / 1000;
+
+ NaiveDateTime::from_timestamp(1420070400 + offset, 0)
+ }
+ }
+
+ impl From<i64> for $name {
+ fn from(v: i64) -> $name {
+ $name(v)
+ }
+ }
+
+ impl PartialEq for $name {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+ }
+
+ impl PartialEq<i64> for $name {
+ fn eq(&self, u: &i64) -> bool {
+ self.0 == *u
+ }
+ }
+
+ impl<'de> Deserialize<'de> for $name {
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
+ deserializer.deserialize_i64(I64Visitor).map($name)
+ }
+ }
+ )*
+ };
+}
+
+macro_rules! id_u64 {
($(#[$attr:meta] $name:ident;)*) => {
$(
#[$attr]
@@ -97,7 +141,7 @@ macro_rules! id {
}
}
-id! {
+id_u64! {
/// An identifier for a Channel
ChannelId;
/// An identifier for an Emoji
@@ -116,6 +160,11 @@ id! {
WebhookId;
}
+id_i64! {
+ /// An identifier for a general-purpose signed snowflake.
+ Snowflake;
+}
+
/// A container for guilds.
///
/// This is used to differentiate whether a guild itself can be used or whether
diff --git a/src/model/utils.rs b/src/model/utils.rs
index f88ecf5..6363fb6 100644
--- a/src/model/utils.rs
+++ b/src/model/utils.rs
@@ -240,3 +240,34 @@ impl<'de> Visitor<'de> for U64Visitor {
Ok(v)
}
}
+
+pub struct I64Visitor;
+
+impl<'de> Visitor<'de> for I64Visitor {
+ type Value = i64;
+
+ fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
+ formatter.write_str("identifier")
+ }
+
+ fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
+ match v.parse::<i64>() {
+ Ok(v) => Ok(v),
+ Err(_) => {
+ let mut s = String::new();
+ s.push_str("Unknown i64 value: ");
+ s.push_str(v);
+
+ Err(DeError::custom(s))
+ },
+ }
+ }
+
+ fn visit_i64<E: DeError>(self, v: i64) -> StdResult<Self::Value, E> {
+ Ok(v)
+ }
+
+ fn visit_u64<E: DeError>(self, v: u64) -> StdResult<Self::Value, E> {
+ Ok(v as i64)
+ }
+}
diff --git a/tests/resources/message_create_2.json b/tests/resources/message_create_2.json
new file mode 100644
index 0000000..f999397
--- /dev/null
+++ b/tests/resources/message_create_2.json
@@ -0,0 +1,23 @@
+{
+ "type": 0,
+ "tts": false,
+ "timestamp": "2017-01-01T01:01:01.100000+00:00",
+ "pinned": false,
+ "nonce": -6000000000000000,
+ "mentions": [],
+ "mention_roles": [],
+ "mention_everyone": false,
+ "id": "300000000000000000",
+ "embeds": [],
+ "edited_timestamp": null,
+ "content": "fake",
+ "channel_id": "100000000000000000",
+ "author": {
+ "username": "fake",
+ "id": "300000000000000000",
+ "discriminator": "1234",
+ "bot": true,
+ "avatar": "f133549aac3208319a9fbc3c12345678"
+ },
+ "attachments": []
+}
diff --git a/tests/test_deser.rs b/tests/test_deser.rs
index f4387bc..1024492 100644
--- a/tests/test_deser.rs
+++ b/tests/test_deser.rs
@@ -111,7 +111,11 @@ fn guild_update() {
#[test]
fn message_create() {
+ // standard
p!(MessageCreateEvent, "message_create_1");
+
+ // negative nonce
+ p!(MessageCreateEvent, "message_create_2");
}
#[test]