Skip to main content

fable_data/wad/
decode.rs

1use std::io::{Read,Seek,SeekFrom};
2
3use nom::IResult;
4use nom::number::complete::le_u32;
5use nom::bytes::complete::{tag,take};
6use nom::sequence::tuple;
7use nom::multi::count;
8use nom::combinator::all_consuming;
9
10use chrono::naive::{NaiveDateTime,NaiveDate,NaiveTime};
11
12use crate::{Decode,Error};
13use crate::shared::decode_bytes_as_utf8_string;
14use crate::Entry;
15
16use super::{Wad,WadHeader,WadEntry};
17
18impl Decode for Wad {
19    fn decode<Source>(source: &mut Source) -> Result<Self, Error> where
20        Source: Read + Seek
21    {
22        let mut header_buf = [0; 32];
23        let mut entries_buf = Vec::new();
24
25        source.read_exact(&mut header_buf)?;
26        let (_, header) = all_consuming(Wad::decode_header)(&header_buf)?;
27
28        source.seek(SeekFrom::Start(header.entries_offset as u64))?;
29        source.read_to_end(&mut entries_buf)?;
30        let (_, entries) = count(Wad::decode_entry, header.entries_count as usize)(&entries_buf)?;
31
32        Ok(Wad { header: header, entries: entries })
33    }
34}
35
36impl Wad {
37    pub fn decode_header(input: &[u8]) -> IResult<&[u8], WadHeader, Error> {
38        let (input, _magic_number) = tag("BBBB")(input)?;
39        let (input, version) = tuple((le_u32, le_u32, le_u32))(input)?;
40        let (input, block_size) = le_u32(input)?;
41        let (input, entries_count) = le_u32(input)?;
42        let (input, _entries_count_again) = le_u32(input)?;
43        let (input, entries_offset) = le_u32(input)?;
44
45        Ok(
46            (
47                input,
48                WadHeader {
49                    version: version,
50                    block_size: block_size,
51                    entries_count: entries_count,
52                    entries_offset: entries_offset,
53                }
54            )
55        )
56    }
57
58    pub fn decode_entry(input: &[u8]) -> IResult<&[u8], WadEntry, Error> {
59        let (input, _unknown_1) = take(16usize)(input)?;
60        let (input, id) = le_u32(input)?;
61        let (input, _unknown_2) = le_u32(input)?;
62        let (input, length) = le_u32(input)?;
63        let (input, offset) = le_u32(input)?;
64        let (input, _unknown_3) = le_u32(input)?;
65        let (input, path_length) = le_u32(input)?;
66        let (input, path) = take(path_length as usize)(input)?;
67
68        let (_, path) = decode_bytes_as_utf8_string(path)?;
69
70        let (input, _unknown_4) = take(16usize)(input)?;
71
72        let (input, created) = Self::decode_timestamp(input)?;
73        let (input, accessed) = Self::decode_timestamp(input)?;
74        let (input, written) = Self::decode_short_timestamp(input)?;
75
76        Ok(
77            (
78                input,
79                WadEntry {
80                    id: id,
81                    length: length,
82                    offset: offset,
83                    path: path,
84                    created: created,
85                    accessed: accessed,
86                    written: written,
87                }
88            )
89        )
90    }
91
92    pub fn decode_timestamp(input: &[u8]) -> IResult<&[u8], NaiveDateTime, Error> {
93        let (input, year) = le_u32(input)?;
94        let (input, month) = le_u32(input)?;
95        let (input, day) = le_u32(input)?;
96        let (input, hour) = le_u32(input)?;
97        let (input, minute) = le_u32(input)?;
98        let (input, second) = le_u32(input)?;
99        let (input, millisecond) = le_u32(input)?;
100
101        let ymd = NaiveDate::from_ymd(year as i32, month, day);
102        let hms = NaiveTime::from_hms_milli(hour, minute, second, millisecond);
103        let date_time = NaiveDateTime::new(ymd, hms);
104
105        Ok((input, date_time))
106    }
107
108    pub fn decode_short_timestamp(input: &[u8]) -> IResult<&[u8], NaiveDateTime, Error> {
109        let (input, year) = le_u32(input)?;
110        let (input, month) = le_u32(input)?;
111        let (input, day) = le_u32(input)?;
112        let (input, hour) = le_u32(input)?;
113        let (input, minute) = le_u32(input)?;
114
115        let ymd = NaiveDate::from_ymd(year as i32, month, day);
116        let hms = NaiveTime::from_hms(hour, minute, 0);
117        let date_time = NaiveDateTime::new(ymd, hms);
118
119        Ok((input, date_time))
120    }
121}
122
123impl Entry for WadEntry {
124    fn len(&self) -> u64 { self.length as u64 }
125    fn pos(&self) -> u64 { self.offset as u64 }
126}