mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
uucore: parse_size_max and split
This commit is contained in:
parent
420965a3ab
commit
636c2bb7ae
2 changed files with 40 additions and 20 deletions
|
@ -21,7 +21,7 @@ use std::io::{stdin, BufRead, BufReader, BufWriter, ErrorKind, Read, Write};
|
|||
use std::path::Path;
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{FromIo, UIoError, UResult, USimpleError, UUsageError};
|
||||
use uucore::parse_size::{parse_size, ParseSizeError};
|
||||
use uucore::parse_size::{parse_size_max, ParseSizeError};
|
||||
use uucore::uio_error;
|
||||
use uucore::{format_usage, help_about, help_section, help_usage};
|
||||
|
||||
|
@ -419,8 +419,7 @@ impl NumberType {
|
|||
let parts: Vec<&str> = s.split('/').collect();
|
||||
match &parts[..] {
|
||||
[n_str] => {
|
||||
let num_chunks = n_str
|
||||
.parse()
|
||||
let num_chunks = parse_size_max(n_str)
|
||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||
if num_chunks > 0 {
|
||||
Ok(Self::Bytes(num_chunks))
|
||||
|
@ -429,32 +428,26 @@ impl NumberType {
|
|||
}
|
||||
}
|
||||
["l", n_str] => {
|
||||
let num_chunks = n_str
|
||||
.parse()
|
||||
let num_chunks = parse_size_max(n_str)
|
||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||
Ok(Self::Lines(num_chunks))
|
||||
}
|
||||
["l", k_str, n_str] => {
|
||||
let num_chunks = n_str
|
||||
.parse()
|
||||
let num_chunks = parse_size_max(n_str)
|
||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||
let chunk_number = k_str
|
||||
.parse()
|
||||
let chunk_number = parse_size_max(k_str)
|
||||
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
||||
Ok(Self::KthLines(chunk_number, num_chunks))
|
||||
}
|
||||
["r", n_str] => {
|
||||
let num_chunks = n_str
|
||||
.parse()
|
||||
let num_chunks = parse_size_max(n_str)
|
||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||
Ok(Self::RoundRobin(num_chunks))
|
||||
}
|
||||
["r", k_str, n_str] => {
|
||||
let num_chunks = n_str
|
||||
.parse()
|
||||
let num_chunks = parse_size_max(n_str)
|
||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||
let chunk_number = k_str
|
||||
.parse()
|
||||
let chunk_number = parse_size_max(k_str)
|
||||
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
||||
Ok(Self::KthRoundRobin(chunk_number, num_chunks))
|
||||
}
|
||||
|
@ -523,7 +516,7 @@ impl Strategy {
|
|||
error: fn(ParseSizeError) -> StrategyError,
|
||||
) -> Result<Strategy, StrategyError> {
|
||||
let s = matches.get_one::<String>(option).unwrap();
|
||||
let n = parse_size(s).map_err(error)?;
|
||||
let n = parse_size_max(s).map_err(error)?;
|
||||
if n > 0 {
|
||||
Ok(strategy(n))
|
||||
} else {
|
||||
|
@ -542,7 +535,7 @@ impl Strategy {
|
|||
matches.value_source(OPT_NUMBER) == Some(ValueSource::CommandLine),
|
||||
) {
|
||||
(Some(v), false, false, false, false) => {
|
||||
let v = parse_size(v).map_err(|_| {
|
||||
let v = parse_size_max(v).map_err(|_| {
|
||||
StrategyError::Lines(ParseSizeError::ParseFailure(v.to_string()))
|
||||
})?;
|
||||
Ok(Self::Lines(v))
|
||||
|
@ -687,7 +680,6 @@ impl Settings {
|
|||
if additional_suffix.contains('/') {
|
||||
return Err(SettingsError::SuffixContainsSeparator(additional_suffix));
|
||||
}
|
||||
|
||||
let strategy = Strategy::from(matches, obs_lines).map_err(SettingsError::Strategy)?;
|
||||
let (suffix_type, suffix_start) = suffix_type_from(matches)?;
|
||||
let suffix_length_str = matches.get_one::<String>(OPT_SUFFIX_LENGTH).unwrap();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
use crate::display::Quotable;
|
||||
|
||||
|
@ -201,8 +202,10 @@ impl<'parser> Parser<'parser> {
|
|||
radix: u32,
|
||||
original_size: &str,
|
||||
) -> Result<u64, ParseSizeError> {
|
||||
u64::from_str_radix(numeric_string, radix)
|
||||
.map_err(|_| ParseSizeError::ParseFailure(original_size.to_string()))
|
||||
u64::from_str_radix(numeric_string, radix).map_err(|e| match e.kind() {
|
||||
IntErrorKind::PosOverflow => ParseSizeError::size_too_big(original_size),
|
||||
_ => ParseSizeError::ParseFailure(original_size.to_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +235,23 @@ pub fn parse_size(size: &str) -> Result<u64, ParseSizeError> {
|
|||
Parser::default().parse(size)
|
||||
}
|
||||
|
||||
/// Same as `parse_size()`, except returns `u64::MAX` on overflow
|
||||
/// GNU lib/coreutils include similar functionality
|
||||
/// and GNU test suite checks this behavior for some utils
|
||||
pub fn parse_size_max(size: &str) -> Result<u64, ParseSizeError> {
|
||||
let result = Parser::default().parse(size);
|
||||
match result {
|
||||
Ok(_) => result,
|
||||
Err(error) => {
|
||||
if let ParseSizeError::SizeTooBig(_) = error {
|
||||
Ok(u64::MAX)
|
||||
} else {
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseSizeError {
|
||||
InvalidSuffix(String), // Suffix
|
||||
|
@ -392,6 +412,14 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
fn overflow_to_max_x64() {
|
||||
assert_eq!(Ok(u64::MAX), parse_size_max("18446744073709551616"));
|
||||
assert_eq!(Ok(u64::MAX), parse_size_max("10000000000000000000000"));
|
||||
assert_eq!(Ok(u64::MAX), parse_size_max("1Y"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_suffix() {
|
||||
let test_strings = ["5mib", "1eb", "1H"];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue