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
//! Tag datablock specifying the section for tag structs.

use byteorder::{ReadBytesExt, LE};
use num_enum::TryFromPrimitive;
use std::io::BufRead;

#[derive(Default, Debug, TryFromPrimitive)]
#[repr(u16)]
/// Location where the data referenced in the tag block is found.
pub enum TagSectionType {
    #[default]
    /// Inside the tag header (metadata)
    Header,
    /// Inside the main parent tag.
    TagData,
    /// Inside resource child tag.
    ResourceData,
    /// Inside the "external" resource (for instance, bitmaps or havok data)
    ActualResource,
}

#[derive(Default, Debug)]
/// Tag data metadata block containing data on where the binary section is located.
pub struct TagDataBlock {
    /// The size of the data block entry in bytes.
    pub entry_size: u32,
    /// How many unused bytes come before the offset.
    pub padding: u16,
    /// Where the data block is stored.
    pub section_type: TagSectionType,
    /// Offset of where the data is stored from the start of the tag file.
    pub offset: u64,
}

impl TagDataBlock {
    /// Allocate new TagDataBlock and set it to default values.
    pub fn new() -> Self {
        Self::default()
    }
    /// Reads the tag data block from the given readers implementing "BufRead".
    /// # Arguments
    ///
    /// * `reader` - A mutable reference to a reader that implements `BufRead` from which to read the data.
    ///
    /// # Returns
    ///
    /// Returns `Ok(())` if the header is successfully read, or an `Err` if an I/O error occurs
    /// or if the header data is invalid.
    pub fn read<R: BufRead>(&mut self, reader: &mut R) -> std::io::Result<()> {
        self.entry_size = reader.read_u32::<LE>()?;
        self.padding = reader.read_u16::<LE>()?;
        self.section_type = TagSectionType::try_from(reader.read_u16::<LE>()?).unwrap();
        self.offset = reader.read_u64::<LE>()?;
        Ok(())
    }
}