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;
use super::constants::{FRAME_FLAG_NEEDS_BAS, FRAME_FLAG_SPLIT};
use super::reliability::Reliability;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FrameHeader {
    pub reliability: Reliability,
    pub is_split: bool,
    pub needs_bas: bool,
}

impl FrameHeader {
    pub fn new(reliability: Reliability, is_split: bool, needs_bas: bool) -> Self {
        Self {
            reliability,
            is_split,
            needs_bas,
        }
    }

    pub fn from_byte(raw: u8) -> Result<Self, DecodeError> {
        let reliability = Reliability::try_from(raw >> 5)?;
        let is_split = (raw & FRAME_FLAG_SPLIT) != 0;
        let needs_bas = (raw & FRAME_FLAG_NEEDS_BAS) != 0;
        Ok(Self {
            reliability,
            is_split,
            needs_bas,
        })
    }

    pub fn to_byte(self) -> u8 {
        let mut raw = (self.reliability as u8) << 5;
        if self.is_split {
            raw |= FRAME_FLAG_SPLIT;
        }
        if self.needs_bas {
            raw |= FRAME_FLAG_NEEDS_BAS;
        }
        raw
    }
}

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

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