Skip to main content

lxdb_format/
section_header.rs

1use crate::Section;
2
3/// Number of bytes occupied by an encoded section header.
4pub const SECTION_HEADER_SIZE: usize = 12;
5
6/// Header preceding every binary LXDB section.
7///
8/// Binary layout:
9///
10/// - section type: 1 byte
11/// - flags: 1 byte
12/// - reserved: 2 bytes
13/// - payload length: 8 bytes
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct SectionHeader {
16    section: Section,
17    flags: u8,
18    length: u64,
19}
20
21impl SectionHeader {
22    pub const SIZE: usize = SECTION_HEADER_SIZE;
23
24    pub const fn new(section: Section, flags: u8, length: u64) -> Self {
25        Self { section, flags, length }
26    }
27
28    pub const fn section(self) -> Section {
29        self.section
30    }
31
32    pub const fn flags(self) -> u8 {
33        self.flags
34    }
35
36    pub const fn length(self) -> u64 {
37        self.length
38    }
39
40    pub fn encode(self) -> [u8; SECTION_HEADER_SIZE] {
41        let mut bytes = [0_u8; SECTION_HEADER_SIZE];
42
43        bytes[0] = self.section.as_u8();
44        bytes[1] = self.flags;
45
46        // bytes[2..4] are reserved and remain zero.
47
48        bytes[4..12].copy_from_slice(&self.length.to_le_bytes());
49
50        bytes
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::{SECTION_HEADER_SIZE, SectionHeader};
57    use crate::{Section, flags};
58
59    #[test]
60    fn encodes_section_header() {
61        let header =
62            SectionHeader::new(Section::Tokens, flags::COMPRESSED | flags::OPTIONAL, 1_024);
63
64        let bytes = header.encode();
65
66        assert_eq!(bytes.len(), SECTION_HEADER_SIZE);
67        assert_eq!(bytes[0], Section::Tokens.as_u8());
68        assert_eq!(bytes[1], flags::COMPRESSED | flags::OPTIONAL);
69        assert_eq!(&bytes[2..4], &[0, 0]);
70
71        assert_eq!(
72            u64::from_le_bytes([
73                bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11],
74            ]),
75            1_024,
76        );
77    }
78
79    #[test]
80    fn encodes_section_without_flags() {
81        let header = SectionHeader::new(Section::Relations, flags::NONE, 500);
82
83        let bytes = header.encode();
84
85        assert_eq!(bytes[1], 0);
86    }
87}