feat: Add listing and decompressing support for lzip

This commit is contained in:
Mathias Zhang 2025-07-03 19:17:03 +08:00
parent 16a1c308b4
commit 2216764e1d
No known key found for this signature in database
5 changed files with 24 additions and 3 deletions

View File

@ -75,6 +75,9 @@ pub fn compress_files(
encoder, encoder,
level.map_or(6, |l| (l as u32).clamp(0, 9)), level.map_or(6, |l| (l as u32).clamp(0, 9)),
)), )),
Lzip => return Err(crate::Error::UnsupportedFormat {
reason: "Lzip compression is not supported in ouch.".to_string(),
}),
Snappy => Box::new( Snappy => Box::new(
gzp::par::compress::ParCompress::<gzp::snap::Snap>::builder() gzp::par::compress::ParCompress::<gzp::snap::Snap>::builder()
.compression_level(gzp::par::compress::Compression::new( .compression_level(gzp::par::compress::Compression::new(
@ -111,7 +114,7 @@ pub fn compress_files(
} }
match first_format { match first_format {
Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Snappy | Zstd | Brotli => { Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Lzip | Snappy | Zstd | Brotli => {
writer = chain_writer_encoder(&first_format, writer)?; writer = chain_writer_encoder(&first_format, writer)?;
let mut reader = fs::File::open(&files[0])?; let mut reader = fs::File::open(&files[0])?;

View File

@ -132,6 +132,10 @@ pub fn decompress_file(options: DecompressOptions) -> crate::Result<()> {
liblzma::stream::Stream::new_lzma_decoder(u64::MAX).unwrap() liblzma::stream::Stream::new_lzma_decoder(u64::MAX).unwrap()
)), )),
Xz => Box::new(liblzma::read::XzDecoder::new(decoder)), Xz => Box::new(liblzma::read::XzDecoder::new(decoder)),
Lzip => Box::new(liblzma::read::XzDecoder::new_stream(
decoder,
liblzma::stream::Stream::new_lzip_decoder(u64::MAX, 0).unwrap(),
)),
Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)),
Zstd => Box::new(zstd::stream::Decoder::new(decoder)?), Zstd => Box::new(zstd::stream::Decoder::new(decoder)?),
Brotli => Box::new(brotli::Decompressor::new(decoder, BUFFER_CAPACITY)), Brotli => Box::new(brotli::Decompressor::new(decoder, BUFFER_CAPACITY)),
@ -147,7 +151,7 @@ pub fn decompress_file(options: DecompressOptions) -> crate::Result<()> {
} }
let files_unpacked = match first_extension { let files_unpacked = match first_extension {
Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Snappy | Zstd | Brotli => { Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Lzip | Snappy | Zstd | Brotli => {
reader = chain_reader_decoder(&first_extension, reader)?; reader = chain_reader_decoder(&first_extension, reader)?;
let mut writer = match utils::ask_to_create_file( let mut writer = match utils::ask_to_create_file(

View File

@ -62,6 +62,10 @@ pub fn list_archive_contents(
liblzma::stream::Stream::new_lzma_decoder(u64::MAX).unwrap(), liblzma::stream::Stream::new_lzma_decoder(u64::MAX).unwrap(),
)), )),
Xz => Box::new(liblzma::read::XzDecoder::new(decoder)), Xz => Box::new(liblzma::read::XzDecoder::new(decoder)),
Lzip => Box::new(liblzma::read::XzDecoder::new_stream(
decoder,
liblzma::stream::Stream::new_lzip_decoder(u64::MAX, 0).unwrap(),
)),
Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), Snappy => Box::new(snap::read::FrameDecoder::new(decoder)),
Zstd => Box::new(zstd::stream::Decoder::new(decoder)?), Zstd => Box::new(zstd::stream::Decoder::new(decoder)?),
Brotli => Box::new(brotli::Decompressor::new(decoder, BUFFER_CAPACITY)), Brotli => Box::new(brotli::Decompressor::new(decoder, BUFFER_CAPACITY)),
@ -131,7 +135,7 @@ pub fn list_archive_contents(
Box::new(archive::sevenz::list_archive(io::Cursor::new(vec), password)?) Box::new(archive::sevenz::list_archive(io::Cursor::new(vec), password)?)
} }
Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Snappy | Zstd | Brotli => { Gzip | Bzip | Bzip3 | Lz4 | Lzma | Xz | Lzip | Snappy | Zstd | Brotli => {
unreachable!("Not an archive, should be validated before calling this function."); unreachable!("Not an archive, should be validated before calling this function.");
} }
}; };

View File

@ -89,6 +89,8 @@ pub enum CompressionFormat {
Xz, Xz,
/// .lzma /// .lzma
Lzma, Lzma,
/// .lzip
Lzip,
/// .sz /// .sz
Snappy, Snappy,
/// tar, tgz, tbz, tbz2, tbz3, txz, tlz4, tlzma, tsz, tzst /// tar, tgz, tbz, tbz2, tbz3, txz, tlz4, tlzma, tsz, tzst
@ -118,6 +120,7 @@ impl CompressionFormat {
Lz4 => false, Lz4 => false,
Lzma => false, Lzma => false,
Xz => false, Xz => false,
Lzip => false,
Snappy => false, Snappy => false,
Zstd => false, Zstd => false,
Brotli => false, Brotli => false,
@ -135,6 +138,7 @@ fn to_extension(ext: &[u8]) -> Option<Extension> {
b"tlz4" => &[Tar, Lz4], b"tlz4" => &[Tar, Lz4],
b"txz" => &[Tar, Xz], b"txz" => &[Tar, Xz],
b"tlzma" => &[Tar, Lzma], b"tlzma" => &[Tar, Lzma],
b"tlz" => &[Tar, Lzip],
b"tsz" => &[Tar, Snappy], b"tsz" => &[Tar, Snappy],
b"tzst" => &[Tar, Zstd], b"tzst" => &[Tar, Zstd],
b"zip" => &[Zip], b"zip" => &[Zip],
@ -144,6 +148,7 @@ fn to_extension(ext: &[u8]) -> Option<Extension> {
b"lz4" => &[Lz4], b"lz4" => &[Lz4],
b"xz" => &[Xz], b"xz" => &[Xz],
b"lzma" => &[Lzma], b"lzma" => &[Lzma],
b"lz" => &[Lzip],
b"sz" => &[Snappy], b"sz" => &[Snappy],
b"zst" => &[Zstd], b"zst" => &[Zstd],
b"rar" => &[Rar], b"rar" => &[Rar],

View File

@ -144,6 +144,9 @@ pub fn try_infer_extension(path: &Path) -> Option<Extension> {
fn is_xz(buf: &[u8]) -> bool { fn is_xz(buf: &[u8]) -> bool {
buf.starts_with(&[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00]) buf.starts_with(&[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])
} }
fn is_lzip(buf: &[u8]) -> bool {
buf.starts_with(&[0x4C, 0x5A, 0x49, 0x50])
}
fn is_lz4(buf: &[u8]) -> bool { fn is_lz4(buf: &[u8]) -> bool {
buf.starts_with(&[0x04, 0x22, 0x4D, 0x18]) buf.starts_with(&[0x04, 0x22, 0x4D, 0x18])
} }
@ -193,6 +196,8 @@ pub fn try_infer_extension(path: &Path) -> Option<Extension> {
Some(Extension::new(&[Lzma], "lzma")) Some(Extension::new(&[Lzma], "lzma"))
} else if is_xz(&buf) { } else if is_xz(&buf) {
Some(Extension::new(&[Xz], "xz")) Some(Extension::new(&[Xz], "xz"))
} else if is_lzip(&buf) {
Some(Extension::new(&[Lzip], "lzip"))
} else if is_lz4(&buf) { } else if is_lz4(&buf) {
Some(Extension::new(&[Lz4], "lz4")) Some(Extension::new(&[Lz4], "lz4"))
} else if is_sz(&buf) { } else if is_sz(&buf) {