use std;
use enum_primitive_derive::Primitive;
use num_traits;
use ll;
use crate::{host, Address, Packet};
#[expect(clippy::unnecessary_cast)] pub const PACKET_LOSS_SCALE : u32 = ll::ENET_PEER_PACKET_LOSS_SCALE as u32;
#[derive(Clone, Debug, PartialEq)]
pub struct Peer {
raw : *mut ll::ENetPeer,
hostdrop : std::rc::Rc <host::HostDrop>
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Primitive)]
pub enum State {
Disconnected = ll::_ENetPeerState_ENET_PEER_STATE_DISCONNECTED as isize,
Connecting = ll::_ENetPeerState_ENET_PEER_STATE_CONNECTING as isize,
AcknowledgingConnect = ll::_ENetPeerState_ENET_PEER_STATE_ACKNOWLEDGING_CONNECT
as isize,
ConnectionPending = ll::_ENetPeerState_ENET_PEER_STATE_CONNECTION_PENDING as isize,
ConnectionSucceeded = ll::_ENetPeerState_ENET_PEER_STATE_CONNECTION_SUCCEEDED
as isize,
Connected = ll::_ENetPeerState_ENET_PEER_STATE_CONNECTED as isize,
DisconnectLater = ll::_ENetPeerState_ENET_PEER_STATE_DISCONNECT_LATER as isize,
Disconnecting = ll::_ENetPeerState_ENET_PEER_STATE_DISCONNECTING as isize,
AcknowledgingDisconnect = ll::_ENetPeerState_ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT
as isize,
Zombie = ll::_ENetPeerState_ENET_PEER_STATE_ZOMBIE as isize
}
#[derive(Debug)]
pub enum ConnectError {
NoPeersAvailable,
Failure
}
#[derive(Debug)]
pub enum SendError {
PeerNotConnected (State),
PeerNoChannelID (u8),
PacketCreateZeroLength,
PacketCreateMallocFailure,
PacketExceedsMaximumSize (usize),
Failure
}
impl Peer {
pub(crate) const unsafe fn from_raw (
peer : *mut ll::ENetPeer,
hostdrop : std::rc::Rc <host::HostDrop>
) -> Self {
Peer {
raw: peer,
hostdrop
}
}
#[inline]
pub const unsafe fn raw (&self) -> *mut ll::ENetPeer {
self.raw
}
#[inline]
pub fn incoming_peer_id (&self) -> u16 {
unsafe { (*self.raw).incomingPeerID }
}
#[inline]
pub fn state (&self) -> State {
use num_traits::FromPrimitive;
#[expect(clippy::unnecessary_cast)] unsafe { State::from_u32 ((*self.raw).state as u32).unwrap() }
}
#[inline]
pub fn address (&self) -> Address {
unsafe { Address::from_ll ((*self.raw).address) }
}
#[inline]
pub fn packet_loss_epoch (&self) -> u32 {
unsafe { (*self.raw).packetLossEpoch }
}
#[inline]
pub fn packets_sent (&self) -> u32 {
unsafe { (*self.raw).packetsSent }
}
#[inline]
pub fn packets_lost (&self) -> u32 {
unsafe { (*self.raw).packetsLost }
}
#[inline]
pub fn packet_loss (&self) -> u32 {
unsafe { (*self.raw).packetLoss }
}
#[inline]
pub fn round_trip_time (&self) -> u32 {
unsafe { (*self.raw).roundTripTime }
}
#[inline]
pub fn round_trip_time_variance (&self) -> u32 {
unsafe { (*self.raw).roundTripTimeVariance }
}
#[inline]
pub fn ping (&mut self) {
unsafe {
ll::enet_peer_ping (self.raw())
}
}
#[inline]
pub fn get_ping_interval (&mut self) -> u32 {
unsafe {
(*self.raw).pingInterval
}
}
#[inline]
pub fn ping_interval (&mut self, ping_interval : u32) {
unsafe {
ll::enet_peer_ping_interval (self.raw(), ping_interval)
}
}
#[inline]
pub fn timeout (&mut self,
timeout_limit : u32, timeout_minimum : u32, timeout_maximum : u32
) {
unsafe {
ll::enet_peer_timeout (self.raw(),
timeout_limit, timeout_minimum, timeout_maximum)
}
}
#[inline]
pub fn get_timeout (&mut self) -> (u32, u32, u32) {
unsafe {
( (*self.raw).timeoutLimit,
(*self.raw).timeoutMinimum,
(*self.raw).timeoutMaximum )
}
}
pub fn send (&mut self, channel_id : u8, packet : Packet) -> Result <(), SendError> {
use num_traits::FromPrimitive;
unsafe {
if (*self.raw).state != ll::_ENetPeerState_ENET_PEER_STATE_CONNECTED {
#[expect(clippy::unnecessary_cast)] return Err (SendError::PeerNotConnected(
State::from_u32 ((*self.raw).state as u32).unwrap()
))
}
if (*self.raw).channelCount as u8 <= channel_id {
return Err (SendError::PeerNoChannelID (channel_id))
}
let raw = match packet {
Packet::Allocate { bytes, flags } => {
if (*self.hostdrop.raw()).maximumPacketSize < bytes.len() {
return Err (SendError::PacketExceedsMaximumSize (bytes.len()))
}
if bytes.is_empty() {
return Err (SendError::PacketCreateZeroLength)
}
ll::enet_packet_create (
bytes.as_ptr() as *const std::os::raw::c_void, bytes.len(), flags.bits())
}
Packet::NoAllocate { bytes, flags } => {
if (*(*self.raw).host).maximumPacketSize < bytes.len() {
return Err (SendError::PacketExceedsMaximumSize(bytes.len()))
}
if bytes.is_empty() {
return Err (SendError::PacketCreateZeroLength)
}
#[expect(clippy::unnecessary_cast)] ll::enet_packet_create (
bytes.as_ptr() as *const std::os::raw::c_void,
bytes.len(),
flags.bits() | ll::_ENetPacketFlag_ENET_PACKET_FLAG_NO_ALLOCATE as u32)
}
};
if raw.is_null() {
return Err (SendError::PacketCreateMallocFailure)
}
if ll::enet_peer_send (self.raw(), channel_id, raw) < 0 {
return Err (SendError::Failure)
}
Ok(())
}
}
#[inline]
pub fn disconnect (&self) {
unsafe {
ll::enet_peer_disconnect (self.raw(), 0)
}
}
#[inline]
pub fn disconnect_now (&self) {
unsafe {
ll::enet_peer_disconnect_now (self.raw(), 0)
}
}
#[inline]
pub fn disconnect_later (&self) {
unsafe {
ll::enet_peer_disconnect_later (self.raw(), 0)
}
}
#[inline]
pub fn reset (&self) {
unsafe {
ll::enet_peer_reset (self.raw())
}
}
}