an efficient binary archive format
at main 106 lines 3.0 kB view raw
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}