diff --git a/Cargo.toml b/Cargo.toml index a25d05a..ed2051e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" byteorder = "*" strum = { version = "*", features = ["derive"] } aes = "*" +flate2 = "*" hashbrown = "*" thiserror = "*" diff --git a/src/entry.rs b/src/entry.rs index e1f7c5b..2cea50b 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -4,16 +4,15 @@ use std::io; #[derive(Debug)] pub struct Block { - pub offset: u64, - /// size of the compressed block - pub size: u64, + pub start: u64, + pub end: u64, } impl Block { pub fn new(reader: &mut R) -> Result { Ok(Self { - offset: reader.read_u64::()?, - size: reader.read_u64::()?, + start: reader.read_u64::()?, + end: reader.read_u64::()?, }) } } @@ -26,7 +25,7 @@ pub struct Entry { pub compression: Compression, pub timestamp: Option, pub hash: [u8; 20], - pub compression_blocks: Option>, + pub blocks: Option>, pub encrypted: bool, pub block_uncompressed: Option, } @@ -51,7 +50,7 @@ impl Entry { false => None, }, hash: reader.read_guid()?, - compression_blocks: match version >= Version::CompressionEncryption + blocks: match version >= Version::CompressionEncryption && compression != Compression::None { true => Some(reader.read_array(Block::new)?), @@ -90,7 +89,26 @@ impl Entry { use io::Write; match self.compression { Compression::None => buf.write_all(&data)?, - Compression::Zlib => todo!(), + Compression::Zlib => { + let mut decoder = flate2::write::ZlibDecoder::new(buf); + match &self.blocks { + Some(blocks) => { + for block in blocks { + decoder.write( + &data[match version >= Version::RelativeChunkOffsets { + true => { + (block.start - self.offset) as usize + ..(block.end - self.offset) as usize + } + false => block.start as usize..block.end as usize, + }], + )?; + } + } + None => decoder.write_all(&data)?, + } + buf = decoder.finish()?; + } Compression::Gzip => todo!(), Compression::Oodle => todo!(), }