this repo has no description
1use super::stream::{guard_file_output, open_input, open_output};
2use crate::{
3 progress::{ProgressArgs, copy_with_progress},
4 utils::*,
5};
6use clap::Args;
7use std::io;
8use xz2::read::XzDecoder;
9use xz2::write::XzEncoder;
10
11#[derive(Args, Debug)]
12pub struct XzArgs {
13 #[clap(flatten)]
14 pub common_args: CommonArgs,
15
16 #[clap(flatten)]
17 progress_args: ProgressArgs,
18
19 #[clap(flatten)]
20 pub level_args: LevelArgs,
21}
22
23pub struct Xz {
24 pub level: i32,
25 pub progress_args: ProgressArgs,
26}
27
28impl Default for Xz {
29 fn default() -> Self {
30 let validator = DefaultCompressionValidator;
31 Xz {
32 level: validator.default_level(),
33 progress_args: ProgressArgs::default(),
34 }
35 }
36}
37
38impl Xz {
39 pub fn new(args: &XzArgs) -> Xz {
40 Xz {
41 level: args.level_args.resolve(&DefaultCompressionValidator),
42 progress_args: args.progress_args,
43 }
44 }
45}
46
47impl Compressor for Xz {
48 /// The standard extension for the xz format.
49 fn extension(&self) -> &str {
50 "xz"
51 }
52
53 /// Full name for xz.
54 fn name(&self) -> &str {
55 "xz"
56 }
57
58 fn compress(&self, input: CmprssInput, output: CmprssOutput) -> Result {
59 guard_file_output(&output, "Xz")?;
60 let (mut input_stream, file_size) = open_input(input, "Xz")?;
61
62 if let CmprssOutput::Writer(writer) = output {
63 let mut encoder = XzEncoder::new(writer, self.level as u32);
64 io::copy(&mut input_stream, &mut encoder)?;
65 encoder.finish()?;
66 } else {
67 let output_stream = open_output(&output)?;
68 let mut encoder = XzEncoder::new(output_stream, self.level as u32);
69 copy_with_progress(
70 &mut input_stream,
71 &mut encoder,
72 self.progress_args.chunk_size.size_in_bytes,
73 file_size,
74 self.progress_args.progress,
75 &output,
76 )?;
77 }
78
79 Ok(())
80 }
81
82 fn extract(&self, input: CmprssInput, output: CmprssOutput) -> Result {
83 guard_file_output(&output, "Xz")?;
84 let (input_stream, file_size) = open_input(input, "Xz")?;
85 let mut decoder = XzDecoder::new(input_stream);
86
87 if let CmprssOutput::Writer(mut writer) = output {
88 io::copy(&mut decoder, &mut writer)?;
89 } else {
90 let mut output_stream = open_output(&output)?;
91 copy_with_progress(
92 &mut decoder,
93 &mut output_stream,
94 self.progress_args.chunk_size.size_in_bytes,
95 file_size,
96 self.progress_args.progress,
97 &output,
98 )?;
99 }
100
101 Ok(())
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::test_utils::*;
109
110 /// Test the basic interface of the Xz compressor
111 #[test]
112 fn test_xz_interface() {
113 let compressor = Xz::default();
114 test_compressor_interface(&compressor, "xz", Some("xz"));
115 }
116
117 /// Test the default compression level
118 #[test]
119 fn test_xz_default_compression() -> Result {
120 let compressor = Xz::default();
121 test_compression(&compressor)
122 }
123
124 /// Test fast compression level
125 #[test]
126 fn test_xz_fast_compression() -> Result {
127 let fast_compressor = Xz {
128 level: 1,
129 progress_args: ProgressArgs::default(),
130 };
131 test_compression(&fast_compressor)
132 }
133
134 /// Test best compression level
135 #[test]
136 fn test_xz_best_compression() -> Result {
137 let best_compressor = Xz {
138 level: 9,
139 progress_args: ProgressArgs::default(),
140 };
141 test_compression(&best_compressor)
142 }
143}