rust: Move config value parsing functions to a new module
Differential Revision: https://phab.mercurial-scm.org/D10021
--- a/rust/hg-core/src/config.rs Tue Feb 16 13:08:37 2021 +0100
+++ b/rust/hg-core/src/config.rs Wed Feb 17 20:24:04 2021 +0100
@@ -11,5 +11,6 @@
mod config;
mod layer;
+mod values;
pub use config::{Config, ConfigValueParseError};
pub use layer::{ConfigError, ConfigParseError};
--- a/rust/hg-core/src/config/config.rs Tue Feb 16 13:08:37 2021 +0100
+++ b/rust/hg-core/src/config/config.rs Wed Feb 17 20:24:04 2021 +0100
@@ -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)`
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-core/src/config/values.rs Wed Feb 17 20:24:04 2021 +0100
@@ -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()
+}