sevenz_rust/
reader.rs

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