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
use super::structures::*;
use std::path::Path;
use std::fs;
use std::io::Read;
use std::mem::{transmute, size_of};
#[derive(Debug)]
pub enum WadError {
EntryNotFound(String),
}
#[derive(Debug)]
pub struct Wad {
pub header: Header,
pub directory: Vec<DirEntry>,
pub data_offset: usize,
pub data: Vec<u8>
}
impl Wad {
pub fn parse_header(h: &[u8]) -> Header {
let mut buf = [0u8; size_of::<Header>()];
(&h[0..]).read(&mut buf).unwrap();
unsafe {
transmute(buf)
}
}
pub fn parse_entries(count: usize, d: &[u8]) -> Vec<DirEntry> {
let mut tmp = Vec::new();
let mut tmp_entry = DirEntry {
ptr: 0,
size: 0,
name: [0;8]
};
let mut buf = [0u8; size_of::<DirEntry>()];
for i in 0..count {
(&d[i*size_of::<DirEntry>()..]).read(&mut buf).unwrap();
tmp_entry = unsafe {transmute(buf)};
tmp.push(tmp_entry);
}
tmp
}
pub fn load(path: &Path) -> Wad {
let mut file = fs::File::open(path).unwrap();
let mut bytes = Vec::with_capacity(file.metadata().unwrap().len() as usize);
file.read_to_end(&mut bytes).unwrap();
let header = Self::parse_header(&bytes);
let entries = Self::parse_entries(header.entry_no as usize, &bytes[header.dir_ptr as usize..]);
let offset = entries[0].ptr as usize;
let data = (&bytes[offset..header.dir_ptr as usize]).to_vec();
Wad {
header: header,
directory: entries,
data_offset: offset,
data: data
}
}
pub fn get_entry(&self, name: &[u8;8]) -> Result<Vec<Vec<u8>>, WadError> {
let mut tmp = Vec::new();
for entry in self.directory.iter() {
if entry.name == *name {
tmp.push(Vec::from(&self.data[entry.ptr as usize - self.data_offset..entry.size as usize]));
break;
}
}
if tmp.len() == 0 {
Err(WadError::EntryNotFound(String::from_utf8(name.to_vec()).unwrap()))
} else {
Ok(tmp)
}
}
pub unsafe fn get_entry_as<T>(&self, name: &[u8;8]) -> Result<Vec<&T>, WadError> {
let entries = &self.get_entry(name)?[..];
let mut tmp = Vec::new();
for entry in entries.iter() {
tmp.push((entry.as_ptr() as *const T).as_ref().unwrap());
}
Ok(tmp)
}
}