titanium_gateway/
opcode.rs

1//! Discord Gateway opcodes.
2//!
3//! Opcodes define the type of payload being sent or received over the Gateway WebSocket.
4
5use serde_repr::{Deserialize_repr, Serialize_repr};
6
7/// Discord Gateway operation codes.
8///
9/// See: <https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes>
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
11#[repr(u8)]
12pub enum OpCode {
13    /// Dispatch - An event was dispatched.
14    /// Direction: Receive
15    Dispatch = 0,
16
17    /// Heartbeat - Keep the connection alive.
18    /// Direction: Send/Receive
19    Heartbeat = 1,
20
21    /// Identify - Start a new session.
22    /// Direction: Send
23    Identify = 2,
24
25    /// Presence Update - Update the client's presence.
26    /// Direction: Send
27    PresenceUpdate = 3,
28
29    /// Voice State Update - Join/leave/move between voice channels.
30    /// Direction: Send
31    VoiceStateUpdate = 4,
32
33    /// Resume - Resume a previous session.
34    /// Direction: Send
35    Resume = 6,
36
37    /// Reconnect - Server requested a reconnect.
38    /// Direction: Receive
39    Reconnect = 7,
40
41    /// Request Guild Members - Request guild member chunks.
42    /// Direction: Send
43    RequestGuildMembers = 8,
44
45    /// Invalid Session - Session has been invalidated.
46    /// Direction: Receive
47    InvalidSession = 9,
48
49    /// Hello - Sent after connecting, contains heartbeat interval.
50    /// Direction: Receive
51    Hello = 10,
52
53    /// Heartbeat ACK - Acknowledgment of heartbeat received.
54    /// Direction: Receive
55    HeartbeatAck = 11,
56
57    /// Request Soundboard Sounds - Request soundboard sounds (API v10+).
58    /// Direction: Send
59    RequestSoundboardSounds = 31,
60}
61
62impl OpCode {
63    /// Returns whether this opcode is only received (not sent).
64    pub const fn is_receive_only(self) -> bool {
65        matches!(
66            self,
67            OpCode::Dispatch
68                | OpCode::Reconnect
69                | OpCode::InvalidSession
70                | OpCode::Hello
71                | OpCode::HeartbeatAck
72        )
73    }
74
75    /// Returns whether this opcode is only sent (not received).
76    pub const fn is_send_only(self) -> bool {
77        matches!(
78            self,
79            OpCode::Identify
80                | OpCode::PresenceUpdate
81                | OpCode::VoiceStateUpdate
82                | OpCode::Resume
83                | OpCode::RequestGuildMembers
84                | OpCode::RequestSoundboardSounds
85        )
86    }
87
88    /// Returns whether this opcode can be both sent and received.
89    pub const fn is_bidirectional(self) -> bool {
90        matches!(self, OpCode::Heartbeat)
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_opcode_serialization() {
100        let json = serde_json::to_string(&OpCode::Hello).unwrap();
101        assert_eq!(json, "10");
102
103        let opcode: OpCode = serde_json::from_str("10").unwrap();
104        assert_eq!(opcode, OpCode::Hello);
105    }
106
107    #[test]
108    fn test_opcode_direction() {
109        assert!(OpCode::Dispatch.is_receive_only());
110        assert!(OpCode::Identify.is_send_only());
111        assert!(OpCode::Heartbeat.is_bidirectional());
112    }
113}