1#![allow(unused)]
2use crate::{folder::*, method_options::MethodOptions};
3use bit_set::BitSet;
4use nt_time::FileTime;
5use std::sync::Arc;
6
7pub(crate) const SIGNATURE_HEADER_SIZE: u64 = 32;
8pub(crate) const SEVEN_Z_SIGNATURE: &[u8] = &[b'7', b'z', 0xBC, 0xAF, 0x27, 0x1C];
9
10pub(crate) const K_END: u8 = 0x00;
11pub(crate) const K_HEADER: u8 = 0x01;
12pub(crate) const K_ARCHIVE_PROPERTIES: u8 = 0x02;
13pub(crate) const K_ADDITIONAL_STREAMS_INFO: u8 = 0x03;
14pub(crate) const K_MAIN_STREAMS_INFO: u8 = 0x04;
15pub(crate) const K_FILES_INFO: u8 = 0x05;
16pub(crate) const K_PACK_INFO: u8 = 0x06;
17pub(crate) const K_UNPACK_INFO: u8 = 0x07;
18pub(crate) const K_SUB_STREAMS_INFO: u8 = 0x08;
19pub(crate) const K_SIZE: u8 = 0x09;
20pub(crate) const K_CRC: u8 = 0x0A;
21pub(crate) const K_FOLDER: u8 = 0x0B;
22pub(crate) const K_CODERS_UNPACK_SIZE: u8 = 0x0C;
23pub(crate) const K_NUM_UNPACK_STREAM: u8 = 0x0D;
24pub(crate) const K_EMPTY_STREAM: u8 = 0x0E;
25pub(crate) const K_EMPTY_FILE: u8 = 0x0F;
26pub(crate) const K_ANTI: u8 = 0x10;
27pub(crate) const K_NAME: u8 = 0x11;
28pub(crate) const K_C_TIME: u8 = 0x12;
29pub(crate) const K_A_TIME: u8 = 0x13;
30pub(crate) const K_M_TIME: u8 = 0x14;
31pub(crate) const K_WIN_ATTRIBUTES: u8 = 0x15;
32pub(crate) const K_COMMENT: u8 = 0x16;
33pub(crate) const K_ENCODED_HEADER: u8 = 0x17;
34pub(crate) const K_START_POS: u8 = 0x18;
35pub(crate) const K_DUMMY: u8 = 0x19;
36
37#[derive(Debug, Default, Clone)]
38pub struct Archive {
39 pub pack_pos: u64,
41 pub pack_sizes: Vec<u64>,
42 pub pack_crcs_defined: BitSet,
43 pub pack_crcs: Vec<u64>,
44 pub folders: Vec<Folder>,
45 pub sub_streams_info: Option<SubStreamsInfo>,
46 pub files: Vec<SevenZArchiveEntry>,
47 pub stream_map: StreamMap,
48 pub is_solid: bool,
49}
50
51#[derive(Debug, Default, Clone)]
52pub struct SubStreamsInfo {
53 pub unpack_sizes: Vec<u64>,
54 pub has_crc: BitSet,
55 pub crcs: Vec<u64>,
56}
57
58#[derive(Debug, Default, Clone)]
59pub struct SevenZArchiveEntry {
60 pub name: String,
61 pub has_stream: bool,
62 pub is_directory: bool,
63 pub is_anti_item: bool,
64 pub has_creation_date: bool,
65 pub has_last_modified_date: bool,
66 pub has_access_date: bool,
67 pub creation_date: FileTime,
68 pub last_modified_date: FileTime,
69 pub access_date: FileTime,
70 pub has_windows_attributes: bool,
71 pub windows_attributes: u32,
72 pub has_crc: bool,
73 pub crc: u64,
74 pub compressed_crc: u64,
75 pub size: u64,
76 pub compressed_size: u64,
77 pub(crate) content_methods: Arc<Vec<SevenZMethodConfiguration>>,
78}
79
80impl SevenZArchiveEntry {
81 pub fn new() -> Self {
82 Self::default()
83 }
84
85 pub fn new_file(entry_name: &str) -> Self {
86 Self {
87 name: entry_name.to_string(),
88 has_stream: true,
89 is_directory: false,
90 ..Default::default()
91 }
92 }
93
94 pub fn new_folder(entry_name: &str) -> Self {
95 Self {
96 name: entry_name.to_string(),
97 has_stream: false,
98 is_directory: true,
99 ..Default::default()
100 }
101 }
102
103 pub fn from_path(path: impl AsRef<std::path::Path>, entry_name: String) -> Self {
104 let path = path.as_ref();
105 #[cfg(target_os = "windows")]
106 let entry_name = {
107 let mut name_bytes = entry_name.into_bytes();
108 for b in &mut name_bytes {
109 if *b == b'\\' {
110 *b = b'/';
111 }
112 }
113 String::from_utf8(name_bytes).unwrap()
114 };
115 let mut entry = SevenZArchiveEntry {
116 name: entry_name,
117 has_stream: path.is_file(),
118 is_directory: path.is_dir(),
119 ..Default::default()
120 };
121
122 if let Ok(meta) = path.metadata() {
123 if let Ok(modified) = meta.modified() {
124 if let Ok(date) = modified.try_into() {
125 entry.last_modified_date = date;
126 entry.has_last_modified_date = entry.last_modified_date.to_raw() > 0;
127 }
128 }
129 if let Ok(date) = meta.created() {
130 if let Ok(date) = date.try_into() {
131 entry.creation_date = date;
132 entry.has_creation_date = entry.creation_date.to_raw() > 0;
133 }
134 }
135 if let Ok(date) = meta.accessed() {
136 if let Ok(date) = date.try_into() {
137 entry.access_date = date;
138 entry.has_access_date = entry.access_date.to_raw() > 0;
139 }
140 }
141 }
142 entry
143 }
144
145 pub fn name(&self) -> &str {
146 self.name.as_ref()
147 }
148
149 pub fn is_directory(&self) -> bool {
150 self.is_directory
151 }
152
153 pub fn has_stream(&self) -> bool {
154 self.has_stream
155 }
156
157 pub fn creation_date(&self) -> FileTime {
158 self.creation_date
159 }
160
161 pub fn last_modified_date(&self) -> FileTime {
162 self.last_modified_date
163 }
164
165 pub fn size(&self) -> u64 {
166 self.size
167 }
168
169 pub fn windows_attributes(&self) -> u32 {
170 self.windows_attributes
171 }
172
173 pub fn access_date(&self) -> FileTime {
174 self.access_date
175 }
176
177 pub fn is_anti_item(&self) -> bool {
178 self.is_anti_item
179 }
180}
181
182#[derive(Debug, Default)]
183pub struct SevenZMethodConfiguration {
184 pub method: SevenZMethod,
185 pub options: Option<MethodOptions>,
186}
187
188impl From<SevenZMethod> for SevenZMethodConfiguration {
189 fn from(value: SevenZMethod) -> Self {
190 Self::new(value)
191 }
192}
193
194impl Clone for SevenZMethodConfiguration {
195 fn clone(&self) -> Self {
196 Self {
197 method: self.method,
198 options: self.options.clone(),
199 }
200 }
201}
202
203impl SevenZMethodConfiguration {
204 pub fn new(method: SevenZMethod) -> Self {
205 Self {
206 method,
207 options: None,
208 }
209 }
210
211 pub fn with_options(mut self, options: MethodOptions) -> Self {
212 self.options = Some(options);
213 self
214 }
215}
216
217#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, Hash)]
218pub struct SevenZMethod(&'static str, &'static [u8]);
219
220impl SevenZMethod {
221 pub const ID_COPY: &'static [u8] = &[0x00];
222
223 pub const ID_LZMA: &'static [u8] = &[0x03, 0x01, 0x01];
224 pub const ID_LZMA2: &'static [u8] = &[0x21];
225 pub const ID_ZSTD: &'static [u8] = &[4, 247, 17, 1];
226 pub const ID_DEFLATE: &'static [u8] = &[0x04, 0x01, 0x08];
227 pub const ID_DEFLATE64: &'static [u8] = &[0x04, 0x01, 0x09];
228
229 pub const ID_BCJ_X86: &'static [u8] = &[0x03, 0x03, 0x01, 0x03];
230 pub const ID_BCJ_PPC: &'static [u8] = &[0x03, 0x03, 0x02, 0x05];
231 pub const ID_BCJ_IA64: &'static [u8] = &[0x03, 0x03, 0x04, 0x01];
232 pub const ID_BCJ_ARM: &'static [u8] = &[0x03, 0x03, 0x05, 0x01];
233 pub const ID_BCJ_ARM_THUMB: &'static [u8] = &[0x03, 0x03, 0x07, 0x01];
234 pub const ID_BCJ_SPARC: &'static [u8] = &[0x03, 0x03, 0x08, 0x05];
235 pub const ID_DELTA: &'static [u8] = &[0x03];
236 pub const ID_BZIP2: &'static [u8] = &[0x04, 0x02, 0x02];
237 pub const ID_AES256SHA256: &'static [u8] = &[0x06, 0xf1, 0x07, 0x01];
238 pub const ID_BCJ2: &'static [u8] = &[0x03, 0x03, 0x01, 0x1B];
239 pub const COPY: SevenZMethod = Self("COPY", Self::ID_COPY);
241
242 pub const LZMA: Self = Self("LZMA", Self::ID_LZMA);
243 pub const LZMA2: Self = Self("LZMA2", Self::ID_LZMA2);
244 pub const ZSTD: Self = Self("ZSTD", Self::ID_ZSTD);
245
246 pub const DEFLATE: Self = Self("DEFLATE", Self::ID_DEFLATE);
247 pub const DEFLATE64: Self = Self("DEFLATE64", Self::ID_DEFLATE64);
248
249 pub const BZIP2: Self = Self("BZIP2", Self::ID_BZIP2);
250 pub const AES256SHA256: Self = Self("AES256SHA256", Self::ID_AES256SHA256);
251
252 pub const BCJ_X86_FILTER: Self = Self("BCJ_X86", Self::ID_BCJ_X86);
253 pub const BCJ_PPC_FILTER: Self = Self("BCJ_PPC", Self::ID_BCJ_PPC);
254 pub const BCJ_IA64_FILTER: Self = Self("BCJ_IA64", Self::ID_BCJ_IA64);
255 pub const BCJ_ARM_FILTER: Self = Self("BCJ_ARM", Self::ID_BCJ_ARM);
256 pub const BCJ_ARM_THUMB_FILTER: Self = Self("BCJ_ARM_THUMB", Self::ID_BCJ_ARM_THUMB);
257 pub const BCJ_SPARC_FILTER: Self = Self("BCJ_SPARC", Self::ID_BCJ_SPARC);
258 pub const DELTA_FILTER: Self = Self("DELTA", Self::ID_DELTA);
259 pub const BCJ2_FILTER: Self = Self("BCJ2", Self::ID_BCJ2);
260
261 const METHODS: &'static [&'static SevenZMethod] = &[
262 &Self::COPY,
263 &Self::ZSTD,
264 &Self::LZMA,
265 &Self::LZMA2,
266 &Self::DEFLATE,
267 &Self::DEFLATE64,
268 &Self::BZIP2,
269 &Self::AES256SHA256,
270 &Self::BCJ_X86_FILTER,
271 &Self::BCJ_PPC_FILTER,
272 &Self::BCJ_IA64_FILTER,
273 &Self::BCJ_ARM_FILTER,
274 &Self::BCJ_ARM_THUMB_FILTER,
275 &Self::BCJ_SPARC_FILTER,
276 &Self::DELTA_FILTER,
277 &Self::BCJ2_FILTER,
278 ];
279
280 #[inline]
281 pub const fn name(&self) -> &'static str {
282 self.0
283 }
284
285 #[inline]
286 pub const fn id(&self) -> &'static [u8] {
287 self.1
288 }
289
290 #[inline]
291 pub fn by_id(id: &[u8]) -> Option<Self> {
292 Self::METHODS
293 .iter()
294 .find(|item| item.id() == id)
295 .cloned()
296 .cloned()
297 }
298}
299
300#[derive(Debug, Default, Clone)]
301pub struct StreamMap {
302 pub folder_first_pack_stream_index: Vec<usize>,
303 pub pack_stream_offsets: Vec<u64>,
304 pub folder_first_file_index: Vec<usize>,
305 pub file_folder_index: Vec<Option<usize>>,
306}
307
308#[derive(Debug, Clone, Copy)]
309pub(crate) struct StartHeader {
310 pub(crate) next_header_offset: u64,
311 pub(crate) next_header_size: u64,
312 pub(crate) next_header_crc: u64,
313}