1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

uucore: create parse_size::Parser struct

Add a `uucore::parse_size::Parser` struct which will allow future
commits to add fields that change the behavior of `parse_size()`.
This commit is contained in:
Jeffrey Finkelstein 2022-11-18 20:20:30 -05:00
parent 2f311c7a2d
commit 847378f8d2

View file

@ -10,29 +10,37 @@ use std::fmt;
use crate::display::Quotable;
/// Parse a size string into a number of bytes.
/// Parser for sizes in SI or IEC units (multiples of 1000 or 1024 bytes).
///
/// A size string comprises an integer and an optional unit. The unit
/// may be K, M, G, T, P, E, Z or Y (powers of 1024), or KB, MB,
/// etc. (powers of 1000), or b which is 512.
/// Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
///
/// # Errors
///
/// Will return `ParseSizeError` if it's not possible to parse this
/// string into a number, e.g. if the string does not begin with a
/// numeral, or if the unit is not one of the supported units described
/// in the preceding section.
///
/// # Examples
///
/// ```rust
/// use uucore::parse_size::parse_size;
/// assert_eq!(Ok(123), parse_size("123"));
/// assert_eq!(Ok(9 * 1000), parse_size("9kB")); // kB is 1000
/// assert_eq!(Ok(2 * 1024), parse_size("2K")); // K is 1024
/// ```
pub fn parse_size(size: &str) -> Result<u64, ParseSizeError> {
/// The [`Parser::parse`] function performs the parse.
#[derive(Default)]
pub struct Parser {
}
impl Parser {
/// Parse a size string into a number of bytes.
///
/// A size string comprises an integer and an optional unit. The unit
/// may be K, M, G, T, P, E, Z or Y (powers of 1024), or KB, MB,
/// etc. (powers of 1000), or b which is 512.
/// Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
///
/// # Errors
///
/// Will return `ParseSizeError` if it's not possible to parse this
/// string into a number, e.g. if the string does not begin with a
/// numeral, or if the unit is not one of the supported units described
/// in the preceding section.
///
/// # Examples
///
/// ```rust
/// use uucore::parse_size::parse_size;
/// assert_eq!(Ok(123), parse_size("123"));
/// assert_eq!(Ok(9 * 1000), parse_size("9kB")); // kB is 1000
/// assert_eq!(Ok(2 * 1024), parse_size("2K")); // K is 1024
/// ```
pub fn parse(&self, size: &str) -> Result<u64, ParseSizeError> {
if size.is_empty() {
return Err(ParseSizeError::parse_failure(size));
}
@ -52,10 +60,14 @@ pub fn parse_size(size: &str) -> Result<u64, ParseSizeError> {
// the factor it represents. For example, if the argument is "123K",
// then the unit part is "K" and the factor is 1024. This may be the
// empty string, in which case, the factor is 1.
//
// The lowercase "b" (used by `od`, `head`, `tail`, etc.) means
// "block" and the Posix block size is 512. The uppercase "B"
// means "byte".
let unit = &size[numeric_string.len()..];
let (base, exponent): (u128, u32) = match unit {
"" => (1, 0),
"b" => (512, 1), // (`od`, `head` and `tail` use "b")
"b" => (512, 1),
"KiB" | "kiB" | "K" | "k" => (1024, 1),
"MiB" | "miB" | "M" | "m" => (1024, 2),
"GiB" | "giB" | "G" | "g" => (1024, 3),
@ -82,6 +94,33 @@ pub fn parse_size(size: &str) -> Result<u64, ParseSizeError> {
number
.checked_mul(factor)
.ok_or_else(|| ParseSizeError::size_too_big(size))
}
}
/// Parse a size string into a number of bytes.
///
/// A size string comprises an integer and an optional unit. The unit
/// may be K, M, G, T, P, E, Z or Y (powers of 1024), or KB, MB,
/// etc. (powers of 1000), or b which is 512.
/// Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
///
/// # Errors
///
/// Will return `ParseSizeError` if it's not possible to parse this
/// string into a number, e.g. if the string does not begin with a
/// numeral, or if the unit is not one of the supported units described
/// in the preceding section.
///
/// # Examples
///
/// ```rust
/// use uucore::parse_size::parse_size;
/// assert_eq!(Ok(123), parse_size("123"));
/// assert_eq!(Ok(9 * 1000), parse_size("9kB")); // kB is 1000
/// assert_eq!(Ok(2 * 1024), parse_size("2K")); // K is 1024
/// ```
pub fn parse_size(size: &str) -> Result<u64, ParseSizeError> {
Parser::default().parse(size)
}
#[derive(Debug, PartialEq, Eq)]