diff --git a/src/cli/args.rs b/src/cli/args.rs index a200dc6..5183e59 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -44,6 +44,10 @@ pub struct CliArgs { /// Ouch and claps subcommands #[command(subcommand)] pub cmd: Subcommand, + + /// Compression raw level as each algo has + #[arg(short = 'r', long, global = true, default_value_t = u32::MAX)] + pub raw_level: u32, } #[derive(Parser, PartialEq, Eq, Debug)] diff --git a/src/commands/compress.rs b/src/commands/compress.rs index fb69a75..e0dee06 100644 --- a/src/commands/compress.rs +++ b/src/commands/compress.rs @@ -31,6 +31,7 @@ pub fn compress_files( quiet: bool, question_policy: QuestionPolicy, file_visibility_policy: FileVisibilityPolicy, + raw_level: u32, ) -> crate::Result { // If the input files contain a directory, then the total size will be underestimated let file_writer = BufWriter::with_capacity(BUFFER_CAPACITY, output_file); @@ -43,20 +44,73 @@ pub fn compress_files( Gzip => Box::new( // by default, ParCompress uses a default compression level of 3 // instead of the regular default that flate2 uses - gzp::par::compress::ParCompress::::builder() - .compression_level(Default::default()) - .from_writer(encoder), + if raw_level == u32::MAX { + gzp::par::compress::ParCompress::::builder() + .compression_level(Default::default()) + .from_writer(encoder) + } else { + gzp::par::compress::ParCompress::::builder() + .compression_level(gzp::par::compress::Compression::new(raw_level)) + .from_writer(encoder) + }, ), - 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(gzp::par::compress::ParCompress::::builder().from_writer(encoder)), + Bzip => { + if raw_level == u32::MAX { + Box::new(bzip2::write::BzEncoder::new(encoder, Default::default())) + } else { + Box::new(bzip2::write::BzEncoder::new( + encoder, + bzip2::Compression::new(raw_level), + )) + } + } + Lz4 => { + if raw_level == u32::MAX { + Box::new(lzzzz::lz4f::WriteCompressor::new(encoder, Default::default())?) + } else { + Box::new(lzzzz::lz4f::WriteCompressor::new( + encoder, + lzzzz::lz4f::PreferencesBuilder::new() + .compression_level(raw_level as i32) + .build(), + )?) + } + } + Lzma => { + if raw_level == u32::MAX { + Box::new(xz2::write::XzEncoder::new(encoder, 6)) + } else { + Box::new(xz2::write::XzEncoder::new(encoder, raw_level)) + } + } + Snappy => { + if raw_level == u32::MAX { + Box::new(gzp::par::compress::ParCompress::::builder().from_writer(encoder)) + } else { + Box::new( + gzp::par::compress::ParCompress::::builder() + .compression_level(gzp::par::compress::Compression::new(raw_level)) + .from_writer(encoder), + ) + } + } Zstd => { - let zstd_encoder = zstd::stream::write::Encoder::new(encoder, Default::default()); + if raw_level == u32::MAX { + Box::new( + zstd::stream::write::Encoder::new(encoder, Default::default()) + .unwrap() + .auto_finish(), + ) + } else { + Box::new( + zstd::stream::write::Encoder::new(encoder, raw_level as i32) + .unwrap() + .auto_finish(), + ) + } // Safety: // Encoder::new() can only fail if `level` is invalid, but Default::default() // is guaranteed to be valid - Box::new(zstd_encoder.unwrap().auto_finish()) } Tar | Zip => unreachable!(), }; diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a96983d..d2f0eb7 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -80,6 +80,7 @@ pub fn run( args.quiet, question_policy, file_visibility_policy, + args.raw_level, ); if let Ok(true) = compress_result {