this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at f7bbb7638e8ed85d5c92d23cfdcf38ed665b3b21 182 lines 5.0 kB view raw
1use super::stream::{guard_file_output, open_input, open_output}; 2use crate::progress::{ProgressArgs, copy_with_progress}; 3use crate::utils::*; 4use clap::Args; 5use std::io; 6use zstd::stream::{read::Decoder, write::Encoder}; 7 8/// Zstd-specific compression validator (-7 to 22 range) 9#[derive(Debug, Clone, Copy)] 10pub struct ZstdCompressionValidator; 11 12impl CompressionLevelValidator for ZstdCompressionValidator { 13 fn min_level(&self) -> i32 { 14 -7 15 } 16 fn max_level(&self) -> i32 { 17 22 18 } 19 fn default_level(&self) -> i32 { 20 1 21 } 22 23 fn name_to_level(&self, name: &str) -> Option<i32> { 24 match name.to_lowercase().as_str() { 25 "none" => Some(-7), 26 "fast" => Some(1), 27 "best" => Some(22), 28 _ => None, 29 } 30 } 31} 32 33#[derive(Args, Debug)] 34pub struct ZstdArgs { 35 #[clap(flatten)] 36 pub common_args: CommonArgs, 37 38 #[clap(flatten)] 39 pub level_args: LevelArgs, 40 41 #[clap(flatten)] 42 pub progress_args: ProgressArgs, 43} 44 45pub struct Zstd { 46 pub compression_level: i32, 47 pub progress_args: ProgressArgs, 48} 49 50impl Default for Zstd { 51 fn default() -> Self { 52 let validator = ZstdCompressionValidator; 53 Zstd { 54 compression_level: validator.default_level(), 55 progress_args: ProgressArgs::default(), 56 } 57 } 58} 59 60impl Zstd { 61 pub fn new(args: &ZstdArgs) -> Zstd { 62 Zstd { 63 compression_level: args.level_args.resolve(&ZstdCompressionValidator), 64 progress_args: args.progress_args, 65 } 66 } 67} 68 69impl Compressor for Zstd { 70 /// The standard extension for the zstd format. 71 fn extension(&self) -> &str { 72 "zst" 73 } 74 75 /// Full name for zstd. 76 fn name(&self) -> &str { 77 "zstd" 78 } 79 80 /// Compress an input file or pipe to a zstd archive 81 fn compress(&self, input: CmprssInput, output: CmprssOutput) -> Result { 82 guard_file_output(&output, "Zstd")?; 83 let (mut input_stream, file_size) = open_input(input, "Zstd")?; 84 85 if let CmprssOutput::Writer(writer) = output { 86 let mut encoder = Encoder::new(writer, self.compression_level)?; 87 io::copy(&mut input_stream, &mut encoder)?; 88 encoder.finish()?; 89 } else { 90 let output_stream = open_output(&output)?; 91 let mut encoder = Encoder::new(output_stream, self.compression_level)?; 92 copy_with_progress( 93 &mut input_stream, 94 &mut encoder, 95 self.progress_args.chunk_size.size_in_bytes, 96 file_size, 97 self.progress_args.progress, 98 &output, 99 )?; 100 encoder.finish()?; 101 } 102 103 Ok(()) 104 } 105 106 /// Extract a zstd archive to an output file or pipe 107 fn extract(&self, input: CmprssInput, output: CmprssOutput) -> Result { 108 guard_file_output(&output, "Zstd")?; 109 let (input_stream, file_size) = open_input(input, "Zstd")?; 110 let mut decoder = Decoder::new(input_stream)?; 111 112 if let CmprssOutput::Writer(mut writer) = output { 113 io::copy(&mut decoder, &mut writer)?; 114 } else { 115 let mut output_stream = open_output(&output)?; 116 copy_with_progress( 117 &mut decoder, 118 &mut output_stream, 119 self.progress_args.chunk_size.size_in_bytes, 120 file_size, 121 self.progress_args.progress, 122 &output, 123 )?; 124 } 125 126 Ok(()) 127 } 128} 129 130#[cfg(test)] 131mod tests { 132 use super::*; 133 use crate::test_utils::*; 134 135 /// Test the basic interface of the Zstd compressor 136 #[test] 137 fn test_zstd_interface() { 138 let compressor = Zstd::default(); 139 test_compressor_interface(&compressor, "zstd", Some("zst")); 140 } 141 142 /// Test the default compression level 143 #[test] 144 fn test_zstd_default_compression() -> Result { 145 let compressor = Zstd::default(); 146 test_compression(&compressor) 147 } 148 149 /// Test fast compression level 150 #[test] 151 fn test_zstd_fast_compression() -> Result { 152 let fast_compressor = Zstd { 153 compression_level: 1, 154 progress_args: ProgressArgs::default(), 155 }; 156 test_compression(&fast_compressor) 157 } 158 159 /// Test best compression level 160 #[test] 161 fn test_zstd_best_compression() -> Result { 162 let best_compressor = Zstd { 163 compression_level: 22, 164 progress_args: ProgressArgs::default(), 165 }; 166 test_compression(&best_compressor) 167 } 168 169 #[test] 170 fn test_zstd_compression_validator() { 171 let validator = ZstdCompressionValidator; 172 test_compression_validator_helper( 173 &validator, 174 -7, // min_level 175 22, // max_level 176 1, // default_level 177 Some(1), // fast_name_level 178 Some(22), // best_name_level 179 Some(-7), // none_name_level 180 ); 181 } 182}