Skip to content

Commit

Permalink
Fix negative nonces failing to deserialize
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Zeyla Hellyer committed Jun 11, 2017
1 parent 2f30f9a commit d0b64cd
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/model/channel/message.rs
Expand Up @@ -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.
Expand Down
53 changes: 51 additions & 2 deletions src/model/mod.rs
Expand Up @@ -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]
Expand Down Expand Up @@ -97,7 +141,7 @@ macro_rules! id {
}
}

id! {
id_u64! {
/// An identifier for a Channel
ChannelId;
/// An identifier for an Emoji
Expand All @@ -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
Expand Down
31 changes: 31 additions & 0 deletions src/model/utils.rs
Expand Up @@ -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)
}
}
23 changes: 23 additions & 0 deletions 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": []
}
4 changes: 4 additions & 0 deletions tests/test_deser.rs
Expand Up @@ -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]
Expand Down

0 comments on commit d0b64cd

Please sign in to comment.