use crate::snowflake::Snowflake;
use lazy_static::lazy_static;
use parking_lot::{lock_api::Mutex, RawMutex};
use std::{error::Error, fmt::Display, str::FromStr};
pub type BasePacket = [u8; 1024];
pub struct PacketMessageContent(pub [u8; 1004]);
pub const PROTOCOL_VERSION: u8 = 1;
lazy_static! {
pub static ref SNOWFLAKE: Mutex<RawMutex, Snowflake> = Mutex::new(Default::default());
}
pub struct Packet {
inner: BasePacket,
}
impl Packet {
pub fn new(inner: BasePacket) -> Self {
Packet {
inner,
}
}
pub fn op(&self) -> Opcode {
self.inner[1].into()
}
pub fn version(&self) -> u8 {
self.inner[0]
}
pub fn snowflake(&self, start: usize) -> [u8; 8] {
self.inner[start..start+8].try_into().unwrap()
}
pub fn set_op(&mut self, op: Opcode) {
self.inner[1] = op as u8;
}
pub fn set_version(&mut self, version: u8) {
self.inner[0] = version;
}
pub fn set_snowflake(&mut self, sf: [u8; 8], start_offset: usize) {
self.inner[start_offset..start_offset + 8].copy_from_slice(&sf);
}
pub fn set_content(&mut self, content: PacketMessageContent) -> Result<(), PacketError> {
match self.inner[1].into() {
Opcode::Message => {
let n = &self.inner[..20];
self.inner = [n, &content.0].concat().try_into().unwrap();
Ok(())
}
t => Err(PacketError::InvaidContent { t }),
}
}
}
impl Into<[u8; 1024]> for Packet {
fn into(self) -> [u8; 1024] {
self.inner
}
}
impl From<u8> for Opcode {
fn from(op: u8) -> Self {
use self::Opcode::*;
match op {
0 => Ping,
1 => Ok,
2 => MemberJoin,
3 => MemberLeave,
4 => Message,
_ => panic!("Opcode `{}` out of range", op),
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum Opcode {
Ping = 0,
Ok,
MemberJoin,
MemberLeave,
Message,
}
#[derive(Debug)]
pub enum PacketError {
InvaidContent { t: Opcode },
BadContent { t: Opcode },
}
impl Display for PacketError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use self::PacketError::*;
match self {
InvaidContent { t } => write!(
f,
"Tried to put content into a packet of type {:?}. Supported types are:
- Message",
t
),
BadContent { t } => write!(f, "Malformed packet of type {:?}.", t),
}
}
}
impl Error for PacketError {}
impl FromStr for PacketMessageContent {
type Err = PacketError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let b = s.as_bytes();
if b.len() > 1004 {
return Err(PacketError::BadContent { t: Opcode::Message });
}
let re = [0u8].repeat(1004 - b.len());
let uuw = re.as_slice();
let uw: [u8; 1004] = [b, uuw].concat().try_into().unwrap();
Ok(PacketMessageContent(uw))
}
}
#[cfg(test)]
pub mod test {
use std::time::Duration;
use super::*;
#[test]
fn packet() {
let mut packet = Packet::new([0; 1024]);
packet.set_op(Opcode::Message);
packet.set_content("uwu".parse().unwrap()).unwrap();
packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 3);
std::thread::sleep(Duration::from_secs(1));
packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 11);
std::thread::sleep(Duration::from_secs(1));
packet.set_snowflake(SNOWFLAKE.lock().generate_u8_u64(), 30);
std::thread::sleep(Duration::from_secs(1));
assert_eq!(packet.inner[0], 0);
assert_eq!(packet.inner[1], 4);
assert_eq!(&packet.inner[20..23], "uwu".as_bytes());
println!("{:?}", u64::from_le_bytes(packet.snowflake(3)));
println!("{:?}", u64::from_le_bytes(packet.snowflake(11)));
println!("{:?}", u64::from_le_bytes(packet.snowflake(30)));
}
}