You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.8 KiB
Rust
126 lines
2.8 KiB
Rust
use bytes::Bytes;
|
|
use serde::{Serialize, Deserialize};
|
|
use serde_repr::*;
|
|
use std::convert::{TryFrom, Infallible};
|
|
use std::num::ParseIntError;
|
|
use std::str::FromStr;
|
|
|
|
#[repr(u16)]
|
|
#[derive(Serialize_repr, Deserialize_repr, Copy, Ord, PartialOrd, Eq, PartialEq, Debug, Clone)]
|
|
enum GatewayOpcode {
|
|
Dispatch = 0,
|
|
Heartbeat = 1,
|
|
Identify = 2,
|
|
StatusUpdate = 3,
|
|
VoiceStateUpdate = 4,
|
|
Resume = 6,
|
|
Reconnect = 7,
|
|
RequestGuildMembers = 8,
|
|
InvalidSession = 9,
|
|
Hello = 10,
|
|
HeartbeatAck = 11,
|
|
|
|
UnknownError = 4000,
|
|
UnknownOpcode = 4001,
|
|
DecodeError = 4002,
|
|
NotAuthenticated = 4003,
|
|
AuthenticationFailed = 4004,
|
|
InvalidSeq = 4007,
|
|
RateLimited = 4008,
|
|
SessionTimeout = 4009,
|
|
InvalidShard = 4010,
|
|
ShardingRequired = 4011,
|
|
}
|
|
|
|
impl GatewayOpcode {
|
|
#[inline]
|
|
fn is_err(&self) -> bool {
|
|
return (*self as u16) >= 4000;
|
|
}
|
|
|
|
#[inline]
|
|
fn is_ok(&self) -> bool {
|
|
return (*self as u16) < 4000;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
struct GatewayEvent {
|
|
#[serde(rename = "op")]
|
|
opcode: GatewayOpcode,
|
|
#[serde(rename = "d")]
|
|
data: String,
|
|
#[serde(rename = "s")]
|
|
sequence_num: Option<u64>,
|
|
#[serde(rename = "t")]
|
|
event_name: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
struct Identify {
|
|
token: String,
|
|
properties: IdentifyProperties,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
struct IdentifyProperties {
|
|
#[serde(rename = "$os")]
|
|
os: String,
|
|
#[serde(rename = "$browser")]
|
|
browser: String,
|
|
#[serde(rename = "$device")]
|
|
device: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
struct Ready {
|
|
#[serde(rename = "v")]
|
|
protocol_version: u32,
|
|
user: (),
|
|
private_channels: Vec<()>,
|
|
guilds: Vec<UnavailableGuild>,
|
|
session_id: String,
|
|
shared: Option<(u32, u32)>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
struct UnavailableGuild {
|
|
id: Snowflake,
|
|
available: bool,
|
|
}
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(try_from = "String", into = "String")]
|
|
struct Snowflake(u64);
|
|
|
|
impl Into<String> for Snowflake {
|
|
fn into(self) -> String {
|
|
self.0.to_string()
|
|
}
|
|
}
|
|
|
|
|
|
impl TryFrom<String> for Snowflake {
|
|
type Error = ParseIntError;
|
|
|
|
fn try_from(from: String) -> Result<Snowflake, ParseIntError> {
|
|
Ok(Snowflake(u64::from_str(&from)?))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::discord::dto::{Snowflake, GatewayOpcode};
|
|
|
|
#[test]
|
|
fn snowflake() {
|
|
assert_eq!(Ok(Snowflake(4)), serde_json::from_str("\"4\"").map_err(|_| ()));
|
|
assert_eq!(Ok("\"4\"".to_string()), serde_json::to_string(&Snowflake(4)).map_err(|_| ()));
|
|
}
|
|
|
|
#[test]
|
|
fn opcode() {
|
|
assert!(GatewayOpcode::SessionTimeout.is_err())
|
|
}
|
|
} |