this repo has no description
0
fork

Configure Feed

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

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