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