mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-31 13:07:46 +00:00
Fix type-error when calling parse_size
from split
This commit is contained in:
parent
8535cd41e0
commit
159a1dc1db
1 changed files with 35 additions and 37 deletions
|
@ -14,9 +14,11 @@ mod platform;
|
||||||
use crate::filenames::FilenameIterator;
|
use crate::filenames::FilenameIterator;
|
||||||
use crate::filenames::SuffixType;
|
use crate::filenames::SuffixType;
|
||||||
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
|
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::{metadata, File};
|
use std::fs::{metadata, File};
|
||||||
|
use std::io;
|
||||||
use std::io::{stdin, BufReader, BufWriter, ErrorKind, Read, Write};
|
use std::io::{stdin, BufReader, BufWriter, ErrorKind, Read, Write};
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -175,17 +177,17 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||||
/// The strategy for breaking up the input file into chunks.
|
/// The strategy for breaking up the input file into chunks.
|
||||||
enum Strategy {
|
enum Strategy {
|
||||||
/// Each chunk has the specified number of lines.
|
/// Each chunk has the specified number of lines.
|
||||||
Lines(usize),
|
Lines(u64),
|
||||||
|
|
||||||
/// Each chunk has the specified number of bytes.
|
/// Each chunk has the specified number of bytes.
|
||||||
Bytes(usize),
|
Bytes(u64),
|
||||||
|
|
||||||
/// Each chunk has as many lines as possible without exceeding the
|
/// Each chunk has as many lines as possible without exceeding the
|
||||||
/// specified number of bytes.
|
/// specified number of bytes.
|
||||||
LineBytes(usize),
|
LineBytes(u64),
|
||||||
|
|
||||||
/// Split the file into this many chunks.
|
/// Split the file into this many chunks.
|
||||||
Number(usize),
|
Number(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error when parsing a chunking strategy from command-line arguments.
|
/// An error when parsing a chunking strategy from command-line arguments.
|
||||||
|
@ -246,7 +248,7 @@ impl Strategy {
|
||||||
}
|
}
|
||||||
(0, 0, 0, 1) => {
|
(0, 0, 0, 1) => {
|
||||||
let s = matches.value_of(OPT_NUMBER).unwrap();
|
let s = matches.value_of(OPT_NUMBER).unwrap();
|
||||||
let n = s.parse::<usize>().map_err(StrategyError::NumberOfChunks)?;
|
let n = s.parse::<u64>().map_err(StrategyError::NumberOfChunks)?;
|
||||||
Ok(Self::Number(n))
|
Ok(Self::Number(n))
|
||||||
}
|
}
|
||||||
_ => Err(StrategyError::MultipleWays),
|
_ => Err(StrategyError::MultipleWays),
|
||||||
|
@ -399,17 +401,17 @@ struct ByteChunkWriter<'a> {
|
||||||
settings: &'a Settings,
|
settings: &'a Settings,
|
||||||
|
|
||||||
/// The maximum number of bytes allowed for a single chunk of output.
|
/// The maximum number of bytes allowed for a single chunk of output.
|
||||||
chunk_size: usize,
|
chunk_size: u64,
|
||||||
|
|
||||||
/// Running total of number of chunks that have been completed.
|
/// Running total of number of chunks that have been completed.
|
||||||
num_chunks_written: usize,
|
num_chunks_written: u64,
|
||||||
|
|
||||||
/// Remaining capacity in number of bytes in the current chunk.
|
/// Remaining capacity in number of bytes in the current chunk.
|
||||||
///
|
///
|
||||||
/// This number starts at `chunk_size` and decreases as bytes are
|
/// This number starts at `chunk_size` and decreases as bytes are
|
||||||
/// written. Once it reaches zero, a writer for a new chunk is
|
/// written. Once it reaches zero, a writer for a new chunk is
|
||||||
/// initialized and this number gets reset to `chunk_size`.
|
/// initialized and this number gets reset to `chunk_size`.
|
||||||
num_bytes_remaining_in_current_chunk: usize,
|
num_bytes_remaining_in_current_chunk: u64,
|
||||||
|
|
||||||
/// The underlying writer for the current chunk.
|
/// The underlying writer for the current chunk.
|
||||||
///
|
///
|
||||||
|
@ -423,7 +425,7 @@ struct ByteChunkWriter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ByteChunkWriter<'a> {
|
impl<'a> ByteChunkWriter<'a> {
|
||||||
fn new(chunk_size: usize, settings: &'a Settings) -> Option<ByteChunkWriter<'a>> {
|
fn new(chunk_size: u64, settings: &'a Settings) -> Option<ByteChunkWriter<'a>> {
|
||||||
let mut filename_iterator = FilenameIterator::new(
|
let mut filename_iterator = FilenameIterator::new(
|
||||||
&settings.prefix,
|
&settings.prefix,
|
||||||
&settings.additional_suffix,
|
&settings.additional_suffix,
|
||||||
|
@ -453,7 +455,7 @@ impl<'a> Write for ByteChunkWriter<'a> {
|
||||||
// different underlying writers. In that case, each iteration of
|
// different underlying writers. In that case, each iteration of
|
||||||
// this loop writes to the underlying writer that corresponds to
|
// this loop writes to the underlying writer that corresponds to
|
||||||
// the current chunk number.
|
// the current chunk number.
|
||||||
let mut carryover_bytes_written = 0;
|
let mut carryover_bytes_written: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
if buf.is_empty() {
|
if buf.is_empty() {
|
||||||
return Ok(carryover_bytes_written);
|
return Ok(carryover_bytes_written);
|
||||||
|
@ -464,19 +466,23 @@ impl<'a> Write for ByteChunkWriter<'a> {
|
||||||
// write enough bytes to fill the current chunk, then increment
|
// write enough bytes to fill the current chunk, then increment
|
||||||
// the chunk number and repeat.
|
// the chunk number and repeat.
|
||||||
let n = buf.len();
|
let n = buf.len();
|
||||||
if n < self.num_bytes_remaining_in_current_chunk {
|
if (n as u64) < self.num_bytes_remaining_in_current_chunk {
|
||||||
let num_bytes_written = self.inner.write(buf)?;
|
let num_bytes_written = self.inner.write(buf)?;
|
||||||
self.num_bytes_remaining_in_current_chunk -= num_bytes_written;
|
self.num_bytes_remaining_in_current_chunk -= num_bytes_written as u64;
|
||||||
return Ok(carryover_bytes_written + num_bytes_written);
|
return Ok(carryover_bytes_written + num_bytes_written);
|
||||||
} else {
|
} else {
|
||||||
// Write enough bytes to fill the current chunk.
|
// Write enough bytes to fill the current chunk.
|
||||||
let i = self.num_bytes_remaining_in_current_chunk;
|
//
|
||||||
|
// Conversion to usize is safe because we checked that
|
||||||
|
// self.num_bytes_remaining_in_current_chunk is lower than
|
||||||
|
// n, which is already usize.
|
||||||
|
let i = self.num_bytes_remaining_in_current_chunk as usize;
|
||||||
let num_bytes_written = self.inner.write(&buf[..i])?;
|
let num_bytes_written = self.inner.write(&buf[..i])?;
|
||||||
|
|
||||||
// It's possible that the underlying writer did not
|
// It's possible that the underlying writer did not
|
||||||
// write all the bytes.
|
// write all the bytes.
|
||||||
if num_bytes_written < i {
|
if num_bytes_written < i {
|
||||||
self.num_bytes_remaining_in_current_chunk -= num_bytes_written;
|
self.num_bytes_remaining_in_current_chunk -= num_bytes_written as u64;
|
||||||
return Ok(carryover_bytes_written + num_bytes_written);
|
return Ok(carryover_bytes_written + num_bytes_written);
|
||||||
} else {
|
} else {
|
||||||
// Move the window to look at only the remaining bytes.
|
// Move the window to look at only the remaining bytes.
|
||||||
|
@ -527,17 +533,17 @@ struct LineChunkWriter<'a> {
|
||||||
settings: &'a Settings,
|
settings: &'a Settings,
|
||||||
|
|
||||||
/// The maximum number of lines allowed for a single chunk of output.
|
/// The maximum number of lines allowed for a single chunk of output.
|
||||||
chunk_size: usize,
|
chunk_size: u64,
|
||||||
|
|
||||||
/// Running total of number of chunks that have been completed.
|
/// Running total of number of chunks that have been completed.
|
||||||
num_chunks_written: usize,
|
num_chunks_written: u64,
|
||||||
|
|
||||||
/// Remaining capacity in number of lines in the current chunk.
|
/// Remaining capacity in number of lines in the current chunk.
|
||||||
///
|
///
|
||||||
/// This number starts at `chunk_size` and decreases as lines are
|
/// This number starts at `chunk_size` and decreases as lines are
|
||||||
/// written. Once it reaches zero, a writer for a new chunk is
|
/// written. Once it reaches zero, a writer for a new chunk is
|
||||||
/// initialized and this number gets reset to `chunk_size`.
|
/// initialized and this number gets reset to `chunk_size`.
|
||||||
num_lines_remaining_in_current_chunk: usize,
|
num_lines_remaining_in_current_chunk: u64,
|
||||||
|
|
||||||
/// The underlying writer for the current chunk.
|
/// The underlying writer for the current chunk.
|
||||||
///
|
///
|
||||||
|
@ -551,7 +557,7 @@ struct LineChunkWriter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LineChunkWriter<'a> {
|
impl<'a> LineChunkWriter<'a> {
|
||||||
fn new(chunk_size: usize, settings: &'a Settings) -> Option<LineChunkWriter<'a>> {
|
fn new(chunk_size: u64, settings: &'a Settings) -> Option<LineChunkWriter<'a>> {
|
||||||
let mut filename_iterator = FilenameIterator::new(
|
let mut filename_iterator = FilenameIterator::new(
|
||||||
&settings.prefix,
|
&settings.prefix,
|
||||||
&settings.additional_suffix,
|
&settings.additional_suffix,
|
||||||
|
@ -632,7 +638,7 @@ impl<'a> Write for LineChunkWriter<'a> {
|
||||||
fn split_into_n_chunks_by_byte<R>(
|
fn split_into_n_chunks_by_byte<R>(
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
num_chunks: usize,
|
num_chunks: u64,
|
||||||
) -> UResult<()>
|
) -> UResult<()>
|
||||||
where
|
where
|
||||||
R: Read,
|
R: Read,
|
||||||
|
@ -648,16 +654,20 @@ where
|
||||||
// files.
|
// files.
|
||||||
let metadata = metadata(&settings.input).unwrap();
|
let metadata = metadata(&settings.input).unwrap();
|
||||||
let num_bytes = metadata.len();
|
let num_bytes = metadata.len();
|
||||||
let will_have_empty_files = settings.elide_empty_files && num_chunks as u64 > num_bytes;
|
let will_have_empty_files = settings.elide_empty_files && num_chunks > num_bytes;
|
||||||
let (num_chunks, chunk_size) = if will_have_empty_files {
|
let (num_chunks, chunk_size) = if will_have_empty_files {
|
||||||
let num_chunks = num_bytes as usize;
|
let num_chunks = num_bytes;
|
||||||
let chunk_size = 1;
|
let chunk_size = 1;
|
||||||
(num_chunks, chunk_size)
|
(num_chunks, chunk_size)
|
||||||
} else {
|
} else {
|
||||||
let chunk_size = ((num_bytes / (num_chunks as u64)) as usize).max(1);
|
let chunk_size = (num_bytes / (num_chunks)).max(1);
|
||||||
(num_chunks, chunk_size)
|
(num_chunks, chunk_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let num_chunks: usize = num_chunks
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| USimpleError::new(1, "Number of chunks too big"))?;
|
||||||
|
|
||||||
// This object is responsible for creating the filename for each chunk.
|
// This object is responsible for creating the filename for each chunk.
|
||||||
let mut filename_iterator = FilenameIterator::new(
|
let mut filename_iterator = FilenameIterator::new(
|
||||||
&settings.prefix,
|
&settings.prefix,
|
||||||
|
@ -682,29 +692,17 @@ where
|
||||||
// Write `chunk_size` bytes from the reader into each writer
|
// Write `chunk_size` bytes from the reader into each writer
|
||||||
// except the last.
|
// except the last.
|
||||||
//
|
//
|
||||||
// Re-use the buffer to avoid re-allocating a `Vec` on each
|
|
||||||
// iteration. The contents will be completely overwritten each
|
|
||||||
// time we call `read_exact()`.
|
|
||||||
//
|
|
||||||
// The last writer gets all remaining bytes so that if the number
|
// The last writer gets all remaining bytes so that if the number
|
||||||
// of bytes in the input file was not evenly divisible by
|
// of bytes in the input file was not evenly divisible by
|
||||||
// `num_chunks`, we don't leave any bytes behind.
|
// `num_chunks`, we don't leave any bytes behind.
|
||||||
let mut buf = vec![0u8; chunk_size];
|
|
||||||
for writer in writers.iter_mut().take(num_chunks - 1) {
|
for writer in writers.iter_mut().take(num_chunks - 1) {
|
||||||
reader.read_exact(&mut buf)?;
|
io::copy(&mut reader.by_ref().take(chunk_size), writer)?;
|
||||||
writer.write_all(&buf)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write all the remaining bytes to the last chunk.
|
// Write all the remaining bytes to the last chunk.
|
||||||
//
|
|
||||||
// To do this, we resize our buffer to have the necessary number
|
|
||||||
// of bytes.
|
|
||||||
let i = num_chunks - 1;
|
let i = num_chunks - 1;
|
||||||
let last_chunk_size = num_bytes as usize - (chunk_size * (num_chunks - 1));
|
let last_chunk_size = num_bytes - (chunk_size * (num_chunks as u64 - 1));
|
||||||
buf.resize(last_chunk_size, 0);
|
io::copy(&mut reader.by_ref().take(last_chunk_size), &mut writers[i])?;
|
||||||
|
|
||||||
reader.read_exact(&mut buf)?;
|
|
||||||
writers[i].write_all(&buf)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue