diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/bytesize/src | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/bytesize/src')
-rw-r--r-- | vendor/bytesize/src/lib.rs | 204 | ||||
-rw-r--r-- | vendor/bytesize/src/parse.rs | 218 |
2 files changed, 383 insertions, 39 deletions
diff --git a/vendor/bytesize/src/lib.rs b/vendor/bytesize/src/lib.rs index e2d63c9c5..01c4440e5 100644 --- a/vendor/bytesize/src/lib.rs +++ b/vendor/bytesize/src/lib.rs @@ -27,12 +27,17 @@ //! assert_eq!("518 GB".to_string(), ByteSize::gb(518).to_string(false)); //! ``` +mod parse; + #[cfg(feature = "serde")] -#[macro_use] extern crate serde; +#[cfg(feature = "serde")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "serde")] +use std::convert::TryFrom; -use std::fmt::{Debug, Display, Formatter, Result}; -use std::ops::{Add, Mul}; +use std::fmt::{self, Debug, Display, Formatter}; +use std::ops::{Add, AddAssign, Mul, MulAssign}; /// byte size for 1 byte pub const B: u64 = 1; @@ -58,8 +63,8 @@ pub const TIB: u64 = 1_099_511_627_776; /// bytes size for 1 pebibyte pub const PIB: u64 = 1_125_899_906_842_624; -static UNITS: &'static str = "KMGTPE"; -static UNITS_SI: &'static str = "kMGTPE"; +static UNITS: &str = "KMGTPE"; +static UNITS_SI: &str = "kMGTPE"; static LN_KB: f64 = 6.931471806; // ln 1024 static LN_KIB: f64 = 6.907755279; // ln 1000 @@ -104,68 +109,67 @@ pub fn pib<V: Into<u64>>(size: V) -> u64 { } /// Byte size representation -#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Default)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] pub struct ByteSize(pub u64); impl ByteSize { #[inline(always)] - pub fn b(size: u64) -> ByteSize { + pub const fn b(size: u64) -> ByteSize { ByteSize(size) } #[inline(always)] - pub fn kb(size: u64) -> ByteSize { + pub const fn kb(size: u64) -> ByteSize { ByteSize(size * KB) } #[inline(always)] - pub fn kib(size: u64) -> ByteSize { + pub const fn kib(size: u64) -> ByteSize { ByteSize(size * KIB) } #[inline(always)] - pub fn mb(size: u64) -> ByteSize { + pub const fn mb(size: u64) -> ByteSize { ByteSize(size * MB) } #[inline(always)] - pub fn mib(size: u64) -> ByteSize { + pub const fn mib(size: u64) -> ByteSize { ByteSize(size * MIB) } #[inline(always)] - pub fn gb(size: u64) -> ByteSize { + pub const fn gb(size: u64) -> ByteSize { ByteSize(size * GB) } #[inline(always)] - pub fn gib(size: u64) -> ByteSize { + pub const fn gib(size: u64) -> ByteSize { ByteSize(size * GIB) } #[inline(always)] - pub fn tb(size: u64) -> ByteSize { + pub const fn tb(size: u64) -> ByteSize { ByteSize(size * TB) } #[inline(always)] - pub fn tib(size: u64) -> ByteSize { + pub const fn tib(size: u64) -> ByteSize { ByteSize(size * TIB) } #[inline(always)] - pub fn pb(size: u64) -> ByteSize { + pub const fn pb(size: u64) -> ByteSize { ByteSize(size * PB) } #[inline(always)] - pub fn pib(size: u64) -> ByteSize { + pub const fn pib(size: u64) -> ByteSize { ByteSize(size * PIB) } #[inline(always)] - pub fn as_u64(&self) -> u64 { + pub const fn as_u64(&self) -> u64 { self.0 } @@ -204,27 +208,19 @@ pub fn to_string(bytes: u64, si_prefix: bool) -> String { } impl Display for ByteSize { - fn fmt(&self, f: &mut Formatter) -> Result { + fn fmt(&self, f: &mut Formatter) ->fmt::Result { f.pad(&to_string(self.0, false)) } } impl Debug for ByteSize { - fn fmt(&self, f: &mut Formatter) -> Result { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}", self) } } macro_rules! commutative_op { ($t:ty) => { - impl Add<$t> for ByteSize { - type Output = ByteSize; - #[inline(always)] - fn add(self, rhs: $t) -> ByteSize { - ByteSize(self.0 + (rhs as u64)) - } - } - impl Add<ByteSize> for $t { type Output = ByteSize; #[inline(always)] @@ -233,14 +229,6 @@ macro_rules! commutative_op { } } - impl Mul<$t> for ByteSize { - type Output = ByteSize; - #[inline(always)] - fn mul(self, rhs: $t) -> ByteSize { - ByteSize(self.0 * (rhs as u64)) - } - } - impl Mul<ByteSize> for $t { type Output = ByteSize; #[inline(always)] @@ -265,13 +253,118 @@ impl Add<ByteSize> for ByteSize { } } +impl AddAssign<ByteSize> for ByteSize { + #[inline(always)] + fn add_assign(&mut self, rhs: ByteSize) { + self.0 += rhs.0 + } +} + +impl<T> Add<T> for ByteSize + where T: Into<u64> { + type Output = ByteSize; + #[inline(always)] + fn add(self, rhs: T) -> ByteSize { + ByteSize(self.0 + (rhs.into() as u64)) + } +} + +impl<T> AddAssign<T> for ByteSize + where T: Into<u64> { + #[inline(always)] + fn add_assign(&mut self, rhs: T) { + self.0 += rhs.into() as u64; + } +} + +impl<T> Mul<T> for ByteSize + where T: Into<u64> { + type Output = ByteSize; + #[inline(always)] + fn mul(self, rhs: T) -> ByteSize { + ByteSize(self.0 * (rhs.into() as u64)) + } +} + +impl<T> MulAssign<T> for ByteSize + where T: Into<u64> { + #[inline(always)] + fn mul_assign(&mut self, rhs: T) { + self.0 *= rhs.into() as u64; + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for ByteSize { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + struct ByteSizeVistor; + + impl<'de> de::Visitor<'de> for ByteSizeVistor { + type Value = ByteSize; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an integer or string") + } + + fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> { + if let Ok(val) = u64::try_from(value) { + Ok(ByteSize(val)) + } else { + Err(E::invalid_value( + de::Unexpected::Signed(value), + &"integer overflow", + )) + } + } + + fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> { + Ok(ByteSize(value)) + } + + fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> { + if let Ok(val) = value.parse() { + Ok(val) + } else { + Err(E::invalid_value( + de::Unexpected::Str(value), + &"parsable string", + )) + } + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_any(ByteSizeVistor) + } else { + deserializer.deserialize_u64(ByteSizeVistor) + } + } +} + +#[cfg(feature = "serde")] +impl Serialize for ByteSize { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + if serializer.is_human_readable() { + <str>::serialize(self.to_string().as_str(), serializer) + } else { + self.0.serialize(serializer) + } + } +} + #[cfg(test)] mod tests { use super::*; #[test] fn test_arithmetic_op() { - let x = ByteSize::mb(1); + let mut x = ByteSize::mb(1); let y = ByteSize::kb(100); assert_eq!((x + y).as_u64(), 1_100_000u64); @@ -279,11 +372,16 @@ mod tests { assert_eq!((x + (100 * 1000) as u64).as_u64(), 1_100_000); assert_eq!((x * 2u64).as_u64(), 2_000_000); + + x += y; + assert_eq!(x.as_u64(), 1_100_000); + x *= 2u64; + assert_eq!(x.as_u64(), 2_200_000); } #[test] fn test_arithmetic_primitives() { - let x = ByteSize::mb(1); + let mut x = ByteSize::mb(1); assert_eq!((x + MB as u64).as_u64(), 2_000_000); @@ -292,6 +390,12 @@ mod tests { assert_eq!((x + KB as u16).as_u64(), 1_001_000); assert_eq!((x + B as u8).as_u64(), 1_000_001); + + x += MB as u64; + x += MB as u32; + x += 10u16; + x += 1u8; + assert_eq!(x.as_u64(), 3_000_011); } #[test] @@ -374,4 +478,26 @@ mod tests { fn test_to_string() { assert_to_string("609.0 PB", ByteSize::pb(609), false); } + + #[cfg(feature = "serde")] + #[test] + fn test_serde() { + #[derive(Serialize, Deserialize)] + struct S { + x: ByteSize, + } + + let s: S = serde_json::from_str(r#"{ "x": "5 B" }"#).unwrap(); + assert_eq!(s.x, ByteSize(5)); + + let s: S = serde_json::from_str(r#"{ "x": 1048576 }"#).unwrap(); + assert_eq!(s.x, "1 MiB".parse::<ByteSize>().unwrap()); + + let s: S = toml::from_str(r#"x = "2.5 MiB""#).unwrap(); + assert_eq!(s.x, "2.5 MiB".parse::<ByteSize>().unwrap()); + + // i64 MAX + let s: S = toml::from_str(r#"x = "9223372036854775807""#).unwrap(); + assert_eq!(s.x, "9223372036854775807".parse::<ByteSize>().unwrap()); + } } diff --git a/vendor/bytesize/src/parse.rs b/vendor/bytesize/src/parse.rs new file mode 100644 index 000000000..e86034e2f --- /dev/null +++ b/vendor/bytesize/src/parse.rs @@ -0,0 +1,218 @@ +use super::ByteSize; + +impl std::str::FromStr for ByteSize { + type Err = String; + + fn from_str(value: &str) -> Result<Self, Self::Err> { + if let Ok(v) = value.parse::<u64>() { + return Ok(Self(v)); + } + let number: String = value + .chars() + .take_while(|c| c.is_ascii_digit() || c == &'.') + .collect(); + match number.parse::<f64>() { + Ok(v) => { + let suffix: String = value + .chars() + .skip_while(|c| c.is_whitespace() || c.is_ascii_digit() || c == &'.') + .collect(); + match suffix.parse::<Unit>() { + Ok(u) => Ok(Self((v * u) as u64)), + Err(error) => Err(format!( + "couldn't parse {:?} into a known SI unit, {}", + suffix, error + )), + } + } + Err(error) => Err(format!( + "couldn't parse {:?} into a ByteSize, {}", + value, error + )), + } + } +} + +enum Unit { + Byte, + // power of tens + KiloByte, + MegaByte, + GigaByte, + TeraByte, + PetaByte, + // power of twos + KibiByte, + MebiByte, + GibiByte, + TebiByte, + PebiByte, +} + +impl Unit { + fn factor(&self) -> u64 { + match self { + Self::Byte => super::B, + // power of tens + Self::KiloByte => super::KB, + Self::MegaByte => super::MB, + Self::GigaByte => super::GB, + Self::TeraByte => super::TB, + Self::PetaByte => super::PB, + // power of twos + Self::KibiByte => super::KIB, + Self::MebiByte => super::MIB, + Self::GibiByte => super::GIB, + Self::TebiByte => super::TIB, + Self::PebiByte => super::PIB, + } + } +} + +mod impl_ops { + use super::Unit; + use std::ops; + + impl ops::Add<u64> for Unit { + type Output = u64; + + fn add(self, other: u64) -> Self::Output { + self.factor() + other + } + } + + impl ops::Add<Unit> for u64 { + type Output = u64; + + fn add(self, other: Unit) -> Self::Output { + self + other.factor() + } + } + + impl ops::Mul<u64> for Unit { + type Output = u64; + + fn mul(self, other: u64) -> Self::Output { + self.factor() * other + } + } + + impl ops::Mul<Unit> for u64 { + type Output = u64; + + fn mul(self, other: Unit) -> Self::Output { + self * other.factor() + } + } + + impl ops::Add<f64> for Unit { + type Output = f64; + + fn add(self, other: f64) -> Self::Output { + self.factor() as f64 + other + } + } + + impl ops::Add<Unit> for f64 { + type Output = f64; + + fn add(self, other: Unit) -> Self::Output { + other.factor() as f64 + self + } + } + + impl ops::Mul<f64> for Unit { + type Output = f64; + + fn mul(self, other: f64) -> Self::Output { + self.factor() as f64 * other + } + } + + impl ops::Mul<Unit> for f64 { + type Output = f64; + + fn mul(self, other: Unit) -> Self::Output { + other.factor() as f64 * self + } + } +} + +impl std::str::FromStr for Unit { + type Err = String; + + fn from_str(unit: &str) -> Result<Self, Self::Err> { + match unit.to_lowercase().as_str() { + "b" => Ok(Self::Byte), + // power of tens + "k" | "kb" => Ok(Self::KiloByte), + "m" | "mb" => Ok(Self::MegaByte), + "g" | "gb" => Ok(Self::GigaByte), + "t" | "tb" => Ok(Self::TeraByte), + "p" | "pb" => Ok(Self::PetaByte), + // power of twos + "ki" | "kib" => Ok(Self::KibiByte), + "mi" | "mib" => Ok(Self::MebiByte), + "gi" | "gib" => Ok(Self::GibiByte), + "ti" | "tib" => Ok(Self::TebiByte), + "pi" | "pib" => Ok(Self::PebiByte), + _ => Err(format!("couldn't parse unit of {:?}", unit)), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn when_ok() { + // shortcut for writing test cases + fn parse(s: &str) -> u64 { + s.parse::<ByteSize>().unwrap().0 + } + + assert_eq!("0".parse::<ByteSize>().unwrap().0, 0); + assert_eq!(parse("0"), 0); + assert_eq!(parse("500"), 500); + assert_eq!(parse("1K"), Unit::KiloByte * 1); + assert_eq!(parse("1Ki"), Unit::KibiByte * 1); + assert_eq!(parse("1.5Ki"), (1.5 * Unit::KibiByte) as u64); + assert_eq!(parse("1KiB"), 1 * Unit::KibiByte); + assert_eq!(parse("1.5KiB"), (1.5 * Unit::KibiByte) as u64); + assert_eq!(parse("3 MB"), Unit::MegaByte * 3); + assert_eq!(parse("4 MiB"), Unit::MebiByte * 4); + assert_eq!(parse("6 GB"), 6 * Unit::GigaByte); + assert_eq!(parse("4 GiB"), 4 * Unit::GibiByte); + assert_eq!(parse("88TB"), 88 * Unit::TeraByte); + assert_eq!(parse("521TiB"), 521 * Unit::TebiByte); + assert_eq!(parse("8 PB"), 8 * Unit::PetaByte); + assert_eq!(parse("8P"), 8 * Unit::PetaByte); + assert_eq!(parse("12 PiB"), 12 * Unit::PebiByte); + } + + #[test] + fn when_err() { + // shortcut for writing test cases + fn parse(s: &str) -> Result<ByteSize, String> { + s.parse::<ByteSize>() + } + + assert!(parse("").is_err()); + assert!(parse("a124GB").is_err()); + } + + #[test] + fn to_and_from_str() { + // shortcut for writing test cases + fn parse(s: &str) -> u64 { + s.parse::<ByteSize>().unwrap().0 + } + + assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * Unit::GigaByte); + assert_eq!( + parse(&crate::to_string(parse("128.000 GiB"), true)), + 128 * Unit::GibiByte + ); + } +} |