wgtk/space/section/
bwtb.rs

1use std::fmt::{self, Formatter};
2use std::collections::HashMap;
3use std::io::Read;
4
5use super::{SectionId};
6use crate::util::io::WgReadExt;
7
8
9/// Header section, defining all offsets for real sections. This section is a fake section
10/// and doesn't implement the [Section](super::Section) trait.
11pub struct BWTB {
12    pub root: SectionMeta,
13    pub sections: Vec<SectionMeta>,
14    sections_from_id: HashMap<SectionId, usize>
15}
16
17impl BWTB {
18
19    pub fn decode<R: Read>(read: &mut R) -> std::io::Result<BWTB> {
20
21        let root = SectionMeta::decode(read)?;
22        assert_eq!(&root.id, b"BWTB");
23
24        let mut sections = Vec::with_capacity(root.sections_count);
25        for _ in 0..root.sections_count {
26            sections.push(SectionMeta::decode(read)?);
27        }
28
29        Ok(BWTB {
30            root,
31            sections_from_id: sections.iter()
32                .enumerate()
33                .map(|(i, r)| (r.id.clone(), i))
34                .collect(),
35            sections,
36        })
37
38    }
39
40    /// Get section metadata from its identifier.
41    pub fn get_section_meta(&self, id: &SectionId) -> Option<&SectionMeta> {
42        self.sections.get(*self.sections_from_id.get(id)?)
43    }
44
45}
46
47
48/// Metadata for section, its offset and length. Sections count is an internal value only
49/// used by the fake [BWTB] header section.
50pub struct SectionMeta {
51    pub id: SectionId,
52    pub off: usize,
53    pub len: usize,
54    pub sections_count: usize
55}
56
57impl SectionMeta {
58
59    fn decode<R: Read>(read: &mut R) -> std::io::Result<SectionMeta> {
60
61        let mut id = [0; 4];
62        read.read_exact(&mut id)?;
63
64        read.read_u32()?;
65        let off = read.read_u32()? as usize;
66        read.read_u32()?;
67        let len = read.read_u32()? as usize;
68        let rows_count = read.read_u32()? as usize;
69
70        Ok(SectionMeta {
71            id,
72            off,
73            len,
74            sections_count: rows_count
75        })
76
77    }
78
79}
80
81impl fmt::Debug for SectionMeta {
82
83    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84        f.debug_struct("SectionMeta")
85            .field("id", &self.id.iter().map(|&c| c as char).collect::<String>())
86            .field("off", &self.off)
87            .field("len", &self.len)
88            .finish()
89    }
90
91}