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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#![warn(missing_docs)]
use std::{
fs::File,
io::{self, BufReader, Cursor, ErrorKind, Read, Seek, SeekFrom},
path::Path,
};
use byteorder::{BigEndian, ReadBytesExt};
use compression::CompressedRead;
use read::{get_info, read_next_item};
pub mod compression;
pub mod extract;
pub mod read;
pub struct MarFileInfo {
offset_to_index: u32,
#[allow(dead_code)]
has_signature_block: bool,
#[allow(dead_code)]
num_signatures: u32,
#[allow(dead_code)]
has_additional_blocks: bool,
#[allow(dead_code)]
offset_additional_blocks: u32,
#[allow(dead_code)]
num_additional_blocks: u32,
}
pub struct MarItem {
offset: u32,
pub length: u32,
pub flags: u32,
pub name: String,
}
pub struct Mar<R> {
info: MarFileInfo,
buffer: R,
}
impl<R> Mar<R>
where
R: Read + Seek,
{
pub fn from_buffer(mut buffer: R) -> io::Result<Mar<R>> {
let info = get_info(&mut buffer)?;
Ok(Mar { info, buffer })
}
}
impl Mar<BufReader<File>> {
pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Mar<BufReader<File>>> {
let buffer = BufReader::new(File::open(path)?);
Self::from_buffer(buffer)
}
}
impl<R> Mar<R>
where
R: Read + Seek,
{
pub fn read<'a>(&'a mut self, item: &MarItem) -> io::Result<CompressedRead<'a, R>> {
self.buffer.seek(SeekFrom::Start(item.offset as u64))?;
CompressedRead::new(&mut self.buffer, item.length as u64)
}
pub fn files(&mut self) -> io::Result<Files> {
self.buffer
.seek(SeekFrom::Start(self.info.offset_to_index as u64))?;
let size_of_index = self.buffer.read_u32::<BigEndian>()?;
let mut index = vec![0; size_of_index as usize];
self.buffer.read_exact(&mut index)?;
Ok(Files {
index: Cursor::new(index),
})
}
}
pub struct Files {
index: Cursor<Vec<u8>>,
}
impl Iterator for Files {
type Item = io::Result<MarItem>;
fn next(&mut self) -> Option<Self::Item> {
match read_next_item(&mut self.index) {
Ok(item) => Some(Ok(item)),
Err(e) => {
if e.kind() == ErrorKind::UnexpectedEof {
None
} else {
Some(Err(e))
}
}
}
}
}