aboutsummaryrefslogtreecommitdiff
path: root/src/zip/file/read.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip/file/read.rs')
-rw-r--r--src/zip/file/read.rs42
1 files changed, 33 insertions, 9 deletions
diff --git a/src/zip/file/read.rs b/src/zip/file/read.rs
index 56f42da..c5c7e99 100644
--- a/src/zip/file/read.rs
+++ b/src/zip/file/read.rs
@@ -2,16 +2,17 @@ use crate::driver::FileDriver;
2use crate::zip::{CompressionMethod, ZipError, ZipFileInfo, ZipResult}; 2use crate::zip::{CompressionMethod, ZipError, ZipFileInfo, ZipResult};
3use bzip2::read::BzDecoder; 3use bzip2::read::BzDecoder;
4use flate2::read::DeflateDecoder; 4use flate2::read::DeflateDecoder;
5use liblzma::read::XzDecoder;
6use liblzma::stream::{Filters, LzmaOptions, Stream};
5use std::io::{ 7use std::io::{
6 Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom, 8 Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom,
7}; 9};
8use xz2::read::XzDecoder;
9 10
10enum IoProxy<Io: Read> { 11enum IoProxy<Io: Read> {
11 Store(Io), 12 Store(Io),
12 Deflate(DeflateDecoder<Io>), 13 Deflate(DeflateDecoder<Io>),
13 BZip2(BzDecoder<Io>), 14 BZip2(BzDecoder<Io>),
14 XZ(XzDecoder<Io>), 15 Xz(XzDecoder<Io>),
15} 16}
16 17
17pub struct ZipFileReader<'d, Io: Read> { 18pub struct ZipFileReader<'d, Io: Read> {
@@ -39,6 +40,7 @@ impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> {
39 io.read(&mut buf)?; 40 io.read(&mut buf)?;
40 buf 41 buf
41 }; 42 };
43
42 if u32::from_le_bytes(buf[..4].try_into().unwrap()) != 0x04034b50 { 44 if u32::from_le_bytes(buf[..4].try_into().unwrap()) != 0x04034b50 {
43 return Err(ZipError::InvalidFileHeaderSignature.into()); 45 return Err(ZipError::InvalidFileHeaderSignature.into());
44 } 46 }
@@ -46,20 +48,42 @@ impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> {
46 + 30 48 + 30
47 + u16::from_le_bytes(buf[26..28].try_into().unwrap()) as u64 49 + u16::from_le_bytes(buf[26..28].try_into().unwrap()) as u64
48 + u16::from_le_bytes(buf[28..30].try_into().unwrap()) as u64; 50 + u16::from_le_bytes(buf[28..30].try_into().unwrap()) as u64;
49 io.seek(SeekFrom::Start(data_pointer))?; 51 let mut cursor = io.seek(SeekFrom::Start(data_pointer))?;
50 52
51 Ok(Self { 53 Ok(Self {
52 io: match info.compression_method { 54 io: match info.compression_method {
53 CompressionMethod::Store => IoProxy::Store(io), 55 CompressionMethod::Store => IoProxy::Store(io),
54 CompressionMethod::Deflate => IoProxy::Deflate(DeflateDecoder::new(io)), 56 CompressionMethod::Deflate => IoProxy::Deflate(DeflateDecoder::new(io)),
55 CompressionMethod::BZip2 => IoProxy::BZip2(BzDecoder::new(io)), 57 CompressionMethod::BZip2 => IoProxy::BZip2(BzDecoder::new(io)),
56 CompressionMethod::LZMA => IoProxy::XZ(XzDecoder::new(io)), 58 CompressionMethod::Lzma => {
57 CompressionMethod::XZ => IoProxy::XZ(XzDecoder::new(io)), 59 let buf = {
60 let mut buf = [0; 9];
61 io.read(&mut buf)?;
62 cursor += 9;
63 buf
64 };
65 IoProxy::Xz(XzDecoder::new_stream(
66 io,
67 Stream::new_raw_decoder(
68 Filters::new().lzma1(
69 LzmaOptions::new()
70 .literal_context_bits((buf[4] % 9) as u32)
71 .literal_position_bits((buf[4] / 9 % 5) as u32)
72 .position_bits((buf[4] / 45) as u32)
73 .dict_size(
74 u32::from_le_bytes(buf[5..9].try_into().unwrap()).min(4096),
75 ),
76 ),
77 )
78 .unwrap(),
79 ))
80 }
81 CompressionMethod::Xz => IoProxy::Xz(XzDecoder::new(io)),
58 }, 82 },
59 info, 83 info,
60 84
61 bounds: (data_pointer, data_pointer + info.compressed_size), 85 bounds: (cursor, data_pointer + info.compressed_size),
62 cursor: data_pointer, 86 cursor: cursor,
63 }) 87 })
64 } 88 }
65 89
@@ -78,7 +102,7 @@ impl<'d, Io: Read> Read for ZipFileReader<'d, Io> {
78 IoProxy::Store(io) => io.read(&mut buf[..upper]), 102 IoProxy::Store(io) => io.read(&mut buf[..upper]),
79 IoProxy::Deflate(io) => io.read(&mut buf[..upper]), 103 IoProxy::Deflate(io) => io.read(&mut buf[..upper]),
80 IoProxy::BZip2(io) => io.read(&mut buf[..upper]), 104 IoProxy::BZip2(io) => io.read(&mut buf[..upper]),
81 IoProxy::XZ(io) => io.read(&mut buf[..upper]), 105 IoProxy::Xz(io) => io.read(&mut buf[..upper]),
82 }?; 106 }?;
83 self.cursor += upper as u64; 107 self.cursor += upper as u64;
84 Ok(bytes) 108 Ok(bytes)
@@ -118,7 +142,7 @@ impl<'d, Io: Read + Seek> Seek for ZipFileReader<'d, Io> {
118 } 142 }
119 _ => Err(IoError::new( 143 _ => Err(IoError::new(
120 IoErrorKind::Unsupported, 144 IoErrorKind::Unsupported,
121 ZipError::CompressionDataIsUnseekable, 145 ZipError::CompressedDataIsUnseekable,
122 )), 146 )),
123 } 147 }
124 } 148 }