1use std::{
2 cell::RefCell,
3 collections::HashMap,
4 fs::File,
5 io::{Read, Seek, SeekFrom},
6 num::NonZeroUsize,
7 rc::Rc,
8};
9
10use crc32fast::Hasher;
11
12use crate::{Password, archive::*, bitset::BitSet, block::*, decoder::add_decoder, error::Error};
13
14const MAX_MEM_LIMIT_KB: usize = usize::MAX / 1024;
15
16pub struct BoundedReader<R: Read> {
17 inner: R,
18 remain: usize,
19}
20
21impl<R: Read> BoundedReader<R> {
22 pub fn new(inner: R, max_size: usize) -> Self {
23 Self {
24 inner,
25 remain: max_size,
26 }
27 }
28}
29
30impl<R: Read> Read for BoundedReader<R> {
31 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
32 if self.remain == 0 {
33 return Ok(0);
34 }
35 let remain = self.remain;
36 let buf2 = if buf.len() < remain {
37 buf
38 } else {
39 &mut buf[..remain]
40 };
41 match self.inner.read(buf2) {
42 Ok(size) => {
43 if self.remain < size {
44 self.remain = 0;
45 } else {
46 self.remain -= size;
47 }
48 Ok(size)
49 }
50 Err(e) => Err(e),
51 }
52 }
53}
54
55#[derive(Debug, Default, Clone)]
56pub struct SeekableBoundedReader<R: Read + Seek> {
57 inner: R,
58 cur: u64,
59 bounds: (u64, u64),
60}
61
62impl<R: Read + Seek> Seek for SeekableBoundedReader<R> {
63 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
64 let new_pos = match pos {
65 SeekFrom::Start(pos) => self.bounds.0 as i64 + pos as i64,
66 SeekFrom::End(pos) => self.bounds.1 as i64 + pos,
67 SeekFrom::Current(pos) => self.cur as i64 + pos,
68 };
69 if new_pos < 0 {
70 return Err(std::io::Error::other("SeekBeforeStart"));
71 }
72 self.cur = new_pos as u64;
73 self.inner.seek(SeekFrom::Start(self.cur))
74 }
75}
76
77impl<R: Read + Seek> Read for SeekableBoundedReader<R> {
78 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
79 if self.cur >= self.bounds.1 {
80 return Ok(0);
81 }
82 if self.stream_position()? != self.cur {
83 self.inner.seek(SeekFrom::Start(self.cur))?;
84 }
85 let buf2 = if buf.len() < (self.bounds.1 - self.cur) as usize {
86 buf
87 } else {
88 &mut buf[..(self.bounds.1 - self.cur) as usize]
89 };
90 let size = self.inner.read(buf2)?;
91 self.cur += size as u64;
92 Ok(size)
93 }
94}
95
96impl<R: Read + Seek> SeekableBoundedReader<R> {
97 pub fn new(inner: R, bounds: (u64, u64)) -> Self {
98 Self {
99 inner,
100 cur: bounds.0,
101 bounds,
102 }
103 }
104}
105
106struct Crc32VerifyingReader<R> {
107 inner: R,
108 crc_digest: Hasher,
109 expected_value: u64,
110 remaining: i64,
111}
112
113impl<R: Read> Crc32VerifyingReader<R> {
114 fn new(inner: R, remaining: usize, expected_value: u64) -> Self {
115 Self {
116 inner,
117 crc_digest: Hasher::new(),
118 expected_value,
119 remaining: remaining as i64,
120 }
121 }
122}
123
124impl<R: Read> Read for Crc32VerifyingReader<R> {
125 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
126 if self.remaining <= 0 {
127 return Ok(0);
128 }
129 let size = self.inner.read(buf)?;
130 if size > 0 {
131 self.remaining -= size as i64;
132 self.crc_digest.update(&buf[..size]);
133 }
134 if self.remaining <= 0 {
135 let d = std::mem::replace(&mut self.crc_digest, Hasher::new()).finalize();
136 if d as u64 != self.expected_value {
137 return Err(std::io::Error::other(Error::ChecksumVerificationFailed));
138 }
139 }
140 Ok(size)
141 }
142}
143
144impl Archive {
145 #[inline]
147 pub fn open(path: impl AsRef<std::path::Path>) -> Result<Archive, Error> {
148 Self::open_with_password(path, &Password::empty())
149 }
150
151 #[inline]
157 pub fn open_with_password(
158 path: impl AsRef<std::path::Path>,
159 password: &Password,
160 ) -> Result<Archive, Error> {
161 let mut file = File::open(path)?;
162 Self::read(&mut file, password)
163 }
164
165 pub fn read<R: Read + Seek>(reader: &mut R, password: &Password) -> Result<Archive, Error> {
191 let reader_len = reader.seek(SeekFrom::End(0))?;
192 reader.seek(SeekFrom::Start(0))?;
193
194 let mut signature = [0; 6];
195 reader.read_exact(&mut signature).map_err(Error::io)?;
196 if signature != SEVEN_Z_SIGNATURE {
197 return Err(Error::BadSignature(signature));
198 }
199 let mut versions = [0; 2];
200 reader.read_exact(&mut versions).map_err(Error::io)?;
201 let version_major = versions[0];
202 let version_minor = versions[1];
203 if version_major != 0 {
204 return Err(Error::UnsupportedVersion {
205 major: version_major,
206 minor: version_minor,
207 });
208 }
209
210 let start_header_crc = read_u32(reader)?;
211
212 let header_valid = if start_header_crc == 0 {
213 let current_position = reader.stream_position().map_err(Error::io)?;
214 let mut buf = [0; 20];
215 reader.read_exact(&mut buf).map_err(Error::io)?;
216 reader
217 .seek(SeekFrom::Start(current_position))
218 .map_err(Error::io)?;
219 buf.iter().any(|a| *a != 0)
220 } else {
221 true
222 };
223 if header_valid {
224 let start_header = Self::read_start_header(reader, start_header_crc)?;
225 Self::init_archive(reader, start_header, password, true, 1)
226 } else {
227 Self::try_to_locale_end_header(reader, reader_len, password, 1)
228 }
229 }
230
231 fn read_start_header<R: Read>(
232 reader: &mut R,
233 start_header_crc: u32,
234 ) -> Result<StartHeader, Error> {
235 let mut buf = [0; 20];
236 reader.read_exact(&mut buf).map_err(Error::io)?;
237 let crc32 = crc32fast::hash(&buf);
238 if crc32 != start_header_crc {
239 return Err(Error::ChecksumVerificationFailed);
240 }
241 let mut buf_read = buf.as_slice();
242 let offset = read_u64le(&mut buf_read)?;
243
244 let size = read_u64le(&mut buf_read)?;
245 let crc = read_u32(&mut buf_read)?;
246 Ok(StartHeader {
247 next_header_offset: offset,
248 next_header_size: size,
249 next_header_crc: crc as u64,
250 })
251 }
252
253 fn read_header<R: Read + Seek>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
254 let mut nid = read_u8(header)?;
255 if nid == K_ARCHIVE_PROPERTIES {
256 Self::read_archive_properties(header)?;
257 nid = read_u8(header)?;
258 }
259
260 if nid == K_ADDITIONAL_STREAMS_INFO {
261 return Err(Error::other("Additional streams unsupported"));
262 }
263 if nid == K_MAIN_STREAMS_INFO {
264 Self::read_streams_info(header, archive)?;
265 nid = read_u8(header)?;
266 }
267 if nid == K_FILES_INFO {
268 Self::read_files_info(header, archive)?;
269 nid = read_u8(header)?;
270 }
271 if nid != K_END {
272 return Err(Error::BadTerminatedHeader(nid));
273 }
274
275 Ok(())
276 }
277
278 fn read_archive_properties<R: Read + Seek>(header: &mut R) -> Result<(), Error> {
279 let mut nid = read_u8(header)?;
280 while nid != K_END {
281 let property_size = read_usize(header, "propertySize")?;
282 header
283 .seek(SeekFrom::Current(property_size as i64))
284 .map_err(Error::io)?;
285 nid = read_u8(header)?;
286 }
287 Ok(())
288 }
289
290 fn try_to_locale_end_header<R: Read + Seek>(
291 reader: &mut R,
292 reader_len: u64,
293 password: &Password,
294 thread_count: u32,
295 ) -> Result<Self, Error> {
296 let search_limit = 1024 * 1024;
297 let prev_data_size = reader.stream_position().map_err(Error::io)? + 20;
298 let size = reader_len;
299 let min_pos = if reader.stream_position().map_err(Error::io)? + search_limit > size {
300 reader.stream_position().map_err(Error::io)?
301 } else {
302 size - search_limit
303 };
304 let mut pos = reader_len - 1;
305 while pos > min_pos {
306 pos -= 1;
307
308 reader.seek(SeekFrom::Start(pos)).map_err(Error::io)?;
309 let nid = read_u8(reader)?;
310 if nid == K_ENCODED_HEADER || nid == K_HEADER {
311 let start_header = StartHeader {
312 next_header_offset: pos - prev_data_size,
313 next_header_size: reader_len - pos,
314 next_header_crc: 0,
315 };
316 let result =
317 Self::init_archive(reader, start_header, password, false, thread_count)?;
318
319 if !result.files.is_empty() {
320 return Ok(result);
321 }
322 }
323 }
324 Err(Error::other(
325 "Start header corrupt and unable to guess end header",
326 ))
327 }
328
329 fn init_archive<R: Read + Seek>(
330 reader: &mut R,
331 start_header: StartHeader,
332 password: &Password,
333 verify_crc: bool,
334 thread_count: u32,
335 ) -> Result<Self, Error> {
336 if start_header.next_header_size > usize::MAX as u64 {
337 return Err(Error::other(format!(
338 "Cannot handle next_header_size {}",
339 start_header.next_header_size
340 )));
341 }
342
343 let next_header_size_int = start_header.next_header_size as usize;
344
345 reader
346 .seek(SeekFrom::Start(
347 SIGNATURE_HEADER_SIZE + start_header.next_header_offset,
348 ))
349 .map_err(Error::io)?;
350
351 let mut buf = vec![0; next_header_size_int];
352 reader.read_exact(&mut buf).map_err(Error::io)?;
353 if verify_crc && crc32fast::hash(&buf) as u64 != start_header.next_header_crc {
354 return Err(Error::NextHeaderCrcMismatch);
355 }
356
357 let mut archive = Archive::default();
358 let mut buf_reader = buf.as_slice();
359 let mut nid = read_u8(&mut buf_reader)?;
360 let mut header = if nid == K_ENCODED_HEADER {
361 let (mut out_reader, buf_size) = Self::read_encoded_header(
362 &mut buf_reader,
363 reader,
364 &mut archive,
365 password,
366 thread_count,
367 )?;
368 buf.clear();
369 buf.resize(buf_size, 0);
370 out_reader
371 .read_exact(&mut buf)
372 .map_err(|e| Error::bad_password(e, !password.is_empty()))?;
373 archive = Archive::default();
374 buf_reader = buf.as_slice();
375 nid = read_u8(&mut buf_reader)?;
376 buf_reader
377 } else {
378 buf_reader
379 };
380 let mut header = std::io::Cursor::new(&mut header);
381 if nid == K_HEADER {
382 Self::read_header(&mut header, &mut archive)?;
383 } else {
384 return Err(Error::other("Broken or unsupported archive: no Header"));
385 }
386
387 archive.is_solid = archive
388 .blocks
389 .iter()
390 .any(|block| block.num_unpack_sub_streams > 1);
391
392 Ok(archive)
393 }
394
395 fn read_encoded_header<'r, R: Read, RI: 'r + Read + Seek>(
396 header: &mut R,
397 reader: &'r mut RI,
398 archive: &mut Archive,
399 password: &Password,
400 thread_count: u32,
401 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
402 Self::read_streams_info(header, archive)?;
403 let block = archive
404 .blocks
405 .first()
406 .ok_or(Error::other("no blocks, can't read encoded header"))?;
407 let first_pack_stream_index = 0;
408 let block_offset = SIGNATURE_HEADER_SIZE + archive.pack_pos;
409 if archive.pack_sizes.is_empty() {
410 return Err(Error::other("no packed streams, can't read encoded header"));
411 }
412
413 reader
414 .seek(SeekFrom::Start(block_offset))
415 .map_err(Error::io)?;
416 let coder_len = block.coders.len();
417 let unpack_size = block.get_unpack_size() as usize;
418 let pack_size = archive.pack_sizes[first_pack_stream_index] as usize;
419 let input_reader =
420 SeekableBoundedReader::new(reader, (block_offset, block_offset + pack_size as u64));
421 let mut decoder: Box<dyn Read> = Box::new(input_reader);
422 let mut decoder = if coder_len > 0 {
423 for (index, coder) in block.ordered_coder_iter() {
424 if coder.num_in_streams != 1 || coder.num_out_streams != 1 {
425 return Err(Error::other(
426 "Multi input/output stream coders are not yet supported",
427 ));
428 }
429 let next = add_decoder(
430 decoder,
431 block.get_unpack_size_at_index(index) as usize,
432 coder,
433 password,
434 MAX_MEM_LIMIT_KB,
435 thread_count,
436 )?;
437 decoder = Box::new(next);
438 }
439 decoder
440 } else {
441 decoder
442 };
443 if block.has_crc {
444 decoder = Box::new(Crc32VerifyingReader::new(decoder, unpack_size, block.crc));
445 }
446
447 Ok((decoder, unpack_size))
448 }
449
450 fn read_streams_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
451 let mut nid = read_u8(header)?;
452 if nid == K_PACK_INFO {
453 Self::read_pack_info(header, archive)?;
454 nid = read_u8(header)?;
455 }
456
457 if nid == K_UNPACK_INFO {
458 Self::read_unpack_info(header, archive)?;
459 nid = read_u8(header)?;
460 } else {
461 archive.blocks.clear();
462 }
463 if nid == K_SUB_STREAMS_INFO {
464 Self::read_sub_streams_info(header, archive)?;
465 nid = read_u8(header)?;
466 }
467 if nid != K_END {
468 return Err(Error::BadTerminatedStreamsInfo(nid));
469 }
470
471 Ok(())
472 }
473
474 fn read_files_info<R: Read + Seek>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
475 let num_files = read_usize(header, "num files")?;
476 let mut files: Vec<ArchiveEntry> = vec![Default::default(); num_files];
477
478 let mut is_empty_stream: Option<BitSet> = None;
479 let mut is_empty_file: Option<BitSet> = None;
480 let mut is_anti: Option<BitSet> = None;
481 loop {
482 let prop_type = read_u8(header)?;
483 if prop_type == 0 {
484 break;
485 }
486 let size = read_u64(header)?;
487 match prop_type {
488 K_EMPTY_STREAM => {
489 is_empty_stream = Some(read_bits(header, num_files)?);
490 }
491 K_EMPTY_FILE => {
492 let n = if let Some(s) = &is_empty_stream {
493 s.len()
494 } else {
495 return Err(Error::other(
496 "Header format error: kEmptyStream must appear before kEmptyFile",
497 ));
498 };
499 is_empty_file = Some(read_bits(header, n)?);
500 }
501 K_ANTI => {
502 let n = if let Some(s) = is_empty_stream.as_ref() {
503 s.len()
504 } else {
505 return Err(Error::other(
506 "Header format error: kEmptyStream must appear before kEmptyFile",
507 ));
508 };
509 is_anti = Some(read_bits(header, n)?);
510 }
511 K_NAME => {
512 let external = read_u8(header)?;
513 if external != 0 {
514 return Err(Error::other("Not implemented:external != 0"));
515 }
516 if (size - 1) & 1 != 0 {
517 return Err(Error::other("file names length invalid"));
518 }
519
520 let size = assert_usize(size, "file names length")?;
521 let names_reader = NamesReader::new(header, size - 1);
524
525 let mut next_file = 0;
526 for s in names_reader {
527 files[next_file].name = s?;
528 next_file += 1;
529 }
530
531 if next_file != files.len() {
532 return Err(Error::other("Error parsing file names"));
533 }
534 }
535 K_C_TIME => {
536 let times_defined = read_all_or_bits(header, num_files)?;
537 let external = read_u8(header)?;
538 if external != 0 {
539 return Err(Error::other(format!(
540 "kCTime Unimplemented:external={external}"
541 )));
542 }
543 for (i, file) in files.iter_mut().enumerate() {
544 file.has_creation_date = times_defined.contains(i);
545 if file.has_creation_date {
546 file.creation_date = read_u64le(header)?.into();
547 }
548 }
549 }
550 K_A_TIME => {
551 let times_defined = read_all_or_bits(header, num_files)?;
552 let external = read_u8(header)?;
553 if external != 0 {
554 return Err(Error::other(format!(
555 "kATime Unimplemented:external={external}"
556 )));
557 }
558 for (i, file) in files.iter_mut().enumerate() {
559 file.has_access_date = times_defined.contains(i);
560 if file.has_access_date {
561 file.access_date = read_u64le(header)?.into();
562 }
563 }
564 }
565 K_M_TIME => {
566 let times_defined = read_all_or_bits(header, num_files)?;
567 let external = read_u8(header)?;
568 if external != 0 {
569 return Err(Error::other(format!(
570 "kMTime Unimplemented:external={external}"
571 )));
572 }
573 for (i, file) in files.iter_mut().enumerate() {
574 file.has_last_modified_date = times_defined.contains(i);
575 if file.has_last_modified_date {
576 file.last_modified_date = read_u64le(header)?.into();
577 }
578 }
579 }
580 K_WIN_ATTRIBUTES => {
581 let times_defined = read_all_or_bits(header, num_files)?;
582 let external = read_u8(header)?;
583 if external != 0 {
584 return Err(Error::other(format!(
585 "kWinAttributes Unimplemented:external={external}"
586 )));
587 }
588 for (i, file) in files.iter_mut().enumerate() {
589 file.has_windows_attributes = times_defined.contains(i);
590 if file.has_windows_attributes {
591 file.windows_attributes = read_u32(header)?;
592 }
593 }
594 }
595 K_START_POS => return Err(Error::other("kStartPos is unsupported, please report")),
596 K_DUMMY => {
597 header
598 .seek(SeekFrom::Current(size as i64))
599 .map_err(Error::io)?;
600 }
601 _ => {
602 header
603 .seek(SeekFrom::Current(size as i64))
604 .map_err(Error::io)?;
605 }
606 };
607 }
608
609 let mut non_empty_file_counter = 0;
610 let mut empty_file_counter = 0;
611 for (i, file) in files.iter_mut().enumerate() {
612 file.has_stream = is_empty_stream
613 .as_ref()
614 .map(|s| !s.contains(i))
615 .unwrap_or(true);
616 if file.has_stream {
617 let sub_stream_info = if let Some(s) = archive.sub_streams_info.as_ref() {
618 s
619 } else {
620 return Err(Error::other(
621 "Archive contains file with streams but no subStreamsInfo",
622 ));
623 };
624 file.is_directory = false;
625 file.is_anti_item = false;
626 file.has_crc = sub_stream_info.has_crc.contains(non_empty_file_counter);
627 file.crc = sub_stream_info.crcs[non_empty_file_counter];
628 file.size = sub_stream_info.unpack_sizes[non_empty_file_counter];
629 non_empty_file_counter += 1;
630 } else {
631 file.is_directory = if let Some(s) = &is_empty_file {
632 !s.contains(empty_file_counter)
633 } else {
634 true
635 };
636 file.is_anti_item = is_anti
637 .as_ref()
638 .map(|s| s.contains(empty_file_counter))
639 .unwrap_or(false);
640 file.has_crc = false;
641 file.size = 0;
642 empty_file_counter += 1;
643 }
644 }
645 archive.files = files;
646
647 Self::calculate_stream_map(archive)?;
648 Ok(())
649 }
650
651 fn calculate_stream_map(archive: &mut Archive) -> Result<(), Error> {
652 let mut stream_map = StreamMap::default();
653
654 let mut next_block_pack_stream_index = 0;
655 let num_blocks = archive.blocks.len();
656 stream_map.block_first_pack_stream_index = vec![0; num_blocks];
657 for i in 0..num_blocks {
658 stream_map.block_first_pack_stream_index[i] = next_block_pack_stream_index;
659 next_block_pack_stream_index += archive.blocks[i].packed_streams.len();
660 }
661
662 let mut next_pack_stream_offset = 0;
663 let num_pack_sizes = archive.pack_sizes.len();
664 stream_map.pack_stream_offsets = vec![0; num_pack_sizes];
665 for i in 0..num_pack_sizes {
666 stream_map.pack_stream_offsets[i] = next_pack_stream_offset;
667 next_pack_stream_offset += archive.pack_sizes[i];
668 }
669
670 stream_map.block_first_file_index = vec![0; num_blocks];
671 stream_map.file_block_index = vec![None; archive.files.len()];
672 let mut next_block_index = 0;
673 let mut next_block_unpack_stream_index = 0;
674 for i in 0..archive.files.len() {
675 if !archive.files[i].has_stream && next_block_unpack_stream_index == 0 {
676 stream_map.file_block_index[i] = None;
677 continue;
678 }
679 if next_block_unpack_stream_index == 0 {
680 while next_block_index < archive.blocks.len() {
681 stream_map.block_first_file_index[next_block_index] = i;
682 if archive.blocks[next_block_index].num_unpack_sub_streams > 0 {
683 break;
684 }
685 next_block_index += 1;
686 }
687 if next_block_index >= archive.blocks.len() {
688 return Err(Error::other("Too few blocks in archive"));
689 }
690 }
691 stream_map.file_block_index[i] = Some(next_block_index);
692 if !archive.files[i].has_stream {
693 continue;
694 }
695
696 if stream_map.block_first_file_index[next_block_index] == i {
698 let first_pack_stream_index =
699 stream_map.block_first_pack_stream_index[next_block_index];
700 let pack_size = archive.pack_sizes[first_pack_stream_index];
701
702 archive.files[i].compressed_size = pack_size;
703 }
704
705 next_block_unpack_stream_index += 1;
706 if next_block_unpack_stream_index
707 >= archive.blocks[next_block_index].num_unpack_sub_streams
708 {
709 next_block_index += 1;
710 next_block_unpack_stream_index = 0;
711 }
712 }
713
714 archive.stream_map = stream_map;
715 Ok(())
716 }
717
718 fn read_pack_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
719 archive.pack_pos = read_u64(header)?;
720 let num_pack_streams = read_usize(header, "num pack streams")?;
721 let mut nid = read_u8(header)?;
722 if nid == K_SIZE {
723 archive.pack_sizes = vec![0u64; num_pack_streams];
724 for i in 0..archive.pack_sizes.len() {
725 archive.pack_sizes[i] = read_u64(header)?;
726 }
727 nid = read_u8(header)?;
728 }
729
730 if nid == K_CRC {
731 archive.pack_crcs_defined = read_all_or_bits(header, num_pack_streams)?;
732 archive.pack_crcs = vec![0; num_pack_streams];
733 for i in 0..num_pack_streams {
734 if archive.pack_crcs_defined.contains(i) {
735 archive.pack_crcs[i] = read_u32(header)? as u64;
736 }
737 }
738 nid = read_u8(header)?;
739 }
740
741 if nid != K_END {
742 return Err(Error::BadTerminatedPackInfo(nid));
743 }
744
745 Ok(())
746 }
747 fn read_unpack_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
748 let nid = read_u8(header)?;
749 if nid != K_FOLDER {
750 return Err(Error::other(format!("Expected kFolder, got {nid}")));
751 }
752 let num_blocks = read_usize(header, "num blocks")?;
753
754 archive.blocks.reserve_exact(num_blocks);
755 let external = read_u8(header)?;
756 if external != 0 {
757 return Err(Error::ExternalUnsupported);
758 }
759
760 for _ in 0..num_blocks {
761 archive.blocks.push(Self::read_block(header)?);
762 }
763
764 let nid = read_u8(header)?;
765 if nid != K_CODERS_UNPACK_SIZE {
766 return Err(Error::other(format!(
767 "Expected kCodersUnpackSize, got {nid}"
768 )));
769 }
770
771 for block in archive.blocks.iter_mut() {
772 let tos = block.total_output_streams;
773 block.unpack_sizes.reserve_exact(tos);
774 for _ in 0..tos {
775 block.unpack_sizes.push(read_u64(header)?);
776 }
777 }
778
779 let mut nid = read_u8(header)?;
780 if nid == K_CRC {
781 let crcs_defined = read_all_or_bits(header, num_blocks)?;
782 for i in 0..num_blocks {
783 if crcs_defined.contains(i) {
784 archive.blocks[i].has_crc = true;
785 archive.blocks[i].crc = read_u32(header)? as u64;
786 } else {
787 archive.blocks[i].has_crc = false;
788 }
789 }
790 nid = read_u8(header)?;
791 }
792 if nid != K_END {
793 return Err(Error::BadTerminatedUnpackInfo);
794 }
795
796 Ok(())
797 }
798
799 fn read_sub_streams_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
800 for block in archive.blocks.iter_mut() {
801 block.num_unpack_sub_streams = 1;
802 }
803 let mut total_unpack_streams = archive.blocks.len();
804
805 let mut nid = read_u8(header)?;
806 if nid == K_NUM_UNPACK_STREAM {
807 total_unpack_streams = 0;
808 for block in archive.blocks.iter_mut() {
809 let num_streams = read_usize(header, "numStreams")?;
810 block.num_unpack_sub_streams = num_streams;
811 total_unpack_streams += num_streams;
812 }
813 nid = read_u8(header)?;
814 }
815
816 let mut sub_streams_info = SubStreamsInfo::default();
817 sub_streams_info
818 .unpack_sizes
819 .resize(total_unpack_streams, Default::default());
820 sub_streams_info
821 .has_crc
822 .reserve_len_exact(total_unpack_streams);
823 sub_streams_info.crcs = vec![0; total_unpack_streams];
824
825 let mut next_unpack_stream = 0;
826 for block in archive.blocks.iter() {
827 if block.num_unpack_sub_streams == 0 {
828 continue;
829 }
830 let mut sum = 0;
831 if nid == K_SIZE {
832 for _i in 0..block.num_unpack_sub_streams - 1 {
833 let size = read_u64(header)?;
834 sub_streams_info.unpack_sizes[next_unpack_stream] = size;
835 next_unpack_stream += 1;
836 sum += size;
837 }
838 }
839 if sum > block.get_unpack_size() {
840 return Err(Error::other(
841 "sum of unpack sizes of block exceeds total unpack size",
842 ));
843 }
844 sub_streams_info.unpack_sizes[next_unpack_stream] = block.get_unpack_size() - sum;
845 next_unpack_stream += 1;
846 }
847 if nid == K_SIZE {
848 nid = read_u8(header)?;
849 }
850
851 let mut num_digests = 0;
852 for block in archive.blocks.iter() {
853 if block.num_unpack_sub_streams != 1 || !block.has_crc {
854 num_digests += block.num_unpack_sub_streams;
855 }
856 }
857
858 if nid == K_CRC {
859 let has_missing_crc = read_all_or_bits(header, num_digests)?;
860 let mut missing_crcs = vec![0; num_digests];
861 for (i, missing_crc) in missing_crcs.iter_mut().enumerate() {
862 if has_missing_crc.contains(i) {
863 *missing_crc = read_u32(header)? as u64;
864 }
865 }
866 let mut next_crc = 0;
867 let mut next_missing_crc = 0;
868 for block in archive.blocks.iter() {
869 if block.num_unpack_sub_streams == 1 && block.has_crc {
870 sub_streams_info.has_crc.insert(next_crc);
871 sub_streams_info.crcs[next_crc] = block.crc;
872 next_crc += 1;
873 } else {
874 for _i in 0..block.num_unpack_sub_streams {
875 if has_missing_crc.contains(next_missing_crc) {
876 sub_streams_info.has_crc.insert(next_crc);
877 } else {
878 sub_streams_info.has_crc.remove(next_crc);
879 }
880 sub_streams_info.crcs[next_crc] = missing_crcs[next_missing_crc];
881 next_crc += 1;
882 next_missing_crc += 1;
883 }
884 }
885 }
886
887 nid = read_u8(header)?;
888 }
889
890 if nid != K_END {
891 return Err(Error::BadTerminatedSubStreamsInfo);
892 }
893
894 archive.sub_streams_info = Some(sub_streams_info);
895 Ok(())
896 }
897
898 fn read_block<R: Read>(header: &mut R) -> Result<Block, Error> {
899 let mut block = Block::default();
900
901 let num_coders = read_usize(header, "num coders")?;
902 let mut coders = Vec::with_capacity(num_coders);
903 let mut total_in_streams = 0;
904 let mut total_out_streams = 0;
905 for _i in 0..num_coders {
906 let mut coder = Coder::default();
907 let bits = read_u8(header)?;
908 let id_size = bits & 0xF;
909 let is_simple = (bits & 0x10) == 0;
910 let has_attributes = (bits & 0x20) != 0;
911 let more_alternative_methods = (bits & 0x80) != 0;
912
913 coder.id_size = id_size as usize;
914
915 header
916 .read(coder.decompression_method_id_mut())
917 .map_err(Error::io)?;
918 if is_simple {
919 coder.num_in_streams = 1;
920 coder.num_out_streams = 1;
921 } else {
922 coder.num_in_streams = read_u64(header)?;
923 coder.num_out_streams = read_u64(header)?;
924 }
925 total_in_streams += coder.num_in_streams;
926 total_out_streams += coder.num_out_streams;
927 if has_attributes {
928 let properties_size = read_usize(header, "properties size")?;
929 let mut props = vec![0u8; properties_size];
930 header.read(&mut props).map_err(Error::io)?;
931 coder.properties = props;
932 }
933 coders.push(coder);
934 if more_alternative_methods {
936 return Err(Error::other(
937 "Alternative methods are unsupported, please report. The reference implementation doesn't support them either.",
938 ));
939 }
940 }
941 block.coders = coders;
942 let total_in_streams = assert_usize(total_in_streams, "totalInStreams")?;
943 let total_out_streams = assert_usize(total_out_streams, "totalOutStreams")?;
944 block.total_input_streams = total_in_streams;
945 block.total_output_streams = total_out_streams;
946
947 if total_out_streams == 0 {
948 return Err(Error::other("Total output streams can't be 0"));
949 }
950 let num_bind_pairs = total_out_streams - 1;
951 let mut bind_pairs = Vec::with_capacity(num_bind_pairs);
952 for _ in 0..num_bind_pairs {
953 let bp = BindPair {
954 in_index: read_u64(header)?,
955 out_index: read_u64(header)?,
956 };
957 bind_pairs.push(bp);
958 }
959 block.bind_pairs = bind_pairs;
960
961 if total_in_streams < num_bind_pairs {
962 return Err(Error::other(
963 "Total input streams can't be less than the number of bind pairs",
964 ));
965 }
966 let num_packed_streams = total_in_streams - num_bind_pairs;
967 let mut packed_streams = vec![0; num_packed_streams];
968 if num_packed_streams == 1 {
969 let mut index = u64::MAX;
970 for i in 0..total_in_streams {
971 if block.find_bind_pair_for_in_stream(i).is_none() {
972 index = i as u64;
973 break;
974 }
975 }
976 if index == u64::MAX {
977 return Err(Error::other("Couldn't find stream's bind pair index"));
978 }
979 packed_streams[0] = index;
980 } else {
981 for packed_stream in packed_streams.iter_mut() {
982 *packed_stream = read_u64(header)?;
983 }
984 }
985 block.packed_streams = packed_streams;
986
987 Ok(block)
988 }
989}
990
991#[inline]
992fn read_usize<R: Read>(reader: &mut R, field: &str) -> Result<usize, Error> {
993 let size = read_u64(reader)?;
994 assert_usize(size, field)
995}
996
997#[inline]
998fn assert_usize(size: u64, field: &str) -> Result<usize, Error> {
999 if size > usize::MAX as u64 {
1000 return Err(Error::other(format!("Cannot handle {field} {size}")));
1001 }
1002 Ok(size as usize)
1003}
1004
1005#[inline]
1006fn read_u64le<R: Read>(reader: &mut R) -> Result<u64, Error> {
1007 let mut buf = [0; 8];
1008 reader.read_exact(&mut buf).map_err(Error::io)?;
1009 Ok(u64::from_le_bytes(buf))
1010}
1011
1012fn read_u64<R: Read>(reader: &mut R) -> Result<u64, Error> {
1013 let first = read_u8(reader)? as u64;
1014 let mut mask = 0x80_u64;
1015 let mut value = 0;
1016 for i in 0..8 {
1017 if (first & mask) == 0 {
1018 return Ok(value | ((first & (mask - 1)) << (8 * i)));
1019 }
1020 let b = read_u8(reader)? as u64;
1021 value |= b << (8 * i);
1022 mask >>= 1;
1023 }
1024 Ok(value)
1025}
1026
1027#[inline(always)]
1028fn read_u32<R: Read>(reader: &mut R) -> Result<u32, Error> {
1029 let mut buf = [0; 4];
1030 reader.read_exact(&mut buf).map_err(Error::io)?;
1031 Ok(u32::from_le_bytes(buf))
1032}
1033
1034#[inline(always)]
1035fn read_u8<R: Read>(reader: &mut R) -> Result<u8, Error> {
1036 let mut buf = [0];
1037 reader.read_exact(&mut buf).map_err(Error::io)?;
1038 Ok(buf[0])
1039}
1040
1041fn read_all_or_bits<R: Read>(header: &mut R, size: usize) -> Result<BitSet, Error> {
1042 let all = read_u8(header)?;
1043 if all != 0 {
1044 let mut bits = BitSet::with_capacity(size);
1045 for i in 0..size {
1046 bits.insert(i);
1047 }
1048 Ok(bits)
1049 } else {
1050 read_bits(header, size)
1051 }
1052}
1053
1054fn read_bits<R: Read>(header: &mut R, size: usize) -> Result<BitSet, Error> {
1055 let mut bits = BitSet::with_capacity(size);
1056 let mut mask = 0u32;
1057 let mut cache = 0u32;
1058 for i in 0..size {
1059 if mask == 0 {
1060 mask = 0x80;
1061 cache = read_u8(header)? as u32;
1062 }
1063 if (cache & mask) != 0 {
1064 bits.insert(i);
1065 }
1066 mask >>= 1;
1067 }
1068 Ok(bits)
1069}
1070
1071struct NamesReader<'a, R: Read> {
1072 max_bytes: usize,
1073 read_bytes: usize,
1074 cache: Vec<u16>,
1075 reader: &'a mut R,
1076}
1077
1078impl<'a, R: Read> NamesReader<'a, R> {
1079 fn new(reader: &'a mut R, max_bytes: usize) -> Self {
1080 Self {
1081 max_bytes,
1082 reader,
1083 read_bytes: 0,
1084 cache: Vec::with_capacity(16),
1085 }
1086 }
1087}
1088
1089impl<R: Read> Iterator for NamesReader<'_, R> {
1090 type Item = Result<String, Error>;
1091
1092 fn next(&mut self) -> Option<Self::Item> {
1093 if self.max_bytes <= self.read_bytes {
1094 return None;
1095 }
1096 self.cache.clear();
1097 let mut buf = [0; 2];
1098 while self.read_bytes < self.max_bytes {
1099 let r = self.reader.read_exact(&mut buf).map_err(Error::io);
1100 self.read_bytes += 2;
1101 if let Err(e) = r {
1102 return Some(Err(e));
1103 }
1104 let u = u16::from_le_bytes(buf);
1105 if u == 0 {
1106 break;
1107 }
1108 self.cache.push(u);
1109 }
1110
1111 Some(String::from_utf16(&self.cache).map_err(|e| Error::other(e.to_string())))
1112 }
1113}
1114
1115#[derive(Copy, Clone)]
1116struct IndexEntry {
1117 block_index: Option<usize>,
1118 file_index: usize,
1119}
1120
1121pub struct ArchiveReader<R: Read + Seek> {
1123 source: R,
1124 archive: Archive,
1125 password: Password,
1126 thread_count: u32,
1127 index: HashMap<String, IndexEntry>,
1128}
1129
1130#[cfg(not(target_arch = "wasm32"))]
1131impl ArchiveReader<File> {
1132 #[inline]
1134 pub fn open(path: impl AsRef<std::path::Path>, password: Password) -> Result<Self, Error> {
1135 let file = File::open(path.as_ref())
1136 .map_err(|e| Error::file_open(e, path.as_ref().to_string_lossy().to_string()))?;
1137 Self::new(file, password)
1138 }
1139}
1140
1141impl<R: Read + Seek> ArchiveReader<R> {
1142 #[inline]
1144 pub fn new(mut source: R, password: Password) -> Result<Self, Error> {
1145 let archive = Archive::read(&mut source, &password)?;
1146
1147 let mut reader = Self {
1148 source,
1149 archive,
1150 password,
1151 thread_count: 1,
1152 index: HashMap::default(),
1153 };
1154
1155 reader.fill_index();
1156
1157 let thread_count =
1158 std::thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap());
1159 reader.set_thread_count(thread_count.get() as u32);
1160
1161 Ok(reader)
1162 }
1163
1164 #[inline]
1174 pub fn from_archive(archive: Archive, source: R, password: Password) -> Self {
1175 let mut reader = Self {
1176 source,
1177 archive,
1178 password,
1179 thread_count: 1,
1180 index: HashMap::default(),
1181 };
1182
1183 reader.fill_index();
1184
1185 let thread_count =
1186 std::thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap());
1187 reader.set_thread_count(thread_count.get() as u32);
1188
1189 reader
1190 }
1191
1192 pub fn set_thread_count(&mut self, thread_count: u32) {
1197 self.thread_count = thread_count.clamp(1, 256);
1198 }
1199
1200 fn fill_index(&mut self) {
1201 for (file_index, file) in self.archive.files.iter().enumerate() {
1202 let block_index = self.archive.stream_map.file_block_index[file_index];
1203
1204 self.index.insert(
1205 file.name.clone(),
1206 IndexEntry {
1207 block_index,
1208 file_index,
1209 },
1210 );
1211 }
1212 }
1213
1214 #[inline]
1219 pub fn archive(&self) -> &Archive {
1220 &self.archive
1221 }
1222
1223 fn build_decode_stack<'r>(
1224 source: &'r mut R,
1225 archive: &Archive,
1226 block_index: usize,
1227 password: &Password,
1228 thread_count: u32,
1229 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
1230 let block = &archive.blocks[block_index];
1231 if block.total_input_streams > block.total_output_streams {
1232 return Self::build_decode_stack2(source, archive, block_index, password, thread_count);
1233 }
1234 let first_pack_stream_index = archive.stream_map.block_first_pack_stream_index[block_index];
1235 let block_offset = SIGNATURE_HEADER_SIZE
1236 + archive.pack_pos
1237 + archive.stream_map.pack_stream_offsets[first_pack_stream_index];
1238
1239 source
1240 .seek(SeekFrom::Start(block_offset))
1241 .map_err(Error::io)?;
1242 let pack_size = archive.pack_sizes[first_pack_stream_index] as usize;
1243
1244 let mut decoder: Box<dyn Read> = Box::new(BoundedReader::new(source, pack_size));
1245 let block = &archive.blocks[block_index];
1246 for (index, coder) in block.ordered_coder_iter() {
1247 if coder.num_in_streams != 1 || coder.num_out_streams != 1 {
1248 return Err(Error::unsupported(
1249 "Multi input/output stream coders are not yet supported",
1250 ));
1251 }
1252 let next = add_decoder(
1253 decoder,
1254 block.get_unpack_size_at_index(index) as usize,
1255 coder,
1256 password,
1257 MAX_MEM_LIMIT_KB,
1258 thread_count,
1259 )?;
1260 decoder = Box::new(next);
1261 }
1262 if block.has_crc {
1263 decoder = Box::new(Crc32VerifyingReader::new(
1264 decoder,
1265 block.get_unpack_size() as usize,
1266 block.crc,
1267 ));
1268 }
1269
1270 Ok((decoder, pack_size))
1271 }
1272
1273 fn build_decode_stack2<'r>(
1274 source: &'r mut R,
1275 archive: &Archive,
1276 block_index: usize,
1277 password: &Password,
1278 thread_count: u32,
1279 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
1280 const MAX_CODER_COUNT: usize = 32;
1281 let block = &archive.blocks[block_index];
1282 if block.coders.len() > MAX_CODER_COUNT {
1283 return Err(Error::unsupported(format!(
1284 "Too many coders: {}",
1285 block.coders.len()
1286 )));
1287 }
1288
1289 assert!(block.total_input_streams > block.total_output_streams);
1290 let source = ReaderPointer::new(source);
1291 let first_pack_stream_index = archive.stream_map.block_first_pack_stream_index[block_index];
1292 let start_pos = SIGNATURE_HEADER_SIZE + archive.pack_pos;
1293 let offsets = &archive.stream_map.pack_stream_offsets[first_pack_stream_index..];
1294
1295 let mut sources = Vec::with_capacity(block.packed_streams.len());
1296
1297 for (i, offset) in offsets[..block.packed_streams.len()].iter().enumerate() {
1298 let pack_pos = start_pos + offset;
1299 let pack_size = archive.pack_sizes[first_pack_stream_index + i];
1300 let pack_reader =
1301 SeekableBoundedReader::new(source.clone(), (pack_pos, pack_pos + pack_size));
1302 sources.push(pack_reader);
1303 }
1304
1305 let mut coder_to_stream_map = [usize::MAX; MAX_CODER_COUNT];
1306
1307 let mut si = 0;
1308 for (i, coder) in block.coders.iter().enumerate() {
1309 coder_to_stream_map[i] = si;
1310 si += coder.num_in_streams as usize;
1311 }
1312
1313 let main_coder_index = {
1314 let mut coder_used = [false; MAX_CODER_COUNT];
1315 for bp in block.bind_pairs.iter() {
1316 coder_used[bp.out_index as usize] = true;
1317 }
1318 let mut mci = 0;
1319 for (i, used) in coder_used[..block.coders.len()].iter().enumerate() {
1320 if !used {
1321 mci = i;
1322 break;
1323 }
1324 }
1325 mci
1326 };
1327
1328 let id = block.coders[main_coder_index].encoder_method_id();
1329 if id != EncoderMethod::ID_BCJ2 {
1330 return Err(Error::unsupported(format!("Unsupported method: {id:?}")));
1331 }
1332
1333 let num_in_streams = block.coders[main_coder_index].num_in_streams as usize;
1334 let mut inputs: Vec<Box<dyn Read>> = Vec::with_capacity(num_in_streams);
1335 let start_i = coder_to_stream_map[main_coder_index];
1336 for i in start_i..num_in_streams + start_i {
1337 inputs.push(Self::get_in_stream(
1338 block,
1339 &sources,
1340 &coder_to_stream_map,
1341 password,
1342 i,
1343 thread_count,
1344 )?);
1345 }
1346 let mut decoder: Box<dyn Read> = Box::new(crate::filter::bcj2::BCJ2Reader::new(
1347 inputs,
1348 block.get_unpack_size(),
1349 ));
1350 if block.has_crc {
1351 decoder = Box::new(Crc32VerifyingReader::new(
1352 decoder,
1353 block.get_unpack_size() as usize,
1354 block.crc,
1355 ));
1356 }
1357 Ok((
1358 decoder,
1359 archive.pack_sizes[first_pack_stream_index] as usize,
1360 ))
1361 }
1362
1363 fn get_in_stream<'r>(
1364 block: &Block,
1365 sources: &[SeekableBoundedReader<ReaderPointer<'r, R>>],
1366 coder_to_stream_map: &[usize],
1367 password: &Password,
1368 in_stream_index: usize,
1369 thread_count: u32,
1370 ) -> Result<Box<dyn Read + 'r>, Error>
1371 where
1372 R: 'r,
1373 {
1374 let index = block
1375 .packed_streams
1376 .iter()
1377 .position(|&i| i == in_stream_index as u64);
1378 if let Some(index) = index {
1379 return Ok(Box::new(sources[index].clone()));
1380 }
1381
1382 let bp = block
1383 .find_bind_pair_for_in_stream(in_stream_index)
1384 .ok_or_else(|| {
1385 Error::other(format!(
1386 "Couldn't find bind pair for stream {in_stream_index}"
1387 ))
1388 })?;
1389 let index = block.bind_pairs[bp].out_index as usize;
1390
1391 Self::get_in_stream2(
1392 block,
1393 sources,
1394 coder_to_stream_map,
1395 password,
1396 index,
1397 thread_count,
1398 )
1399 }
1400
1401 fn get_in_stream2<'r>(
1402 block: &Block,
1403 sources: &[SeekableBoundedReader<ReaderPointer<'r, R>>],
1404 coder_to_stream_map: &[usize],
1405 password: &Password,
1406 in_stream_index: usize,
1407 thread_count: u32,
1408 ) -> Result<Box<dyn Read + 'r>, Error>
1409 where
1410 R: 'r,
1411 {
1412 let coder = &block.coders[in_stream_index];
1413 let start_index = coder_to_stream_map[in_stream_index];
1414 if start_index == usize::MAX {
1415 return Err(Error::other("in_stream_index out of range"));
1416 }
1417 let uncompressed_len = block.unpack_sizes[in_stream_index] as usize;
1418 if coder.num_in_streams == 1 {
1419 let input = Self::get_in_stream(
1420 block,
1421 sources,
1422 coder_to_stream_map,
1423 password,
1424 start_index,
1425 thread_count,
1426 )?;
1427
1428 let decoder = add_decoder(
1429 input,
1430 uncompressed_len,
1431 coder,
1432 password,
1433 MAX_MEM_LIMIT_KB,
1434 thread_count,
1435 )?;
1436 return Ok(Box::new(decoder));
1437 }
1438 Err(Error::unsupported(
1439 "Multi input stream coders are not yet supported",
1440 ))
1441 }
1442
1443 pub fn for_each_entries<F: FnMut(&ArchiveEntry, &mut dyn Read) -> Result<bool, Error>>(
1449 &mut self,
1450 mut each: F,
1451 ) -> Result<(), Error> {
1452 let block_count = self.archive.blocks.len();
1453 for block_index in 0..block_count {
1454 let forder_dec = BlockDecoder::new(
1455 self.thread_count,
1456 block_index,
1457 &self.archive,
1458 &self.password,
1459 &mut self.source,
1460 );
1461 forder_dec.for_each_entries(&mut each)?;
1462 }
1463 for file_index in 0..self.archive.files.len() {
1465 let block_index = self.archive.stream_map.file_block_index[file_index];
1466 if block_index.is_none() {
1467 let file = &self.archive.files[file_index];
1468 let empty_reader: &mut dyn Read = &mut ([0u8; 0].as_slice());
1469 if !each(file, empty_reader)? {
1470 return Ok(());
1471 }
1472 }
1473 }
1474 Ok(())
1475 }
1476
1477 pub fn read_file(&mut self, name: &str) -> Result<Vec<u8>, Error> {
1483 let index_entry = *self.index.get(name).ok_or(Error::FileNotFound)?;
1484 let file = &self.archive.files[index_entry.file_index];
1485
1486 if !file.has_stream {
1487 return Ok(Vec::new());
1488 }
1489
1490 let block_index = index_entry
1491 .block_index
1492 .ok_or_else(|| Error::other("File has no associated block"))?;
1493
1494 match self.archive.is_solid {
1495 true => {
1496 let mut result = None;
1497 let target_file_ptr = file as *const _;
1498
1499 BlockDecoder::new(
1500 self.thread_count,
1501 block_index,
1502 &self.archive,
1503 &self.password,
1504 &mut self.source,
1505 )
1506 .for_each_entries(&mut |archive_entry, reader| {
1507 let mut data = Vec::with_capacity(archive_entry.size as usize);
1508 reader.read_to_end(&mut data)?;
1509
1510 if std::ptr::eq(archive_entry, target_file_ptr) {
1511 result = Some(data);
1512 Ok(false)
1513 } else {
1514 Ok(true)
1515 }
1516 })?;
1517
1518 result.ok_or(Error::FileNotFound)
1519 }
1520 false => {
1521 let pack_index = self.archive.stream_map.block_first_pack_stream_index[block_index];
1522 let pack_offset = self.archive.stream_map.pack_stream_offsets[pack_index];
1523 let block_offset = SIGNATURE_HEADER_SIZE + self.archive.pack_pos + pack_offset;
1524
1525 self.source.seek(SeekFrom::Start(block_offset))?;
1526
1527 let (mut block_reader, _size) = Self::build_decode_stack(
1528 &mut self.source,
1529 &self.archive,
1530 block_index,
1531 &self.password,
1532 self.thread_count,
1533 )?;
1534
1535 let mut data = Vec::with_capacity(file.size as usize);
1536 let mut decoder: Box<dyn Read> =
1537 Box::new(BoundedReader::new(&mut block_reader, file.size as usize));
1538
1539 if file.has_crc {
1540 decoder = Box::new(Crc32VerifyingReader::new(
1541 decoder,
1542 file.size as usize,
1543 file.crc,
1544 ));
1545 }
1546
1547 decoder.read_to_end(&mut data)?;
1548
1549 Ok(data)
1550 }
1551 }
1552 }
1553
1554 pub fn file_compression_methods(
1556 &self,
1557 file_name: &str,
1558 methods: &mut Vec<EncoderMethod>,
1559 ) -> Result<(), Error> {
1560 let index_entry = self.index.get(file_name).ok_or(Error::FileNotFound)?;
1561 let file = &self.archive.files[index_entry.file_index];
1562
1563 if !file.has_stream {
1564 return Ok(());
1565 }
1566
1567 let block_index = index_entry
1568 .block_index
1569 .ok_or_else(|| Error::other("File has no associated block"))?;
1570
1571 let block = self
1572 .archive
1573 .blocks
1574 .get(block_index)
1575 .ok_or_else(|| Error::other("Block not found"))?;
1576
1577 block
1578 .coders
1579 .iter()
1580 .filter_map(|coder| EncoderMethod::by_id(coder.encoder_method_id()))
1581 .for_each(|method| {
1582 methods.push(method);
1583 });
1584
1585 Ok(())
1586 }
1587}
1588
1589pub struct BlockDecoder<'a, R: Read + Seek> {
1594 thread_count: u32,
1595 block_index: usize,
1596 archive: &'a Archive,
1597 password: &'a Password,
1598 source: &'a mut R,
1599}
1600
1601impl<'a, R: Read + Seek> BlockDecoder<'a, R> {
1602 pub fn new(
1612 thread_count: u32,
1613 block_index: usize,
1614 archive: &'a Archive,
1615 password: &'a Password,
1616 source: &'a mut R,
1617 ) -> Self {
1618 Self {
1619 thread_count,
1620 block_index,
1621 archive,
1622 password,
1623 source,
1624 }
1625 }
1626
1627 pub fn set_thread_count(&mut self, thread_count: u32) {
1630 self.thread_count = thread_count.clamp(1, 256);
1631 }
1632
1633 pub fn entries(&self) -> &[ArchiveEntry] {
1637 let start = self.archive.stream_map.block_first_file_index[self.block_index];
1638 let file_count = self.archive.blocks[self.block_index].num_unpack_sub_streams;
1639 &self.archive.files[start..(file_count + start)]
1640 }
1641
1642 pub fn entry_count(&self) -> usize {
1644 self.archive.blocks[self.block_index].num_unpack_sub_streams
1645 }
1646
1647 pub fn for_each_entries<F: FnMut(&ArchiveEntry, &mut dyn Read) -> Result<bool, Error>>(
1654 self,
1655 each: &mut F,
1656 ) -> Result<bool, Error> {
1657 let Self {
1658 thread_count,
1659 block_index,
1660 archive,
1661 password,
1662 source,
1663 } = self;
1664 let (mut block_reader, _size) = ArchiveReader::build_decode_stack(
1665 source,
1666 archive,
1667 block_index,
1668 password,
1669 thread_count,
1670 )?;
1671 let start = archive.stream_map.block_first_file_index[block_index];
1672 let file_count = archive.blocks[block_index].num_unpack_sub_streams;
1673
1674 for file_index in start..(file_count + start) {
1675 let file = &archive.files[file_index];
1676 if file.has_stream && file.size > 0 {
1677 let mut decoder: Box<dyn Read> =
1678 Box::new(BoundedReader::new(&mut block_reader, file.size as usize));
1679 if file.has_crc {
1680 decoder = Box::new(Crc32VerifyingReader::new(
1681 decoder,
1682 file.size as usize,
1683 file.crc,
1684 ));
1685 }
1686 if !each(file, &mut decoder)
1687 .map_err(|e| e.maybe_bad_password(!self.password.is_empty()))?
1688 {
1689 return Ok(false);
1690 }
1691 } else {
1692 let empty_reader: &mut dyn Read = &mut ([0u8; 0].as_slice());
1693 if !each(file, empty_reader)? {
1694 return Ok(false);
1695 }
1696 }
1697 }
1698 Ok(true)
1699 }
1700}
1701
1702#[derive(Debug)]
1703#[repr(transparent)]
1704struct ReaderPointer<'a, R>(Rc<RefCell<&'a mut R>>);
1705
1706impl<R> Clone for ReaderPointer<'_, R> {
1707 fn clone(&self) -> Self {
1708 Self(Rc::clone(&self.0))
1709 }
1710}
1711
1712impl<'a, R> ReaderPointer<'a, R> {
1713 fn new(reader: &'a mut R) -> Self {
1714 Self(Rc::new(RefCell::new(reader)))
1715 }
1716}
1717
1718impl<R: Read> Read for ReaderPointer<'_, R> {
1719 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1720 self.0.borrow_mut().read(buf)
1721 }
1722}
1723
1724impl<R: Seek> Seek for ReaderPointer<'_, R> {
1725 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
1726 self.0.borrow_mut().seek(pos)
1727 }
1728}