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 std::path::Path;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{FromIo, UIoError, UResult, USimpleError, UUsageError};
|
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::uio_error;
|
||||||
use uucore::{format_usage, help_about, help_section, help_usage};
|
use uucore::{format_usage, help_about, help_section, help_usage};
|
||||||
|
|
||||||
|
@ -419,8 +419,7 @@ impl NumberType {
|
||||||
let parts: Vec<&str> = s.split('/').collect();
|
let parts: Vec<&str> = s.split('/').collect();
|
||||||
match &parts[..] {
|
match &parts[..] {
|
||||||
[n_str] => {
|
[n_str] => {
|
||||||
let num_chunks = n_str
|
let num_chunks = parse_size_max(n_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||||
if num_chunks > 0 {
|
if num_chunks > 0 {
|
||||||
Ok(Self::Bytes(num_chunks))
|
Ok(Self::Bytes(num_chunks))
|
||||||
|
@ -429,32 +428,26 @@ impl NumberType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
["l", n_str] => {
|
["l", n_str] => {
|
||||||
let num_chunks = n_str
|
let num_chunks = parse_size_max(n_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||||
Ok(Self::Lines(num_chunks))
|
Ok(Self::Lines(num_chunks))
|
||||||
}
|
}
|
||||||
["l", k_str, n_str] => {
|
["l", k_str, n_str] => {
|
||||||
let num_chunks = n_str
|
let num_chunks = parse_size_max(n_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||||
let chunk_number = k_str
|
let chunk_number = parse_size_max(k_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
||||||
Ok(Self::KthLines(chunk_number, num_chunks))
|
Ok(Self::KthLines(chunk_number, num_chunks))
|
||||||
}
|
}
|
||||||
["r", n_str] => {
|
["r", n_str] => {
|
||||||
let num_chunks = n_str
|
let num_chunks = parse_size_max(n_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||||
Ok(Self::RoundRobin(num_chunks))
|
Ok(Self::RoundRobin(num_chunks))
|
||||||
}
|
}
|
||||||
["r", k_str, n_str] => {
|
["r", k_str, n_str] => {
|
||||||
let num_chunks = n_str
|
let num_chunks = parse_size_max(n_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
.map_err(|_| NumberTypeError::NumberOfChunks(n_str.to_string()))?;
|
||||||
let chunk_number = k_str
|
let chunk_number = parse_size_max(k_str)
|
||||||
.parse()
|
|
||||||
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
.map_err(|_| NumberTypeError::ChunkNumber(k_str.to_string()))?;
|
||||||
Ok(Self::KthRoundRobin(chunk_number, num_chunks))
|
Ok(Self::KthRoundRobin(chunk_number, num_chunks))
|
||||||
}
|
}
|
||||||
|
@ -523,7 +516,7 @@ impl Strategy {
|
||||||
error: fn(ParseSizeError) -> StrategyError,
|
error: fn(ParseSizeError) -> StrategyError,
|
||||||
) -> Result<Strategy, StrategyError> {
|
) -> Result<Strategy, StrategyError> {
|
||||||
let s = matches.get_one::<String>(option).unwrap();
|
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 {
|
if n > 0 {
|
||||||
Ok(strategy(n))
|
Ok(strategy(n))
|
||||||
} else {
|
} else {
|
||||||
|
@ -542,7 +535,7 @@ impl Strategy {
|
||||||
matches.value_source(OPT_NUMBER) == Some(ValueSource::CommandLine),
|
matches.value_source(OPT_NUMBER) == Some(ValueSource::CommandLine),
|
||||||
) {
|
) {
|
||||||
(Some(v), false, false, false, false) => {
|
(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()))
|
StrategyError::Lines(ParseSizeError::ParseFailure(v.to_string()))
|
||||||
})?;
|
})?;
|
||||||
Ok(Self::Lines(v))
|
Ok(Self::Lines(v))
|
||||||
|
@ -687,7 +680,6 @@ impl Settings {
|
||||||
if additional_suffix.contains('/') {
|
if additional_suffix.contains('/') {
|
||||||
return Err(SettingsError::SuffixContainsSeparator(additional_suffix));
|
return Err(SettingsError::SuffixContainsSeparator(additional_suffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
let strategy = Strategy::from(matches, obs_lines).map_err(SettingsError::Strategy)?;
|
let strategy = Strategy::from(matches, obs_lines).map_err(SettingsError::Strategy)?;
|
||||||
let (suffix_type, suffix_start) = suffix_type_from(matches)?;
|
let (suffix_type, suffix_start) = suffix_type_from(matches)?;
|
||||||
let suffix_length_str = matches.get_one::<String>(OPT_SUFFIX_LENGTH).unwrap();
|
let suffix_length_str = matches.get_one::<String>(OPT_SUFFIX_LENGTH).unwrap();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::num::IntErrorKind;
|
||||||
|
|
||||||
use crate::display::Quotable;
|
use crate::display::Quotable;
|
||||||
|
|
||||||
|
@ -201,8 +202,10 @@ impl<'parser> Parser<'parser> {
|
||||||
radix: u32,
|
radix: u32,
|
||||||
original_size: &str,
|
original_size: &str,
|
||||||
) -> Result<u64, ParseSizeError> {
|
) -> Result<u64, ParseSizeError> {
|
||||||
u64::from_str_radix(numeric_string, radix)
|
u64::from_str_radix(numeric_string, radix).map_err(|e| match e.kind() {
|
||||||
.map_err(|_| ParseSizeError::ParseFailure(original_size.to_string()))
|
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)
|
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)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum ParseSizeError {
|
pub enum ParseSizeError {
|
||||||
InvalidSuffix(String), // Suffix
|
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]
|
#[test]
|
||||||
fn invalid_suffix() {
|
fn invalid_suffix() {
|
||||||
let test_strings = ["5mib", "1eb", "1H"];
|
let test_strings = ["5mib", "1eb", "1H"];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue