silkrust/net/message/
header.rs

1use std::fmt::{Display, Formatter};
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use crate::net::message::id::MessageId;
4
5pub const HEADER_SIZE: usize = 6;
6const HEADER_ENC_MASK: u16 = 0x8000;
7
8/// Message Header
9///
10/// The header of a network message which is always exactly 6 bytes
11#[derive(PartialEq, Eq, Clone, Debug)]
12pub struct Header {
13    /// message data size
14    ///
15    /// An MSB of 1 means that the message is encrypted.
16    size: u16,
17
18    /// message id
19    id: MessageId,
20
21    /// sequential check, ensures a message is not being replayed
22    pub(crate) sequence: u8,
23
24    /// cyclic redundancy check
25    pub(crate) checksum: u8,
26}
27
28impl Display for Header {
29    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
30        write!(
31            f,
32            "{} [{:X} {:X}]",
33            self.id,
34            self.sequence,
35            self.checksum,
36        )
37    }
38}
39
40impl Header {
41    pub fn new(id: MessageId, size: u16) -> Self {
42        Self {
43            id,
44            size,
45            checksum: 0,
46            sequence: 0
47        }
48    }
49
50    pub fn id(&self) -> &MessageId {
51        &self.id
52    }
53
54    pub fn message_size(&self) -> u16 {
55        self.data_size() + HEADER_SIZE as u16
56    }
57
58    pub fn data_size(&self) -> u16 {
59        self.size & !HEADER_ENC_MASK
60    }
61}
62
63impl From<Bytes> for Header {
64    fn from(mut value: Bytes) -> Self {
65        Self {
66            size: value.get_u16_le(),
67            id: MessageId::from(value.get_u16_le()),
68            sequence: value.get_u8(),
69            checksum: value.get_u8()
70        }
71    }
72}
73
74impl From<&[u8]> for Header {
75    fn from(buffer: &[u8]) -> Self {
76        Header {
77            size: u16::from_le_bytes(buffer[0..2].try_into().unwrap()),
78            id: MessageId::from(u16::from_le_bytes(buffer[2..4].try_into().unwrap())),
79            checksum: buffer[5],
80            sequence: buffer[4],
81        }
82    }
83}
84
85impl Into<Bytes> for Header {
86    fn into(self) -> Bytes {
87        let mut mem = BytesMut::new();
88        mem.put_u16_le(self.size);
89        mem.put_u16_le(self.id.into());
90        mem.put_u8(self.sequence);
91        mem.put_u8(self.checksum);
92
93        mem.freeze()
94    }
95}
96
97// TODO: write a test with a known byte array to check if conversions are correct.