···1010use progress::ProgressDisplay;
1111use std::io;
1212use std::path::{Path, PathBuf};
1313+use std::str::FromStr;
1314use utils::*;
14151516/// A compression multi-tool
···4445 common_args: CommonArgs,
4546}
46474848+#[derive(Debug, Clone)]
4949+struct ChunkSize {
5050+ size_in_bytes: usize,
5151+}
5252+5353+impl FromStr for ChunkSize {
5454+ type Err = &'static str;
5555+5656+ fn from_str(s: &str) -> Result<Self, Self::Err> {
5757+ // Try to parse s as just a number
5858+ if let Ok(num) = s.parse::<usize>() {
5959+ return Ok(ChunkSize { size_in_bytes: num });
6060+ }
6161+ // Simplify so that we always assume base 2, regardless of whether we see
6262+ // 'kb' or 'kib'
6363+ let mut s = s.to_lowercase();
6464+ if s.ends_with("ib") {
6565+ s.truncate(s.len() - 2);
6666+ s.push('b');
6767+ };
6868+ let (num_str, unit) = s.split_at(s.len() - 2);
6969+ let num = num_str.parse::<usize>().map_err(|_| "Invalid number")?;
7070+7171+ let size_in_bytes = match unit {
7272+ "kb" => num * 1024,
7373+ "mb" => num * 1024 * 1024,
7474+ "gb" => num * 1024 * 1024 * 1024,
7575+ _ => return Err("Invalid unit"),
7676+ };
7777+7878+ Ok(ChunkSize { size_in_bytes })
7979+ }
8080+}
8181+4782#[derive(Args, Debug)]
4883struct ProgressArgs {
4984 /// Show progress.
5085 #[arg(long, value_enum, default_value = "auto")]
5186 progress: ProgressDisplay,
8787+8888+ /// Chunk size to use during the copy when showing the progress bar.
8989+ #[arg(long, default_value = "8kib")]
9090+ chunk_size: ChunkSize,
5291}
53925493#[derive(Args, Debug)]
···306345 xz::Xz {
307346 level: args.level,
308347 progress: args.progress_args.progress,
348348+ chunk_size: args.progress_args.chunk_size.size_in_bytes,
309349 }
310350}
311351
+6-4
src/xz.rs
···1111pub struct Xz {
1212 pub level: u32,
1313 pub progress: ProgressDisplay,
1414+ pub chunk_size: usize,
1415}
15161617impl Default for Xz {
···1819 Xz {
1920 level: 6,
2021 progress: ProgressDisplay::Auto,
2222+ chunk_size: 8192,
2123 }
2224 }
2325}
···5658 let mut encoder = XzEncoder::new(output_stream, self.level);
5759 let mut bar = progress_bar(file_size, self.progress, &output);
5860 if let Some(progress) = &mut bar {
5959- // Copy the input to the output in 8k chunks
6060- let mut buffer = [0; 8192];
6161+ // Copy the input to the output in chunks so that we can update the progress bar
6262+ let mut buffer = vec![0; self.chunk_size];
6163 loop {
6264 let bytes_read = input_stream.read(&mut buffer)?;
6365 if bytes_read == 0 {
···99101 let mut decoder = XzDecoder::new(output_stream);
100102 let mut bar = progress_bar(file_size, self.progress, &output);
101103 if let Some(progress) = &mut bar {
102102- // Copy the input to the output in 8k chunks
103103- let mut buffer = [0; 8192];
104104+ // Copy the input to the output in chunks so that we can update the progress bar
105105+ let mut buffer = vec![0; self.chunk_size];
104106 loop {
105107 let bytes_read = input_stream.read(&mut buffer)?;
106108 if bytes_read == 0 {