raknet-rust 0.2.0

Asynchronous, high-performance RakNet transport library for Rust.
Documentation
use bytes::{Buf, BufMut};

use crate::error::{DecodeError, EncodeError};

use super::codec::RaknetCodec;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Reliability {
    Unreliable = 0,
    UnreliableSequenced = 1,
    Reliable = 2,
    ReliableOrdered = 3,
    ReliableSequenced = 4,
    UnreliableWithAckReceipt = 5,
    ReliableWithAckReceipt = 6,
    ReliableOrderedWithAckReceipt = 7,
}

#[derive(Debug, Clone, Copy)]
struct ReliabilityProps {
    reliable: bool,
    ordered: bool,
    sequenced: bool,
    with_ack_receipt: bool,
}

const RELIABILITY_PROPS: [ReliabilityProps; 8] = [
    ReliabilityProps {
        reliable: false,
        ordered: false,
        sequenced: false,
        with_ack_receipt: false,
    },
    ReliabilityProps {
        reliable: false,
        ordered: false,
        sequenced: true,
        with_ack_receipt: false,
    },
    ReliabilityProps {
        reliable: true,
        ordered: false,
        sequenced: false,
        with_ack_receipt: false,
    },
    ReliabilityProps {
        reliable: true,
        ordered: true,
        sequenced: false,
        with_ack_receipt: false,
    },
    ReliabilityProps {
        reliable: true,
        ordered: false,
        sequenced: true,
        with_ack_receipt: false,
    },
    ReliabilityProps {
        reliable: false,
        ordered: false,
        sequenced: false,
        with_ack_receipt: true,
    },
    ReliabilityProps {
        reliable: true,
        ordered: false,
        sequenced: false,
        with_ack_receipt: true,
    },
    ReliabilityProps {
        reliable: true,
        ordered: true,
        sequenced: false,
        with_ack_receipt: true,
    },
];

impl Reliability {
    #[inline]
    fn props(self) -> &'static ReliabilityProps {
        &RELIABILITY_PROPS[self as usize]
    }

    #[inline]
    pub fn is_reliable(self) -> bool {
        self.props().reliable
    }

    #[inline]
    pub fn is_ordered(self) -> bool {
        self.props().ordered
    }

    #[inline]
    pub fn is_sequenced(self) -> bool {
        self.props().sequenced
    }

    #[inline]
    pub fn is_with_ack_receipt(self) -> bool {
        self.props().with_ack_receipt
    }
}

impl TryFrom<u8> for Reliability {
    type Error = DecodeError;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0 => Ok(Self::Unreliable),
            1 => Ok(Self::UnreliableSequenced),
            2 => Ok(Self::Reliable),
            3 => Ok(Self::ReliableOrdered),
            4 => Ok(Self::ReliableSequenced),
            5 => Ok(Self::UnreliableWithAckReceipt),
            6 => Ok(Self::ReliableWithAckReceipt),
            7 => Ok(Self::ReliableOrderedWithAckReceipt),
            _ => Err(DecodeError::UnknownReliability(value)),
        }
    }
}

impl RaknetCodec for Reliability {
    fn encode_raknet(&self, dst: &mut impl BufMut) -> Result<(), EncodeError> {
        dst.put_u8(*self as u8);
        Ok(())
    }

    fn decode_raknet(src: &mut impl Buf) -> Result<Self, DecodeError> {
        if !src.has_remaining() {
            return Err(DecodeError::UnexpectedEof);
        }
        Self::try_from(src.get_u8())
    }
}