summaryrefslogtreecommitdiffstats
path: root/vendor/gix-config-value/src/integer.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-config-value/src/integer.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-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.rs156
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(|_| ())?)
+ }
+}