mirror of
https://github.com/xavo95/repak.git
synced 2025-02-22 15:53:45 +00:00
Add LZ4 compression
This commit is contained in:
parent
9090a6984d
commit
9764808fb3
5 changed files with 70 additions and 47 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
@ -668,6 +668,15 @@ version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lz4_flex"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"twox-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
@ -843,6 +852,7 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"flate2",
|
"flate2",
|
||||||
"hex",
|
"hex",
|
||||||
|
"lz4_flex",
|
||||||
"oodle_loader",
|
"oodle_loader",
|
||||||
"pariter",
|
"pariter",
|
||||||
"paste",
|
"paste",
|
||||||
|
@ -1016,6 +1026,12 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -1122,6 +1138,16 @@ dependencies = [
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twox-hash"
|
||||||
|
version = "1.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
|
|
@ -9,8 +9,8 @@ keywords.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["compression", "encryption"]
|
default = ["compression", "encryption"]
|
||||||
compression = ["dep:flate2", "dep:zstd"]
|
compression = ["dep:flate2", "dep:zstd", "dep:lz4_flex"]
|
||||||
oodle = ["dep:oodle_loader"]
|
oodle = ["dep:oodle_loader", "compression"]
|
||||||
encryption = ["dep:aes"]
|
encryption = ["dep:aes"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -18,6 +18,7 @@ byteorder = "1.5"
|
||||||
aes = { workspace = true, optional = true }
|
aes = { workspace = true, optional = true }
|
||||||
flate2 = { version = "1.0", optional = true }
|
flate2 = { version = "1.0", optional = true }
|
||||||
zstd = { version = "0.13", optional = true }
|
zstd = { version = "0.13", optional = true }
|
||||||
|
lz4_flex = { version = "0.11.3", optional = true }
|
||||||
oodle_loader = { path = "../oodle_loader", optional = true}
|
oodle_loader = { path = "../oodle_loader", optional = true}
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
sha1 = { workspace = true }
|
sha1 = { workspace = true }
|
||||||
|
|
|
@ -174,6 +174,7 @@ fn compress(compression: Compression, data: &[u8]) -> Result<Vec<u8>> {
|
||||||
compress.finish()?
|
compress.finish()?
|
||||||
}
|
}
|
||||||
Compression::Zstd => zstd::stream::encode_all(data, 0)?,
|
Compression::Zstd => zstd::stream::encode_all(data, 0)?,
|
||||||
|
Compression::LZ4 => lz4_flex::block::compress(data),
|
||||||
Compression::Oodle => {
|
Compression::Oodle => {
|
||||||
#[cfg(not(feature = "oodle"))]
|
#[cfg(not(feature = "oodle"))]
|
||||||
return Err(super::Error::Oodle);
|
return Err(super::Error::Oodle);
|
||||||
|
|
|
@ -376,7 +376,7 @@ impl Entry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "compression", feature = "oodle"))]
|
#[cfg(feature = "compression")]
|
||||||
let ranges = {
|
let ranges = {
|
||||||
let offset = |index: u64| -> usize {
|
let offset = |index: u64| -> usize {
|
||||||
(match version.version_major() >= VersionMajor::RelativeChunkOffsets {
|
(match version.version_major() >= VersionMajor::RelativeChunkOffsets {
|
||||||
|
@ -406,52 +406,46 @@ impl Entry {
|
||||||
|
|
||||||
match self.compression_slot.and_then(|c| compression[c as usize]) {
|
match self.compression_slot.and_then(|c| compression[c as usize]) {
|
||||||
None => buf.write_all(&data)?,
|
None => buf.write_all(&data)?,
|
||||||
#[cfg(feature = "compression")]
|
|
||||||
Some(Compression::Zlib) => decompress!(flate2::read::ZlibDecoder<&[u8]>),
|
|
||||||
#[cfg(feature = "compression")]
|
|
||||||
Some(Compression::Gzip) => decompress!(flate2::read::GzDecoder<&[u8]>),
|
|
||||||
#[cfg(feature = "compression")]
|
|
||||||
Some(Compression::Zstd) => {
|
|
||||||
for range in ranges {
|
|
||||||
io::copy(&mut zstd::stream::read::Decoder::new(&data[range])?, buf)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "oodle")]
|
|
||||||
Some(Compression::Oodle) => {
|
|
||||||
let mut decompressed = vec![0; self.uncompressed as usize];
|
|
||||||
|
|
||||||
let mut compress_offset = 0;
|
|
||||||
let mut decompress_offset = 0;
|
|
||||||
let block_count = ranges.len();
|
|
||||||
for range in ranges {
|
|
||||||
let decomp = if block_count == 1 {
|
|
||||||
self.uncompressed as usize
|
|
||||||
} else {
|
|
||||||
(self.compression_block_size as usize)
|
|
||||||
.min(self.uncompressed as usize - compress_offset)
|
|
||||||
};
|
|
||||||
let buffer = &mut data[range];
|
|
||||||
let out = oodle_loader::oodle()?.decompress(
|
|
||||||
buffer,
|
|
||||||
&mut decompressed[decompress_offset..decompress_offset + decomp],
|
|
||||||
);
|
|
||||||
if out == 0 {
|
|
||||||
return Err(super::Error::DecompressionFailed(Compression::Oodle));
|
|
||||||
}
|
|
||||||
compress_offset += self.compression_block_size as usize;
|
|
||||||
decompress_offset += out as usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert_eq!(
|
|
||||||
decompress_offset, self.uncompressed as usize,
|
|
||||||
"Oodle decompression length mismatch"
|
|
||||||
);
|
|
||||||
buf.write_all(&decompressed)?;
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "oodle"))]
|
|
||||||
Some(Compression::Oodle) => return Err(super::Error::Oodle),
|
|
||||||
#[cfg(not(feature = "compression"))]
|
#[cfg(not(feature = "compression"))]
|
||||||
_ => return Err(super::Error::Compression),
|
_ => return Err(super::Error::Compression),
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
|
Some(comp) => match comp {
|
||||||
|
Compression::Zlib => decompress!(flate2::read::ZlibDecoder<&[u8]>),
|
||||||
|
Compression::Gzip => decompress!(flate2::read::GzDecoder<&[u8]>),
|
||||||
|
Compression::Zstd => {
|
||||||
|
for range in ranges {
|
||||||
|
io::copy(&mut zstd::stream::read::Decoder::new(&data[range])?, buf)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Compression::LZ4 => {
|
||||||
|
let mut decompressed = vec![0; self.uncompressed as usize];
|
||||||
|
for (decomp_chunk, comp_range) in decompressed
|
||||||
|
.chunks_mut(self.compression_block_size as usize)
|
||||||
|
.zip(ranges)
|
||||||
|
{
|
||||||
|
lz4_flex::block::decompress_into(&data[comp_range], decomp_chunk)
|
||||||
|
.map_err(|_| Error::DecompressionFailed(Compression::LZ4))?;
|
||||||
|
}
|
||||||
|
buf.write_all(&decompressed)?;
|
||||||
|
}
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
|
Compression::Oodle => {
|
||||||
|
let mut decompressed = vec![0; self.uncompressed as usize];
|
||||||
|
for (decomp_chunk, comp_range) in decompressed
|
||||||
|
.chunks_mut(self.compression_block_size as usize)
|
||||||
|
.zip(ranges)
|
||||||
|
{
|
||||||
|
let out =
|
||||||
|
oodle_loader::oodle()?.decompress(&data[comp_range], decomp_chunk);
|
||||||
|
if out == 0 {
|
||||||
|
return Err(Error::DecompressionFailed(Compression::Oodle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.write_all(&decompressed)?;
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "oodle"))]
|
||||||
|
Compression::Oodle => return Err(super::Error::Oodle),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
buf.flush()?;
|
buf.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -119,6 +119,7 @@ pub enum Compression {
|
||||||
Gzip,
|
Gzip,
|
||||||
Oodle,
|
Oodle,
|
||||||
Zstd,
|
Zstd,
|
||||||
|
LZ4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
|
Loading…
Reference in a new issue