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, #[serde(rename = "t")] event_name: Option, } #[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, 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 for Snowflake { fn into(self) -> String { self.0.to_string() } } impl TryFrom for Snowflake { type Error = ParseIntError; fn try_from(from: String) -> Result { 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()) } }