Skip to main content

gvdb/read/
pointer.rs

1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
2
3/// A pointer internal to the GVDB file.
4///
5/// GVDB files use pointer structs with global start and end locations. Pointers
6/// are *always* little-endian, independant of the file endianess.
7///
8/// It is possible to retrieve the bytes stored at this pointer by using
9/// [`File::dereference()`](crate::read::File::dereference).
10#[repr(C)]
11#[derive(Copy, Clone, PartialEq, Eq, Immutable, KnownLayout, FromBytes, IntoBytes)]
12pub struct Pointer {
13    start: u32,
14    end: u32,
15}
16
17impl Pointer {
18    #[allow(unused)]
19    pub(crate) const NULL: Self = Self { start: 0, end: 0 };
20
21    /// Create a new GVDB pointer. Pointers are always internally stored as little endian,
22    /// so we convert the values here.
23    pub fn new(start: usize, end: usize) -> Self {
24        Self {
25            start: (start as u32).to_le(),
26            end: (end as u32).to_le(),
27        }
28    }
29
30    /// Returns the start address of the pointer and convert them to target endianess.
31    pub fn start(&self) -> u32 {
32        u32::from_le(self.start)
33    }
34
35    /// Returns the end address of the pointer and convert them to target endianess.
36    pub fn end(&self) -> u32 {
37        u32::from_le(self.end)
38    }
39
40    /// Returns the number of bytes referenced by the pointer.
41    pub fn size(&self) -> usize {
42        self.end().saturating_sub(self.start()) as usize
43    }
44}
45
46impl std::fmt::Debug for Pointer {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        f.debug_struct("Pointer")
49            .field("start", &self.start())
50            .field("end", &self.end())
51            .finish()
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use crate::read::Pointer;
58
59    #[test]
60    fn derives() {
61        let pointer = Pointer::new(0, 2);
62        let pointer2 = pointer;
63        println!("{pointer2:?}");
64    }
65
66    #[test]
67    fn no_panic_invalid_size() {
68        let invalid_ptr = Pointer::new(100, 0);
69        let size = invalid_ptr.size();
70        assert_eq!(size, 0);
71    }
72}