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}