Skip to main content

pkgar_core/
entry.rs

1//! The packed structs represent the on-disk format of pkgar
2use core::fmt::Display;
3
4use blake3::Hash;
5use bytemuck::{Pod, Zeroable};
6
7use crate::{Error, Mode};
8
9#[derive(Clone, Copy, Debug, Pod, Zeroable)]
10#[repr(packed, C)]
11pub struct Entry {
12    /// Blake3 sum of the file data
13    pub blake3: [u8; 32],
14    /// Offset of file data in the data portion
15    pub offset: u64,
16    /// Size in bytes of the file data in the data portion
17    pub size: u64,
18    /// Unix permissions (user, group, other with read, write, execute)
19    pub mode: u32,
20    /// NUL-terminated relative path from extract directory
21    pub path: [u8; 256],
22}
23
24impl Display for Entry {
25    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26        let (offset, size, mode) = (self.offset, self.size, self.mode);
27        write!(
28            f,
29            "path={:?} hash={} offset={} size={} mode={:o}",
30            alloc::string::String::from_utf8(self.path_bytes().into()).unwrap_or_default(),
31            self.blake3().to_hex(),
32            offset,
33            size,
34            mode
35        )
36    }
37}
38
39impl Entry {
40    pub fn blake3(&self) -> Hash {
41        Hash::from(self.blake3)
42    }
43
44    pub fn offset(&self) -> u64 {
45        self.offset
46    }
47
48    pub fn size(&self) -> u64 {
49        self.size
50    }
51
52    pub fn mode(&self) -> Result<Mode, Error> {
53        Mode::from_bits(self.mode).ok_or(Error::InvalidMode(self.mode))
54    }
55
56    /// Retrieve the path, ending at the first NUL
57    pub fn path_bytes(&self) -> &[u8] {
58        let mut i = 0;
59        while i < self.path.len() {
60            if self.path[i] == 0 {
61                break;
62            }
63            i += 1;
64        }
65        &self.path[..i]
66    }
67}