use enet_sys::{
enet_packet_create, enet_packet_destroy, ENetPacket, _ENetPacketFlag_ENET_PACKET_FLAG_RELIABLE,
_ENetPacketFlag_ENET_PACKET_FLAG_UNSEQUENCED,
};
use crate::Error;
#[derive(Debug)]
pub struct Packet {
inner: *mut ENetPacket,
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum PacketMode {
UnreliableSequenced,
UnreliableUnsequenced,
ReliableSequenced,
}
impl PacketMode {
pub fn is_reliable(&self) -> bool {
match self {
PacketMode::UnreliableSequenced => false,
PacketMode::UnreliableUnsequenced => false,
PacketMode::ReliableSequenced => true,
}
}
pub fn is_sequenced(&self) -> bool {
match self {
PacketMode::UnreliableSequenced => true,
PacketMode::UnreliableUnsequenced => false,
PacketMode::ReliableSequenced => true,
}
}
fn to_sys_flags(self) -> u32 {
match self {
PacketMode::UnreliableSequenced => 0,
PacketMode::UnreliableUnsequenced => {
_ENetPacketFlag_ENET_PACKET_FLAG_UNSEQUENCED as u32
}
PacketMode::ReliableSequenced => _ENetPacketFlag_ENET_PACKET_FLAG_RELIABLE as u32,
}
}
}
impl Packet {
pub fn new(data: &[u8], mode: PacketMode) -> Result<Packet, Error> {
let data_len: enet_sys::size_t = data
.len()
.try_into()
.expect("packet data too long for ENet (`size_t`)");
let res =
unsafe { enet_packet_create(data.as_ptr() as *const _, data_len, mode.to_sys_flags()) };
if res.is_null() {
return Err(Error(0));
}
Ok(Packet::from_sys_packet(res))
}
pub(crate) fn from_sys_packet(inner: *mut ENetPacket) -> Packet {
Packet { inner }
}
pub(crate) fn into_inner(self) -> *mut ENetPacket {
let res = self.inner;
std::mem::forget(self);
res
}
pub fn data(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(
(*self.inner).data,
(*self.inner)
.dataLength
.try_into()
.expect("packet data too long for an `usize`"),
)
}
}
}
impl Drop for Packet {
fn drop(&mut self) {
unsafe {
enet_packet_destroy(self.inner);
}
}
}