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 #[inline]
152 pub fn open(path: impl AsRef<Path>) -> Result<Archive, Error> {
153 Self::open_with_password(path, &Password::empty())
154 }
155
156 #[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 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 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 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 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 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 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#[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 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}