From 52a8acf2e12872b976a876ba99d968504a8f2c80 Mon Sep 17 00:00:00 2001 From: figsoda Date: Tue, 7 Dec 2021 13:59:56 -0500 Subject: [PATCH] support snappy format --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + README.md | 8 ++++---- src/commands.rs | 9 ++++++--- src/extension.rs | 10 ++++++++-- src/utils/fs.rs | 5 +++++ tests/integration.rs | 3 ++- tests/mime.rs | 3 +-- 8 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71973e4..b72af88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -454,6 +454,7 @@ dependencies = [ "parse-display", "proptest", "rand", + "snap", "tar", "tempfile", "test-strategy", @@ -713,6 +714,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "snap" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451" + [[package]] name = "strsim" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index cce5e77..47f764a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ libc = "0.2.103" linked-hash-map = "0.5.4" lzzzz = "0.8.0" once_cell = "1.8.0" +snap = "1.0.5" tar = "0.4.37" walkdir = "2.3.2" xz2 = "0.1.6" diff --git a/README.md b/README.md index d127062..b99f0c7 100644 --- a/README.md +++ b/README.md @@ -72,11 +72,11 @@ ouch c file.txt file.zip # Supported formats -| Format | `.tar` | `.zip` | `.bz`, `.bz2` | `.gz` | `.lz4` | `.xz`, `.lzma` | `.zst` | -|:---------:|:------:|:------:|:-------------:|:-----:|:------:|:---------------------:|:------:| -| Supported | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Format | `.tar` | `.zip` | `.bz`, `.bz2` | `.gz` | `.lz4` | `.xz`, `.lzma` | `.sz` | `.zst` | +|:---------:|:------:|:------:|:-------------:|:-----:|:------:|:--------------:|:-----:|:-------| +| Supported | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -And the aliases: `tgz`, `tbz`, `tbz2`, `tlz4`, `txz`, `tlz`, `tlzma`, `tzst`. +And the aliases: `tgz`, `tbz`, `tbz2`, `tlz4`, `txz`, `tlzma`, `tsz`, `tzst`. Formats can be chained: diff --git a/src/commands.rs b/src/commands.rs index f403c8b..5700bd9 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -304,6 +304,7 @@ fn compress_files(files: Vec, formats: Vec, output_file: fs: Bzip => Box::new(bzip2::write::BzEncoder::new(encoder, Default::default())), Lz4 => Box::new(lzzzz::lz4f::WriteCompressor::new(encoder, Default::default())?), Lzma => Box::new(xz2::write::XzEncoder::new(encoder, 6)), + Snappy => Box::new(snap::write::FrameEncoder::new(encoder)), Zstd => { let zstd_encoder = zstd::stream::write::Encoder::new(encoder, Default::default()); // Safety: @@ -321,7 +322,7 @@ fn compress_files(files: Vec, formats: Vec, output_file: fs: } match formats[0].compression_formats[0] { - Gzip | Bzip | Lz4 | Lzma | Zstd => { + Gzip | Bzip | Lz4 | Lzma | Snappy | Zstd => { let _progress = Progress::new_accessible_aware( total_input_size, precise, @@ -454,6 +455,7 @@ fn decompress_file( Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), Lz4 => Box::new(lzzzz::lz4f::ReadDecompressor::new(decoder)?), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), + Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), Zstd => Box::new(zstd::stream::Decoder::new(decoder)?), Tar | Zip => unreachable!(), }; @@ -466,7 +468,7 @@ fn decompress_file( let files_unpacked; match formats[0].compression_formats[0] { - Gzip | Bzip | Lz4 | Lzma | Zstd => { + Gzip | Bzip | Lz4 | Lzma | Snappy | Zstd => { reader = chain_reader_decoder(&formats[0].compression_formats[0], reader)?; let writer = utils::create_or_ask_overwrite(&output_file_path, question_policy)?; @@ -580,6 +582,7 @@ fn list_archive_contents( Bzip => Box::new(bzip2::read::BzDecoder::new(decoder)), Lz4 => Box::new(lzzzz::lz4f::ReadDecompressor::new(decoder)?), Lzma => Box::new(xz2::read::XzDecoder::new(decoder)), + Snappy => Box::new(snap::read::FrameDecoder::new(decoder)), Zstd => Box::new(zstd::stream::Decoder::new(decoder)?), Tar | Zip => unreachable!(), }; @@ -604,7 +607,7 @@ fn list_archive_contents( crate::archive::zip::list_archive(zip_archive)? } - Gzip | Bzip | Lz4 | Lzma | Zstd => { + Gzip | Bzip | Lz4 | Lzma | Snappy | Zstd => { panic!("Not an archive! This should never happen, if it does, something is wrong with `CompressionFormat::is_archive()`. Please report this error!"); } }; diff --git a/src/extension.rs b/src/extension.rs index d027876..e8807d0 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -57,7 +57,9 @@ pub enum CompressionFormat { Lz4, /// .xz .lzma Lzma, - /// tar, tgz, tbz, tbz2, txz, tlz, tlz4, tlzma, tzst + /// .sz + Snappy, + /// tar, tgz, tbz, tbz2, txz, tlz4, tlzma, tsz, tzst Tar, /// .zst Zstd, @@ -75,6 +77,7 @@ impl CompressionFormat { Bzip => false, Lz4 => false, Lzma => false, + Snappy => false, Zstd => false, } } @@ -91,6 +94,7 @@ impl fmt::Display for CompressionFormat { Zstd => ".zst", Lz4 => ".lz4", Lzma => ".lz", + Snappy => ".sz", Tar => ".tar", Zip => ".zip", } @@ -121,13 +125,15 @@ pub fn separate_known_extensions_from_name(mut path: &Path) -> (&Path, Vec &[Tar, Gzip], "tbz" | "tbz2" => &[Tar, Bzip], "tlz4" => &[Tar, Lz4], - "txz" | "tlz" | "tlzma" => &[Tar, Lzma], + "txz" | "tlzma" => &[Tar, Lzma], + "tsz" => &[Tar, Snappy], "tzst" => &[Tar, Zstd], "zip" => &[Zip], "bz" | "bz2" => &[Bzip], "gz" => &[Gzip], "lz4" => &[Lz4], "xz" | "lzma" => &[Lzma], + "sz" => &[Snappy], "zst" => &[Zstd], _ => break, }; diff --git a/src/utils/fs.rs b/src/utils/fs.rs index 1dd38e0..9adc946 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -83,6 +83,9 @@ pub fn try_infer_extension(path: &Path) -> Option { fn is_lz4(buf: &[u8]) -> bool { buf.starts_with(&[0x04, 0x22, 0x4D, 0x18]) } + fn is_sz(buf: &[u8]) -> bool { + buf.starts_with(&[0xFF, 0x06, 0x00, 0x00, 0x73, 0x4E, 0x61, 0x50, 0x70, 0x59]) + } fn is_zst(buf: &[u8]) -> bool { buf.starts_with(&[0x28, 0xB5, 0x2F, 0xFD]) } @@ -113,6 +116,8 @@ pub fn try_infer_extension(path: &Path) -> Option { Some(Extension::new(&[Lzma], "xz")) } else if is_lz4(&buf) { Some(Extension::new(&[Lz4], "lz4")) + } else if is_sz(&buf) { + Some(Extension::new(&[Snappy], "sz")) } else if is_zst(&buf) { Some(Extension::new(&[Zstd], "zst")) } else { diff --git a/tests/integration.rs b/tests/integration.rs index 49c2a27..0519c60 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -20,8 +20,8 @@ enum DirectoryExtension { Tbz, Tgz, Tlz4, - Tlz, Tlzma, + Tsz, Txz, Zip, } @@ -35,6 +35,7 @@ enum FileExtension { Gz, Lz4, Lzma, + Sz, Xz, } diff --git a/tests/mime.rs b/tests/mime.rs index 0ec73aa..62fe21a 100644 --- a/tests/mime.rs +++ b/tests/mime.rs @@ -17,7 +17,7 @@ fn sanity_check_through_mime() { write_random_content(test_file, &mut SmallRng::from_entropy()); let formats = [ - "tar", "zip", "tar.gz", "tgz", "tbz", "tbz2", "txz", "tlz", "tlzma", "tzst", "tar.bz", "tar.bz2", "tar.lzma", + "tar", "zip", "tar.gz", "tgz", "tbz", "tbz2", "txz", "tlzma", "tzst", "tar.bz", "tar.bz2", "tar.lzma", "tar.xz", "tar.zst", ]; @@ -30,7 +30,6 @@ fn sanity_check_through_mime() { "application/x-bzip2", "application/x-xz", "application/x-xz", - "application/x-xz", "application/zstd", "application/x-bzip2", "application/x-bzip2",