mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
uucore: format: Have get_num return T directly (not result)
And fix all the callers, e.g. all the next_ functions.
This commit is contained in:
parent
51453f833e
commit
5b6a617024
2 changed files with 70 additions and 127 deletions
|
|
@ -3,7 +3,7 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use super::{ExtendedBigDecimal, FormatError};
|
||||
use super::ExtendedBigDecimal;
|
||||
use crate::format::spec::ArgumentLocation;
|
||||
use crate::{
|
||||
error::set_exit_code,
|
||||
|
|
@ -73,14 +73,14 @@ impl<'a> FormatArguments<'a> {
|
|||
self.next_arg_position = self.current_offset;
|
||||
}
|
||||
|
||||
pub fn next_char(&mut self, position: &ArgumentLocation) -> Result<u8, FormatError> {
|
||||
pub fn next_char(&mut self, position: &ArgumentLocation) -> u8 {
|
||||
match self.next_arg(position) {
|
||||
Some(FormatArgument::Char(c)) => Ok(*c as u8),
|
||||
Some(FormatArgument::Unparsed(os)) => match os_str_as_bytes(os)?.first() {
|
||||
Some(&byte) => Ok(byte),
|
||||
None => Ok(b'\0'),
|
||||
Some(FormatArgument::Char(c)) => *c as u8,
|
||||
Some(FormatArgument::Unparsed(os)) => match os_str_as_bytes(os) {
|
||||
Ok(bytes) => bytes.first().copied().unwrap_or(b'\0'),
|
||||
Err(_) => b'\0',
|
||||
},
|
||||
_ => Ok(b'\0'),
|
||||
_ => b'\0',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,38 +91,36 @@ impl<'a> FormatArguments<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn next_i64(&mut self, position: &ArgumentLocation) -> Result<i64, FormatError> {
|
||||
pub fn next_i64(&mut self, position: &ArgumentLocation) -> i64 {
|
||||
match self.next_arg(position) {
|
||||
Some(FormatArgument::SignedInt(n)) => Ok(*n),
|
||||
Some(FormatArgument::SignedInt(n)) => *n,
|
||||
Some(FormatArgument::Unparsed(os)) => Self::get_num::<i64>(os),
|
||||
_ => Ok(0),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_u64(&mut self, position: &ArgumentLocation) -> Result<u64, FormatError> {
|
||||
pub fn next_u64(&mut self, position: &ArgumentLocation) -> u64 {
|
||||
match self.next_arg(position) {
|
||||
Some(FormatArgument::UnsignedInt(n)) => Ok(*n),
|
||||
Some(FormatArgument::UnsignedInt(n)) => *n,
|
||||
Some(FormatArgument::Unparsed(os)) => Self::get_num::<u64>(os),
|
||||
_ => Ok(0),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_extended_big_decimal(
|
||||
&mut self,
|
||||
position: &ArgumentLocation,
|
||||
) -> Result<ExtendedBigDecimal, FormatError> {
|
||||
pub fn next_extended_big_decimal(&mut self, position: &ArgumentLocation) -> ExtendedBigDecimal {
|
||||
match self.next_arg(position) {
|
||||
Some(FormatArgument::Float(n)) => Ok(n.clone()),
|
||||
Some(FormatArgument::Float(n)) => n.clone(),
|
||||
Some(FormatArgument::Unparsed(os)) => Self::get_num::<ExtendedBigDecimal>(os),
|
||||
_ => Ok(ExtendedBigDecimal::zero()),
|
||||
_ => ExtendedBigDecimal::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_num<T>(os: &OsStr) -> Result<T, FormatError>
|
||||
fn get_num<T>(os: &OsStr) -> T
|
||||
where
|
||||
T: ExtendedParser + From<u8> + From<u32> + Default,
|
||||
{
|
||||
let s = os_str_as_bytes(os)?;
|
||||
// FIXME: Remove unwrap
|
||||
let s = os_str_as_bytes(os).unwrap();
|
||||
// Check if the string begins with a quote, and is therefore a literal
|
||||
if let Some((&first, bytes)) = s.split_first() {
|
||||
if (first == b'"' || first == b'\'') && !bytes.is_empty() {
|
||||
|
|
@ -148,11 +146,11 @@ impl<'a> FormatArguments<'a> {
|
|||
String::from_utf8_lossy(&bytes[len..])
|
||||
);
|
||||
}
|
||||
return Ok(val);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
let s = os.to_string_lossy();
|
||||
Ok(extract_value(T::extended_parse(&s), &s))
|
||||
extract_value(T::extended_parse(&s), &s)
|
||||
}
|
||||
|
||||
fn get_at_relative_position(&mut self, pos: NonZero<usize>) -> Option<&'a FormatArgument> {
|
||||
|
|
@ -227,10 +225,7 @@ mod tests {
|
|||
assert!(!args.is_exhausted());
|
||||
assert_eq!(Some(&FormatArgument::Char('a')), args.peek_arg());
|
||||
assert!(!args.is_exhausted()); // Peek shouldn't consume
|
||||
assert_eq!(
|
||||
b'a',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'a', args.next_char(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted()); // After batch, exhausted with a single arg
|
||||
assert_eq!(None, args.peek_arg());
|
||||
|
|
@ -251,50 +246,26 @@ mod tests {
|
|||
]);
|
||||
|
||||
// First batch - two sequential calls
|
||||
assert_eq!(
|
||||
b'z',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
b'y',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'z', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b'y', args.next_char(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same pattern
|
||||
assert_eq!(
|
||||
b'x',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
b'w',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'x', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b'w', args.next_char(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Third batch - same pattern
|
||||
assert_eq!(
|
||||
b'v',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
b'u',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'v', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b'u', args.next_char(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Fourth batch - same pattern (last batch)
|
||||
assert_eq!(
|
||||
b't',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
b's',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b't', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b's', args.next_char(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
@ -313,28 +284,19 @@ mod tests {
|
|||
let mut args = FormatArguments::new(&args);
|
||||
|
||||
// First batch - next_char followed by next_string
|
||||
assert_eq!(
|
||||
b'a',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'a', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!("hello", args.next_string(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same pattern
|
||||
assert_eq!(
|
||||
b'1',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
); // First byte of 123
|
||||
assert_eq!(b'1', args.next_char(&ArgumentLocation::NextArgument)); // First byte of 123
|
||||
assert_eq!("world", args.next_string(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Third batch - same pattern (last batch)
|
||||
assert_eq!(
|
||||
b'z',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'z', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!("test", args.next_string(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
|
|
@ -360,23 +322,23 @@ mod tests {
|
|||
]);
|
||||
|
||||
// First batch - positional access
|
||||
assert_eq!(b'b', args.next_char(&non_zero_pos(2)).unwrap()); // Position 2
|
||||
assert_eq!(b'a', args.next_char(&non_zero_pos(1)).unwrap()); // Position 1
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3)).unwrap()); // Position 3
|
||||
assert_eq!(b'b', args.next_char(&non_zero_pos(2))); // Position 2
|
||||
assert_eq!(b'a', args.next_char(&non_zero_pos(1))); // Position 1
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3))); // Position 3
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same positional pattern
|
||||
assert_eq!(b'e', args.next_char(&non_zero_pos(2)).unwrap()); // Position 2
|
||||
assert_eq!(b'd', args.next_char(&non_zero_pos(1)).unwrap()); // Position 1
|
||||
assert_eq!(b'f', args.next_char(&non_zero_pos(3)).unwrap()); // Position 3
|
||||
assert_eq!(b'e', args.next_char(&non_zero_pos(2))); // Position 2
|
||||
assert_eq!(b'd', args.next_char(&non_zero_pos(1))); // Position 1
|
||||
assert_eq!(b'f', args.next_char(&non_zero_pos(3))); // Position 3
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Third batch - same positional pattern (last batch)
|
||||
assert_eq!(b'h', args.next_char(&non_zero_pos(2)).unwrap()); // Position 2
|
||||
assert_eq!(b'g', args.next_char(&non_zero_pos(1)).unwrap()); // Position 1
|
||||
assert_eq!(b'i', args.next_char(&non_zero_pos(3)).unwrap()); // Position 3
|
||||
assert_eq!(b'h', args.next_char(&non_zero_pos(2))); // Position 2
|
||||
assert_eq!(b'g', args.next_char(&non_zero_pos(1))); // Position 1
|
||||
assert_eq!(b'i', args.next_char(&non_zero_pos(3))); // Position 3
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
@ -396,29 +358,20 @@ mod tests {
|
|||
]);
|
||||
|
||||
// First batch - mix of sequential and positional
|
||||
assert_eq!(
|
||||
b'a',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
); // Sequential
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3)).unwrap()); // Positional
|
||||
assert_eq!(b'a', args.next_char(&ArgumentLocation::NextArgument)); // Sequential
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3))); // Positional
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same mixed pattern
|
||||
assert_eq!(
|
||||
b'd',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
); // Sequential
|
||||
assert_eq!(b'f', args.next_char(&non_zero_pos(3)).unwrap()); // Positional
|
||||
assert_eq!(b'd', args.next_char(&ArgumentLocation::NextArgument)); // Sequential
|
||||
assert_eq!(b'f', args.next_char(&non_zero_pos(3))); // Positional
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Last batch - same mixed pattern
|
||||
assert_eq!(
|
||||
b'g',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
); // Sequential
|
||||
assert_eq!(b'\0', args.next_char(&non_zero_pos(3)).unwrap()); // Out of bounds
|
||||
assert_eq!(b'g', args.next_char(&ArgumentLocation::NextArgument)); // Sequential
|
||||
assert_eq!(b'\0', args.next_char(&non_zero_pos(3))); // Out of bounds
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
@ -437,21 +390,17 @@ mod tests {
|
|||
let mut args = FormatArguments::new(&args);
|
||||
|
||||
// First batch - i64, u64, decimal
|
||||
assert_eq!(10, args.next_i64(&ArgumentLocation::NextArgument).unwrap());
|
||||
assert_eq!(20, args.next_u64(&ArgumentLocation::NextArgument).unwrap());
|
||||
let result = args
|
||||
.next_extended_big_decimal(&ArgumentLocation::NextArgument)
|
||||
.unwrap();
|
||||
assert_eq!(10, args.next_i64(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(20, args.next_u64(&ArgumentLocation::NextArgument));
|
||||
let result = args.next_extended_big_decimal(&ArgumentLocation::NextArgument);
|
||||
assert_eq!(ExtendedBigDecimal::zero(), result);
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same pattern
|
||||
assert_eq!(30, args.next_i64(&ArgumentLocation::NextArgument).unwrap());
|
||||
assert_eq!(40, args.next_u64(&ArgumentLocation::NextArgument).unwrap());
|
||||
let result = args
|
||||
.next_extended_big_decimal(&ArgumentLocation::NextArgument)
|
||||
.unwrap();
|
||||
assert_eq!(30, args.next_i64(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(40, args.next_u64(&ArgumentLocation::NextArgument));
|
||||
let result = args.next_extended_big_decimal(&ArgumentLocation::NextArgument);
|
||||
assert_eq!(ExtendedBigDecimal::zero(), result);
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
|
|
@ -470,13 +419,13 @@ mod tests {
|
|||
|
||||
// First batch - string, number
|
||||
assert_eq!("hello", args.next_string(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(123, args.next_i64(&ArgumentLocation::NextArgument).unwrap());
|
||||
assert_eq!(123, args.next_i64(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same pattern
|
||||
assert_eq!("hello", args.next_string(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(456, args.next_i64(&ArgumentLocation::NextArgument).unwrap());
|
||||
assert_eq!(456, args.next_i64(&ArgumentLocation::NextArgument));
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
@ -495,16 +444,16 @@ mod tests {
|
|||
let mut args = FormatArguments::new(&args);
|
||||
|
||||
// First batch - positional access of different types
|
||||
assert_eq!(b'a', args.next_char(&non_zero_pos(1)).unwrap());
|
||||
assert_eq!(b'a', args.next_char(&non_zero_pos(1)));
|
||||
assert_eq!("test", args.next_string(&non_zero_pos(2)));
|
||||
assert_eq!(42, args.next_u64(&non_zero_pos(3)).unwrap());
|
||||
assert_eq!(42, args.next_u64(&non_zero_pos(3)));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch - same pattern
|
||||
assert_eq!(b'b', args.next_char(&non_zero_pos(1)).unwrap());
|
||||
assert_eq!(b'b', args.next_char(&non_zero_pos(1)));
|
||||
assert_eq!("more", args.next_string(&non_zero_pos(2)));
|
||||
assert_eq!(99, args.next_u64(&non_zero_pos(3)).unwrap());
|
||||
assert_eq!(99, args.next_u64(&non_zero_pos(3)));
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
@ -521,20 +470,14 @@ mod tests {
|
|||
]);
|
||||
|
||||
// First batch
|
||||
assert_eq!(
|
||||
b'a',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3)).unwrap());
|
||||
assert_eq!(b'a', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b'c', args.next_char(&non_zero_pos(3)));
|
||||
args.start_next_batch();
|
||||
assert!(!args.is_exhausted());
|
||||
|
||||
// Second batch (partial)
|
||||
assert_eq!(
|
||||
b'd',
|
||||
args.next_char(&ArgumentLocation::NextArgument).unwrap()
|
||||
);
|
||||
assert_eq!(b'\0', args.next_char(&non_zero_pos(3)).unwrap()); // Out of bounds
|
||||
assert_eq!(b'd', args.next_char(&ArgumentLocation::NextArgument));
|
||||
assert_eq!(b'\0', args.next_char(&non_zero_pos(3))); // Out of bounds
|
||||
args.start_next_batch();
|
||||
assert!(args.is_exhausted());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ impl Spec {
|
|||
let (width, neg_width) = resolve_asterisk_width(*width, args).unwrap_or_default();
|
||||
write_padded(
|
||||
writer,
|
||||
&[args.next_char(position)?],
|
||||
&[args.next_char(position)],
|
||||
width,
|
||||
*align_left || neg_width,
|
||||
)
|
||||
|
|
@ -419,7 +419,7 @@ impl Spec {
|
|||
} => {
|
||||
let (width, neg_width) = resolve_asterisk_width(*width, args).unwrap_or((0, false));
|
||||
let precision = resolve_asterisk_precision(*precision, args).unwrap_or_default();
|
||||
let i = args.next_i64(position)?;
|
||||
let i = args.next_i64(position);
|
||||
|
||||
if precision as u64 > i32::MAX as u64 {
|
||||
return Err(FormatError::InvalidPrecision(precision.to_string()));
|
||||
|
|
@ -447,7 +447,7 @@ impl Spec {
|
|||
} => {
|
||||
let (width, neg_width) = resolve_asterisk_width(*width, args).unwrap_or((0, false));
|
||||
let precision = resolve_asterisk_precision(*precision, args).unwrap_or_default();
|
||||
let i = args.next_u64(position)?;
|
||||
let i = args.next_u64(position);
|
||||
|
||||
if precision as u64 > i32::MAX as u64 {
|
||||
return Err(FormatError::InvalidPrecision(precision.to_string()));
|
||||
|
|
@ -478,7 +478,7 @@ impl Spec {
|
|||
} => {
|
||||
let (width, neg_width) = resolve_asterisk_width(*width, args).unwrap_or((0, false));
|
||||
let precision = resolve_asterisk_precision(*precision, args);
|
||||
let f: ExtendedBigDecimal = args.next_extended_big_decimal(position)?;
|
||||
let f: ExtendedBigDecimal = args.next_extended_big_decimal(position);
|
||||
|
||||
if precision.is_some_and(|p| p as u64 > i32::MAX as u64) {
|
||||
return Err(FormatError::InvalidPrecision(
|
||||
|
|
@ -515,7 +515,7 @@ fn resolve_asterisk_width(
|
|||
match option {
|
||||
None => None,
|
||||
Some(CanAsterisk::Asterisk(loc)) => {
|
||||
let nb = args.next_i64(&loc).unwrap_or(0);
|
||||
let nb = args.next_i64(&loc);
|
||||
if nb < 0 {
|
||||
Some((usize::try_from(-(nb as isize)).ok().unwrap_or(0), true))
|
||||
} else {
|
||||
|
|
@ -534,7 +534,7 @@ fn resolve_asterisk_precision(
|
|||
) -> Option<usize> {
|
||||
match option {
|
||||
None => None,
|
||||
Some(CanAsterisk::Asterisk(loc)) => match args.next_i64(&loc).unwrap_or(0) {
|
||||
Some(CanAsterisk::Asterisk(loc)) => match args.next_i64(&loc) {
|
||||
v if v >= 0 => usize::try_from(v).ok(),
|
||||
v if v < 0 => Some(0usize),
|
||||
_ => None,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue