Skip to main content

bindle_file/
entry.rs

1use zerocopy::{FromBytes, Immutable, IntoBytes, Unaligned};
2
3use crate::compress::Compress;
4
5/// Metadata for an entry in the archive.
6///
7/// Contains information about stored files including offset, size, compression, and CRC32 checksum.
8/// Retrieved via the archive's `index()` method.
9#[repr(C, packed)]
10#[derive(FromBytes, Unaligned, IntoBytes, Immutable, Clone, Copy, Debug, Default)]
11pub struct Entry {
12    offset: u64,
13    compressed_size: u64,
14    uncompressed_size: u64,
15    crc32: u32,
16    name_len: u16,
17    pub compression_type: u8,
18    pub _reserved: u8,
19}
20
21// The binary format uses little-endian byte order for all multi-byte integers.
22// These methods handle endianness conversion transparently:
23// - On little-endian systems (x86, ARM): zero overhead, direct access
24// - On big-endian systems: bytes are swapped to/from little-endian
25
26impl Entry {
27    /// Returns the byte offset where this entry's data starts in the archive.
28    pub fn offset(&self) -> u64 {
29        u64::from_le(self.offset)
30    }
31
32    pub(crate) fn set_offset(&mut self, value: u64) {
33        self.offset = value.to_le();
34    }
35
36    /// Returns the compressed size of this entry in bytes.
37    pub fn compressed_size(&self) -> u64 {
38        u64::from_le(self.compressed_size)
39    }
40
41    pub(crate) fn set_compressed_size(&mut self, value: u64) {
42        self.compressed_size = value.to_le();
43    }
44
45    /// Returns the uncompressed size of this entry in bytes.
46    pub fn uncompressed_size(&self) -> u64 {
47        u64::from_le(self.uncompressed_size)
48    }
49
50    pub(crate) fn set_uncompressed_size(&mut self, value: u64) {
51        self.uncompressed_size = value.to_le();
52    }
53
54    /// Returns the CRC32 checksum of the uncompressed data.
55    pub fn crc32(&self) -> u32 {
56        u32::from_le(self.crc32)
57    }
58
59    pub(crate) fn set_crc32(&mut self, value: u32) {
60        self.crc32 = value.to_le();
61    }
62
63    /// Returns the length of the entry name in bytes.
64    pub fn name_len(&self) -> usize {
65        u16::from_le(self.name_len) as usize
66    }
67
68    pub(crate) fn set_name_len(&mut self, value: u16) {
69        self.name_len = value.to_le();
70    }
71
72    /// Returns the compression type for this entry.
73    pub fn compression_type(&self) -> Compress {
74        Compress::from_u8(self.compression_type)
75    }
76}
77
78#[repr(C, packed)]
79#[derive(FromBytes, Unaligned, IntoBytes, Immutable, Debug)]
80pub(crate) struct Footer {
81    pub index_offset: u64,
82    pub entry_count: u32,
83    pub magic: u32,
84}
85
86impl Footer {
87    pub fn new(index_offset: u64, entry_count: u32, magic: u32) -> Self {
88        Self {
89            index_offset: index_offset.to_le(),
90            entry_count: entry_count.to_le(),
91            magic: magic.to_le(),
92        }
93    }
94
95    pub fn index_offset(&self) -> u64 {
96        u64::from_le(self.index_offset)
97    }
98
99    pub fn entry_count(&self) -> u32 {
100        u32::from_le(self.entry_count)
101    }
102
103    pub fn magic(&self) -> u32 {
104        u32::from_le(self.magic)
105    }
106}