1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use byteorder::{ByteOrder, LittleEndian};

/// ROFL file's header information
#[derive(Debug)]
pub struct BinHeader {
    /// The file's signature
    signature: Vec<u8>, // Fixed-size: 256 bits (or 0 if ignored)
    /// The size of the header (constant in all known examples)
    header_length: u16,
    /// Total file length
    file_length: u32,
    /// Offset in bytes from the start of the file of the metadata section
    metadata_offset: u32,
    /// Length in bytes of the metadata section
    metadata_length: u32,
    /// Offset in bytes from the start of the file of the payload header section
    payload_header_offset: u32,
    /// Length in bytes of the payload header section
    payload_header_length: u32,
    /// Offset in bytes from the start of the file of the payload section
    payload_offset: u32,
}

impl std::fmt::Display for BinHeader {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            concat!(
                "Header size: {0}\n",
                "File size: {1}\n",
                "Metadata offset: {2}\n",
                "Metadata length: {3}\n",
                "Payload Header offset: {4}\n",
                "Payload Header Length: {5}\n",
                "Payload offset: {6}",
            ),
            self.header_length,
            self.file_length,
            self.metadata_offset,
            self.metadata_length,
            self.payload_header_offset,
            self.payload_header_length,
            self.payload_offset,
            )
    }
}

impl BinHeader {
    /// Get the file's signature
    pub fn signature(&self) -> &Vec<u8> {
        &self.signature
    }
    /// Get the file's header length
    pub fn header_len(&self) -> usize {
        self.header_length as usize
    }
    /// Get the file's length in bytes as per its binary data
    /// 
    /// This may not match the actual file's length if an error occured
    pub fn file_len(&self) -> usize {
        self.file_length as usize
    }
    /// Length of the file's metadata section
    /// 
    /// This should not be required in normal use
    pub fn metadata_len(&self) -> usize {
        self.metadata_length as usize
    }
    /// Offset of the file's metadata section
    /// 
    /// This should not be required in normal use
    pub fn metadata_offset(&self) -> usize {
        self.metadata_offset as usize
    }
    /// Length of the file's payload header section
    /// 
    /// This should not be required in normal use
    pub fn payload_header_len(&self) -> usize {
        self.payload_header_length as usize
    }
    /// Offset of the file's payload header section
    /// 
    /// This should not be required in normal use
    pub fn payload_header_offset(&self) -> usize {
        self.payload_header_offset as usize
    }
    /// Offset of the file's payload section
    /// 
    /// This should not be required in normal use
    pub fn payload_offset(&self) -> usize {
        self.payload_offset as usize
    }
    
    /// Create a new header from a manually-loaded file start section
    /// 
    /// Use from_raw_source instead
    #[warn(deprecated)]
    fn from_raw_section(data: &[u8]) -> BinHeader {
        BinHeader {
            signature: Vec::from(&data[6..262]),
            header_length: LittleEndian::read_u16(&data[262..]),
            file_length: LittleEndian::read_u32(&data[264..]),
            metadata_offset: LittleEndian::read_u32(&data[268..]),
            metadata_length: LittleEndian::read_u32(&data[272..]),
            payload_header_offset: LittleEndian::read_u32(&data[276..]),
            payload_header_length: LittleEndian::read_u32(&data[280..]),
            payload_offset: LittleEndian::read_u32(&data[284..]),
        }
    }
    /// Create a new header from a manually-loaded file start section
    /// 
    /// This will be replaced by a from_raw function in the future
    pub fn from_raw_source(data: &[u8]) -> BinHeader {
        BinHeader::from_raw_section(&data[0..])
    }
}