Skip to main content

wsio_core/packet/
mod.rs

1use serde::{
2    Deserialize,
3    Serialize,
4};
5use serde_repr::{
6    Deserialize_repr,
7    Serialize_repr,
8};
9
10pub mod codecs;
11
12// Enums
13#[repr(u8)]
14#[derive(Clone, Debug, Deserialize_repr, Serialize_repr)]
15pub enum WsIoPacketType {
16    Disconnect = 0,
17    Event = 1,
18    Init = 2,
19    Ready = 3,
20}
21
22// Structs
23#[derive(Deserialize)]
24struct InnerPacket(WsIoPacketType, Option<String>, Option<Vec<u8>>);
25
26#[derive(Serialize)]
27struct InnerPacketRef<'a>(&'a WsIoPacketType, &'a Option<String>, &'a Option<Vec<u8>>);
28
29#[derive(Clone, Debug)]
30pub struct WsIoPacket {
31    pub data: Option<Vec<u8>>,
32    pub key: Option<String>,
33    pub r#type: WsIoPacketType,
34}
35
36impl WsIoPacket {
37    #[inline]
38    pub fn new(r#type: WsIoPacketType, key: Option<&str>, data: Option<Vec<u8>>) -> Self {
39        Self {
40            data,
41            key: key.map(str::to_owned),
42            r#type,
43        }
44    }
45
46    // Protected methods
47    #[inline]
48    pub(self) fn from_inner(inner: InnerPacket) -> Self {
49        Self {
50            data: inner.2,
51            key: inner.1,
52            r#type: inner.0,
53        }
54    }
55
56    #[inline]
57    pub(self) fn to_inner_ref(&self) -> InnerPacketRef<'_> {
58        InnerPacketRef(&self.r#type, &self.key, &self.data)
59    }
60
61    // Public methods
62    #[inline]
63    pub fn new_disconnect() -> Self {
64        Self::new(WsIoPacketType::Disconnect, None, None)
65    }
66
67    #[inline]
68    pub fn new_event(event: impl Into<String>, data: Option<Vec<u8>>) -> Self {
69        Self {
70            data,
71            key: Some(event.into()),
72            r#type: WsIoPacketType::Event,
73        }
74    }
75
76    #[inline]
77    pub fn new_init(data: Option<Vec<u8>>) -> Self {
78        Self::new(WsIoPacketType::Init, None, data)
79    }
80
81    #[inline]
82    pub fn new_ready() -> Self {
83        Self::new(WsIoPacketType::Ready, None, None)
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn test_new_packet_constructors() {
93        // Disconnect
94        let packet = WsIoPacket::new_disconnect();
95        assert!(matches!(packet.r#type, WsIoPacketType::Disconnect));
96        assert_eq!(packet.key, None);
97        assert_eq!(packet.data, None);
98
99        // Event without data
100        let packet = WsIoPacket::new_event("chat", None);
101        assert!(matches!(packet.r#type, WsIoPacketType::Event));
102        assert_eq!(packet.key.as_deref(), Some("chat"));
103        assert_eq!(packet.data, None);
104
105        // Event with data
106        let packet = WsIoPacket::new_event("chat", Some(vec![1, 2, 3]));
107        assert!(matches!(packet.r#type, WsIoPacketType::Event));
108        assert_eq!(packet.key.as_deref(), Some("chat"));
109        assert_eq!(packet.data.as_deref(), Some(&[1, 2, 3][..]));
110
111        // Init with data
112        let packet = WsIoPacket::new_init(Some(vec![4, 5, 6]));
113        assert!(matches!(packet.r#type, WsIoPacketType::Init));
114        assert_eq!(packet.key, None);
115        assert_eq!(packet.data.as_deref(), Some(&[4, 5, 6][..]));
116
117        // Ready
118        let packet = WsIoPacket::new_ready();
119        assert!(matches!(packet.r#type, WsIoPacketType::Ready));
120        assert_eq!(packet.key, None);
121        assert_eq!(packet.data, None);
122    }
123}