changeset 51851:0dbf6a5ccf5f

rust-config: add more ways of reading the config These will be needed for future patches of this series to interpret more complex/different config values.
author Raphaël Gomès <rgomes@octobus.net>
date Wed, 19 Jun 2024 12:00:55 +0200
parents f5c46c3518a5
children 06549ab4281b
files rust/hg-core/src/config/config_items.rs rust/hg-core/src/config/mod.rs
diffstat 2 files changed, 178 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-core/src/config/config_items.rs	Tue Mar 26 15:51:31 2024 +0000
+++ b/rust/hg-core/src/config/config_items.rs	Wed Jun 19 12:00:55 2024 +0200
@@ -267,6 +267,66 @@
     }
 }
 
+impl TryFrom<&DefaultConfigItem> for Option<i64> {
+    type Error = HgError;
+
+    fn try_from(value: &DefaultConfigItem) -> Result<Self, Self::Error> {
+        match &value.default {
+            Some(default) => {
+                let err = HgError::abort(
+                    format!(
+                        "programming error: wrong query on config item '{}.{}'",
+                        value.section,
+                        value.name
+                    ),
+                    exit_codes::ABORT,
+                    Some(format!(
+                        "asked for 'i64', type of default is '{}'",
+                        default.type_str()
+                    )),
+                );
+                match default {
+                    DefaultConfigItemType::Primitive(
+                        toml::Value::Integer(b),
+                    ) => Ok(Some(*b)),
+                    _ => Err(err),
+                }
+            }
+            None => Ok(None),
+        }
+    }
+}
+
+impl TryFrom<&DefaultConfigItem> for Option<f64> {
+    type Error = HgError;
+
+    fn try_from(value: &DefaultConfigItem) -> Result<Self, Self::Error> {
+        match &value.default {
+            Some(default) => {
+                let err = HgError::abort(
+                    format!(
+                        "programming error: wrong query on config item '{}.{}'",
+                        value.section,
+                        value.name
+                    ),
+                    exit_codes::ABORT,
+                    Some(format!(
+                        "asked for 'f64', type of default is '{}'",
+                        default.type_str()
+                    )),
+                );
+                match default {
+                    DefaultConfigItemType::Primitive(toml::Value::Float(
+                        b,
+                    )) => Ok(Some(*b)),
+                    _ => Err(err),
+                }
+            }
+            None => Ok(None),
+        }
+    }
+}
+
 /// Allows abstracting over more complex default values than just primitives.
 /// The former `configitems.py` contained some dynamic code that is encoded
 /// in this enum.
--- a/rust/hg-core/src/config/mod.rs	Tue Mar 26 15:51:31 2024 +0000
+++ b/rust/hg-core/src/config/mod.rs	Wed Jun 19 12:00:55 2024 +0200
@@ -531,6 +531,54 @@
         )
     }
 
+    /// Returns an `Err` if the first value found is not a valid unsigned
+    /// integer. Otherwise, returns an `Ok(value)` if found, or `None`.
+    pub fn get_i64(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<i64>, HgError> {
+        self.get_parse(
+            section,
+            item,
+            "valid integer",
+            |value| str::from_utf8(value).ok()?.parse().ok(),
+            true,
+        )
+    }
+
+    /// Returns an `Err` if the first value found is not a valid unsigned
+    /// integer. Otherwise, returns an `Ok(value)` if found, or `None`.
+    pub fn get_u64(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<u64>, HgError> {
+        self.get_parse(
+            section,
+            item,
+            "valid integer",
+            |value| str::from_utf8(value).ok()?.parse().ok(),
+            true,
+        )
+    }
+
+    /// Returns an `Err` if the first value found is not a valid float
+    /// representation. Otherwise, returns an `Ok(value)` if found, or `None`.
+    pub fn get_f64(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<f64>, HgError> {
+        self.get_parse(
+            section,
+            item,
+            "valid float",
+            |value| str::from_utf8(value).ok()?.parse().ok(),
+            true,
+        )
+    }
+
     /// Returns an `Err` if the first value found is not a valid file size
     /// value such as `30` (default unit is bytes), `7 MB`, or `42.5 kb`.
     /// Otherwise, returns an `Ok(value_in_bytes)` if found, or `None`.
@@ -548,6 +596,22 @@
         )
     }
 
+    /// Same as [`Self::get_byte_size`], but doesn't fall back to the default
+    /// `configitem` if not defined in the user config.
+    pub fn get_byte_size_no_default(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> Result<Option<u64>, HgError> {
+        self.get_parse(
+            section,
+            item,
+            "byte quantity",
+            values::parse_byte_size,
+            false,
+        )
+    }
+
     /// Returns an `Err` if the first value found is not a valid boolean.
     /// Otherwise, returns an `Ok(option)`, where `option` is the boolean if
     /// found, or `None`.
@@ -744,6 +808,60 @@
     pub fn tweakdefaults(&mut self) {
         self.layers.insert(0, Config::tweakdefaults_layer());
     }
+
+    /// Return the resource profile for a dimension (memory, cpu or disk).
+    ///
+    /// If no dimension is specified, the generic value is returned.
+    pub fn get_resource_profile(
+        &self,
+        dimension: Option<&str>,
+    ) -> ResourceProfile {
+        let mut value = self.resource_profile_from_item(b"usage", b"resource");
+        if let Some(dimension) = &dimension {
+            let sub_value = self.resource_profile_from_item(
+                b"usage",
+                format!("resources.{}", dimension).as_bytes(),
+            );
+            if sub_value != ResourceProfileValue::Default {
+                value = sub_value
+            }
+        }
+        ResourceProfile {
+            dimension: dimension.map(ToOwned::to_owned),
+            value,
+        }
+    }
+
+    fn resource_profile_from_item(
+        &self,
+        section: &[u8],
+        item: &[u8],
+    ) -> ResourceProfileValue {
+        match self.get(section, item).unwrap_or(b"default") {
+            b"default" => ResourceProfileValue::Default,
+            b"low" => ResourceProfileValue::Low,
+            b"medium" => ResourceProfileValue::Medium,
+            b"high" => ResourceProfileValue::High,
+            _ => ResourceProfileValue::Default,
+        }
+    }
+}
+
+/// Corresponds to `usage.resources[.<dimension>]`.
+///
+/// See `hg help config.usage.resources`.
+#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
+pub struct ResourceProfile {
+    pub dimension: Option<String>,
+    pub value: ResourceProfileValue,
+}
+
+#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
+pub enum ResourceProfileValue {
+    Default,
+    Low,
+    Medium,
+    High,
 }
 
 #[cfg(test)]