Patchwork D10021: rust: Move config value parsing functions to a new module

login
register
mail settings
Submitter phabricator
Date Feb. 19, 2021, 8:31 a.m.
Message ID <differential-rev-PHID-DREV-sttuqesizrhiepbn75km-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48337/
State Superseded
Headers show

Comments

phabricator - Feb. 19, 2021, 8:31 a.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10021

AFFECTED FILES
  rust/hg-core/src/config.rs
  rust/hg-core/src/config/config.rs
  rust/hg-core/src/config/values.rs

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/hg-core/src/config/values.rs b/rust/hg-core/src/config/values.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/config/values.rs
@@ -0,0 +1,43 @@ 
+//! Parsing functions for various type of configuration values.
+//!
+//! Returning `None` indicates a syntax error. Using a `Result` would be more
+//! correct but would take more boilerplate for converting between error types,
+//! compared to using `.ok()` on inner results of various error types to
+//! convert them all to options. The `Config::get_parse` method later converts
+//! those options to results with `ConfigValueParseError`, which contains
+//! details about where the value came from (but omits details of what’s
+//! invalid inside the value).
+
+pub(super) fn parse_bool(v: &[u8]) -> Option<bool> {
+    match v.to_ascii_lowercase().as_slice() {
+        b"1" | b"yes" | b"true" | b"on" | b"always" => Some(true),
+        b"0" | b"no" | b"false" | b"off" | b"never" => Some(false),
+        _ => None,
+    }
+}
+
+pub(super) fn parse_byte_size(value: &[u8]) -> Option<u64> {
+    let value = std::str::from_utf8(value).ok()?.to_ascii_lowercase();
+    const UNITS: &[(&str, u64)] = &[
+        ("g", 1 << 30),
+        ("gb", 1 << 30),
+        ("m", 1 << 20),
+        ("mb", 1 << 20),
+        ("k", 1 << 10),
+        ("kb", 1 << 10),
+        ("b", 1 << 0), // Needs to be last
+    ];
+    for &(unit, multiplier) in UNITS {
+        // TODO: use `value.strip_suffix(unit)` when we require Rust 1.45+
+        if value.ends_with(unit) {
+            let value_before_unit = &value[..value.len() - unit.len()];
+            let float: f64 = value_before_unit.trim().parse().ok()?;
+            if float >= 0.0 {
+                return Some((float * multiplier as f64).round() as u64);
+            } else {
+                return None;
+            }
+        }
+    }
+    value.parse().ok()
+}
diff --git a/rust/hg-core/src/config/config.rs b/rust/hg-core/src/config/config.rs
--- a/rust/hg-core/src/config/config.rs
+++ b/rust/hg-core/src/config/config.rs
@@ -8,6 +8,7 @@ 
 // GNU General Public License version 2 or any later version.
 
 use super::layer;
+use super::values;
 use crate::config::layer::{
     ConfigError, ConfigLayer, ConfigOrigin, ConfigValue,
 };
@@ -64,40 +65,6 @@ 
     pub expected_type: &'static str,
 }
 
-pub fn parse_bool(v: &[u8]) -> Option<bool> {
-    match v.to_ascii_lowercase().as_slice() {
-        b"1" | b"yes" | b"true" | b"on" | b"always" => Some(true),
-        b"0" | b"no" | b"false" | b"off" | b"never" => Some(false),
-        _ => None,
-    }
-}
-
-pub fn parse_byte_size(value: &[u8]) -> Option<u64> {
-    let value = str::from_utf8(value).ok()?.to_ascii_lowercase();
-    const UNITS: &[(&str, u64)] = &[
-        ("g", 1 << 30),
-        ("gb", 1 << 30),
-        ("m", 1 << 20),
-        ("mb", 1 << 20),
-        ("k", 1 << 10),
-        ("kb", 1 << 10),
-        ("b", 1 << 0), // Needs to be last
-    ];
-    for &(unit, multiplier) in UNITS {
-        // TODO: use `value.strip_suffix(unit)` when we require Rust 1.45+
-        if value.ends_with(unit) {
-            let value_before_unit = &value[..value.len() - unit.len()];
-            let float: f64 = value_before_unit.trim().parse().ok()?;
-            if float >= 0.0 {
-                return Some((float * multiplier as f64).round() as u64);
-            } else {
-                return None;
-            }
-        }
-    }
-    value.parse().ok()
-}
-
 impl Config {
     /// Load system and user configuration from various files.
     ///
@@ -324,7 +291,7 @@ 
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<u64>, ConfigValueParseError> {
-        self.get_parse(section, item, "byte quantity", parse_byte_size)
+        self.get_parse(section, item, "byte quantity", values::parse_byte_size)
     }
 
     /// Returns an `Err` if the first value found is not a valid boolean.
@@ -335,7 +302,7 @@ 
         section: &[u8],
         item: &[u8],
     ) -> Result<Option<bool>, ConfigValueParseError> {
-        self.get_parse(section, item, "boolean", parse_bool)
+        self.get_parse(section, item, "boolean", values::parse_bool)
     }
 
     /// Returns the corresponding boolean in the config. Returns `Ok(false)`
diff --git a/rust/hg-core/src/config.rs b/rust/hg-core/src/config.rs
--- a/rust/hg-core/src/config.rs
+++ b/rust/hg-core/src/config.rs
@@ -11,5 +11,6 @@ 
 
 mod config;
 mod layer;
+mod values;
 pub use config::{Config, ConfigValueParseError};
 pub use layer::{ConfigError, ConfigParseError};