spwnmsg_core/
packet.rs

1use crate::snowflake::Snowflake;
2use lazy_static::lazy_static;
3use parking_lot::{lock_api::Mutex, RawMutex};
4use std::{error::Error, fmt::Display, str::FromStr};
5
6pub type BasePacket = [u8; 1024];
7pub struct PacketMessageContent(pub [u8; 1004]);
8
9pub const PROTOCOL_VERSION: u8 = 1;
10
11lazy_static! {
12    pub static ref SNOWFLAKE: Mutex<RawMutex, Snowflake> = Mutex::new(Default::default());
13}
14
15/// Packet layout  
16///
17/// `1` - Protocol version
18///
19/// `2` - Opcode
20pub struct Packet {
21    inner: BasePacket,
22}
23
24impl Packet {
25    pub fn new(inner: BasePacket) -> Self {
26        Packet {
27            inner,
28        }
29    }
30
31    /// Get the packet's op.
32    pub fn op(&self) -> Opcode {
33        self.inner[1].into()
34    }
35
36    /// Get the packet's version.
37    pub fn version(&self) -> u8 {
38        self.inner[0]
39    }
40
41    /// Get a packet snowflake starting at a given index.
42    pub fn snowflake(&self, start: usize) -> [u8; 8] {
43        self.inner[start..start+8].try_into().unwrap()
44    }
45
46    /// Set the packet's op.
47    pub fn set_op(&mut self, op: Opcode) {
48        self.inner[1] = op as u8;
49    }
50
51    /// Set the packet's version.
52    pub fn set_version(&mut self, version: u8) {
53        self.inner[0] = version;
54    }
55
56    pub fn set_snowflake(&mut self, sf: [u8; 8], start_offset: usize) {    
57        self.inner[start_offset..start_offset + 8].copy_from_slice(&sf);
58    }
59
60    /// Set the packet's content depending on the opcode.
61    pub fn set_content(&mut self, content: PacketMessageContent) -> Result<(), PacketError> {
62        match self.inner[1].into() {
63            Opcode::Message => {
64                let n = &self.inner[..20];
65                self.inner = [n, &content.0].concat().try_into().unwrap();
66
67                Ok(())
68            }
69            t => Err(PacketError::InvaidContent { t }),
70        }
71    }
72}
73
74impl Into<[u8; 1024]> for Packet {
75    fn into(self) -> [u8; 1024] {
76        self.inner
77    }
78}
79
80impl From<u8> for Opcode {
81    fn from(op: u8) -> Self {
82        use self::Opcode::*;
83        match op {
84            0 => Ping,
85            1 => Ok,
86            2 => MemberJoin,
87            3 => MemberLeave,
88            4 => Message,
89            _ => panic!("Opcode `{}` out of range", op),
90        }
91    }
92}
93
94#[repr(u8)]
95#[derive(Debug, Clone, Copy)]
96pub enum Opcode {
97    /// Ping packet byte layout  
98    ///
99    /// `3-11` - User ID snowflake
100    ///
101    /// `12-20` - timestamp
102    Ping = 0,
103
104    /// Ok packet byte layout
105    ///
106    /// `3-1024` - `<empty>`
107    ///
108    /// It's okay :)
109    Ok,
110
111    /// Member Join packet byte layout
112    ///
113    /// `3-11` - User ID snowflake
114    ///
115    /// `12-20` - timestamp
116    MemberJoin,
117
118    /// Member Leave packet byte layout
119    ///
120    /// `3-11` - User ID snowflake
121    ///
122    /// `12-20` - timestamp
123    MemberLeave,
124
125    /// Member Join packet byte layout
126    ///
127    /// `3-11` - User ID snowflake (8 bytes)
128    ///
129    /// `12-20` - Message ID snowflake `(8 bytes)`
130    ///
131    /// `21-1024` - Message content `(1003 bytes)`
132    Message,
133}
134
135#[derive(Debug)]
136pub enum PacketError {
137    /// Tried to put content in a packet that does not support it.
138    ///
139    /// For example, called `Packet::content(content)` on a `Opcode::Ping` packet
140    InvaidContent { t: Opcode },
141
142    /// Packet content is too long
143    ///
144    /// For example, called `Packet::content(content)` on a String with a length greater than 1003
145    BadContent { t: Opcode },
146}
147
148impl Display for PacketError {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        use self::PacketError::*;
151        match self {
152            InvaidContent { t } => write!(
153                f,
154                "Tried to put content into a packet of type {:?}. Supported types are:
155                - Message",
156                t
157            ),
158            BadContent { t } => write!(f, "Malformed packet of type {:?}.", t),
159        }
160    }
161}
162
163impl Error for PacketError {}
164
165impl FromStr for PacketMessageContent {
166    type Err = PacketError;
167
168    fn from_str(s: &str) -> Result<Self, Self::Err> {
169        // let n = &self.inner[..20];
170        // let out: BasePacket = [n, &content.0].concat().try_into().unwrap();
171
172        let b = s.as_bytes();
173        if b.len() > 1004 {
174            return Err(PacketError::BadContent { t: Opcode::Message });
175        }
176        let re = [0u8].repeat(1004 - b.len());
177        let uuw = re.as_slice();
178
179        let uw: [u8; 1004] = [b, uuw].concat().try_into().unwrap();
180
181        Ok(PacketMessageContent(uw))
182    }
183}
184
185#[cfg(test)]
186pub mod test {
187    use std::time::Duration;
188    
189    use super::*;
190
191    #[test]
192    fn packet() {
193        let mut packet = Packet::new([0; 1024]);
194
195        packet.set_op(Opcode::Message);
196        packet.set_content("uwu".parse().unwrap()).unwrap();
197        packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 3);
198        std::thread::sleep(Duration::from_secs(1));
199
200        packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 11);
201        std::thread::sleep(Duration::from_secs(1));
202
203        packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 30);
204        std::thread::sleep(Duration::from_secs(1));
205
206        assert_eq!(packet.inner[0], 0);
207        assert_eq!(packet.inner[1], 4);
208        assert_eq!(&packet.inner[20..23], "uwu".as_bytes());
209        
210        println!("{:?}", u64::from_le_bytes(packet.snowflake(3)));
211        println!("{:?}", u64::from_le_bytes(packet.snowflake(11)));
212        println!("{:?}", u64::from_le_bytes(packet.snowflake(30)));
213    }
214}