diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-config-value/src/integer.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-config-value/src/integer.rs')
-rw-r--r-- | vendor/gix-config-value/src/integer.rs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/vendor/gix-config-value/src/integer.rs b/vendor/gix-config-value/src/integer.rs new file mode 100644 index 000000000..b287899ec --- /dev/null +++ b/vendor/gix-config-value/src/integer.rs @@ -0,0 +1,156 @@ +use std::{borrow::Cow, convert::TryFrom, fmt::Display, str::FromStr}; + +use bstr::{BStr, BString}; + +use crate::{Error, Integer}; + +impl Integer { + /// Canonicalize values as simple decimal numbers. + /// An optional suffix of k, m, or g (case-insensitive), will cause the + /// value to be multiplied by 1024 (k), 1048576 (m), or 1073741824 (g) respectively. + /// + /// Returns the result if there is no multiplication overflow. + pub fn to_decimal(&self) -> Option<i64> { + match self.suffix { + None => Some(self.value), + Some(suffix) => match suffix { + Suffix::Kibi => self.value.checked_mul(1024), + Suffix::Mebi => self.value.checked_mul(1024 * 1024), + Suffix::Gibi => self.value.checked_mul(1024 * 1024 * 1024), + }, + } + } +} + +impl Display for Integer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value)?; + if let Some(suffix) = self.suffix { + write!(f, "{suffix}") + } else { + Ok(()) + } + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Integer { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + if let Some(suffix) = self.suffix { + serializer.serialize_i64(self.value << suffix.bitwise_offset()) + } else { + serializer.serialize_i64(self.value) + } + } +} + +fn int_err(input: impl Into<BString>) -> Error { + Error::new( + "Integers needs to be positive or negative numbers which may have a suffix like 1k, 42, or 50G", + input, + ) +} + +impl TryFrom<&BStr> for Integer { + type Error = Error; + + fn try_from(s: &BStr) -> Result<Self, Self::Error> { + let s = std::str::from_utf8(s).map_err(|err| int_err(s).with_err(err))?; + if let Ok(value) = s.parse() { + return Ok(Self { value, suffix: None }); + } + + if s.len() <= 1 { + return Err(int_err(s)); + } + + let (number, suffix) = s.split_at(s.len() - 1); + if let (Ok(value), Ok(suffix)) = (number.parse(), suffix.parse()) { + Ok(Self { + value, + suffix: Some(suffix), + }) + } else { + Err(int_err(s)) + } + } +} + +impl TryFrom<Cow<'_, BStr>> for Integer { + type Error = Error; + + fn try_from(c: Cow<'_, BStr>) -> Result<Self, Self::Error> { + Self::try_from(c.as_ref()) + } +} + +/// Integer suffixes that are supported by `gix-config`. +/// +/// These values are base-2 unit of measurements, not the base-10 variants. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[allow(missing_docs)] +pub enum Suffix { + Kibi, + Mebi, + Gibi, +} + +impl Suffix { + /// Returns the number of bits that the suffix shifts left by. + #[must_use] + pub const fn bitwise_offset(self) -> usize { + match self { + Self::Kibi => 10, + Self::Mebi => 20, + Self::Gibi => 30, + } + } +} + +impl Display for Suffix { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Kibi => write!(f, "k"), + Self::Mebi => write!(f, "m"), + Self::Gibi => write!(f, "g"), + } + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Suffix { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + serializer.serialize_str(match self { + Self::Kibi => "k", + Self::Mebi => "m", + Self::Gibi => "g", + }) + } +} + +impl FromStr for Suffix { + type Err = (); + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "k" | "K" => Ok(Self::Kibi), + "m" | "M" => Ok(Self::Mebi), + "g" | "G" => Ok(Self::Gibi), + _ => Err(()), + } + } +} + +impl TryFrom<&BStr> for Suffix { + type Error = (); + + fn try_from(s: &BStr) -> Result<Self, Self::Error> { + Self::from_str(std::str::from_utf8(s).map_err(|_| ())?) + } +} |