literustlib 0.4.0

Rust parser for LiteNetLib packets
Documentation
#[derive(Debug, Clone, Copy)]
pub struct Header {
    pub property: super::Property,
    pub sequence: Option<u16>,
    pub fragment: Option<super::Fragment>,
}

impl Header {
    pub fn with_prop(property: super::Property) -> Self {
        Self {
            property,
            sequence: None,
            fragment: None,
        }
    }

    pub fn len(&self) -> usize {
        if self.fragment.is_some() {
            9
        } else if self.is_sequenced() {
            3
        } else {
            1
        }
    }

    pub fn is_sequenced(&self) -> bool {
        self.property.is_sequenced()
    }

    pub fn is_client_data(&self) -> bool {
        self.property.is_client_data()
    }

    pub(crate) fn parse(slice: &[u8]) -> std::io::Result<Self> {
        if !slice.is_empty() {
            let flags = slice[0];
            let property = super::Property::try_from(flags & 0x7F)
                        .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
            let sequence = if property.is_sequenced() {
                if slice.len() >= 3 {
                    Some(u16::from_le_bytes([slice[1], slice[2]]))
                } else {
                    return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Data to parse is not long enough for sequence number"));
                }
            } else {
                None
            };
            let fragment = if (flags & 0x80) != 0 {
                Some(super::Fragment::parse(slice)?)
            } else {
                None
            };
            Ok(Self {
                property,
                sequence,
                fragment,
            })
        } else {
            Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Data to parse is empty"))
        }
    }

    pub(crate) fn dump<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
        let mut total_bytes = 1;
        let flags = (self.property as u8) | if self.fragment.is_some() { 0x80 } else { 0x00 };
        writer.write_all(&[flags])?;
        if let Some(seq) = self.sequence {
            writer.write_all(&seq.to_le_bytes())?;
            total_bytes += 2;
        } else if self.fragment.is_some() {
            writer.write_all(&0u16.to_le_bytes())?;
            total_bytes += 2;
        }
        if let Some(frag) = self.fragment {
            total_bytes += frag.dump(writer)?;
        }
        Ok(total_bytes)
    }
}