zero_mysql/protocol/
packet.rs

1use crate::error::{Error, Result, eyre};
2use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
3
4#[repr(C, packed)]
5#[derive(Debug, Clone, Copy, FromBytes, KnownLayout, Immutable, IntoBytes)]
6pub struct PacketHeader {
7    pub length: [u8; 3],
8    pub sequence_id: u8,
9}
10
11impl PacketHeader {
12    pub fn encode(length: usize, sequence_id: u8) -> Self {
13        let len = u32::to_le_bytes(length as u32);
14        Self {
15            length: [len[0], len[1], len[2]],
16            sequence_id,
17        }
18    }
19
20    pub fn encode_in_place(&mut self, length: usize, sequence_id: u8) {
21        let len = u32::to_le_bytes(length as u32);
22        self.length = [len[0], len[1], len[2]];
23        self.sequence_id = sequence_id;
24    }
25
26    pub fn length(&self) -> usize {
27        u32::from_le_bytes([self.length[0], self.length[1], self.length[2], 0]) as usize
28    }
29
30    pub fn from_bytes(data: &[u8]) -> Result<&Self> {
31        if data.len() < 4 {
32            return Err(Error::LibraryBug(eyre!(
33                "packet header too short: {} < 4",
34                data.len()
35            )));
36        }
37        Ok(Self::ref_from_bytes(&data[..4])?)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn packet_header_has_alignment_of_1() {
47        assert_eq!(std::mem::align_of::<PacketHeader>(), 1);
48    }
49}