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
use std::fs::{create_dir_all, File};
use std::io::Error;
use std::io::ErrorKind::InvalidData;
use std::io::Write;
use std::path::Path;
use super::ggpk::GGPK;
pub struct GGPKFile<'a> {
pub ggpk: &'a GGPK,
pub record: FileRecord,
}
impl GGPKFile<'_> {
pub fn write_file(&self, path: &str) -> Result<usize, Error> {
let record = &self.record;
self.ggpk
.mmap
.get(record.begin..(record.begin + record.bytes as usize))
.map(|bytes| {
Path::new(path).parent().map(|path| create_dir_all(path));
File::create(path).and_then(|mut file| file.write(bytes))
})
.unwrap_or_else(|| Err(Error::new(InvalidData, "Read outside GGPK")))
}
pub fn write_into(&self, dst: &mut impl Write) -> Result<usize, Error> {
let record = &self.record;
self.ggpk
.mmap
.get(record.begin..(record.begin + record.bytes as usize))
.map(|bytes| dst.write(bytes))
.unwrap_or_else(|| Err(Error::new(InvalidData, "Read outside GGPK")))
}
pub fn bytes(&self) -> &[u8] {
let record = &self.record;
self.ggpk
.mmap
.get(record.begin..(record.begin + record.bytes as usize))
.unwrap()
}
}
pub struct FileRecord {
pub name: String,
pub path: String,
pub signature: [u8; 32],
pub begin: usize,
pub bytes: u32,
}
impl FileRecord {
pub fn absolute_path(&self) -> String {
format!("{}/{}", self.path, self.name)
}
pub fn clone(&self) -> FileRecord {
FileRecord {
name: self.name.clone(),
path: self.path.clone(),
signature: self.signature,
begin: self.begin,
bytes: self.bytes,
}
}
}