Show More
@@ -0,0 +1,43 b'' | |||
|
1 | //! Parsing functions for various type of configuration values. | |
|
2 | //! | |
|
3 | //! Returning `None` indicates a syntax error. Using a `Result` would be more | |
|
4 | //! correct but would take more boilerplate for converting between error types, | |
|
5 | //! compared to using `.ok()` on inner results of various error types to | |
|
6 | //! convert them all to options. The `Config::get_parse` method later converts | |
|
7 | //! those options to results with `ConfigValueParseError`, which contains | |
|
8 | //! details about where the value came from (but omits details of whatβs | |
|
9 | //! invalid inside the value). | |
|
10 | ||
|
11 | pub(super) fn parse_bool(v: &[u8]) -> Option<bool> { | |
|
12 | match v.to_ascii_lowercase().as_slice() { | |
|
13 | b"1" | b"yes" | b"true" | b"on" | b"always" => Some(true), | |
|
14 | b"0" | b"no" | b"false" | b"off" | b"never" => Some(false), | |
|
15 | _ => None, | |
|
16 | } | |
|
17 | } | |
|
18 | ||
|
19 | pub(super) fn parse_byte_size(value: &[u8]) -> Option<u64> { | |
|
20 | let value = std::str::from_utf8(value).ok()?.to_ascii_lowercase(); | |
|
21 | const UNITS: &[(&str, u64)] = &[ | |
|
22 | ("g", 1 << 30), | |
|
23 | ("gb", 1 << 30), | |
|
24 | ("m", 1 << 20), | |
|
25 | ("mb", 1 << 20), | |
|
26 | ("k", 1 << 10), | |
|
27 | ("kb", 1 << 10), | |
|
28 | ("b", 1 << 0), // Needs to be last | |
|
29 | ]; | |
|
30 | for &(unit, multiplier) in UNITS { | |
|
31 | // TODO: use `value.strip_suffix(unit)` when we require Rust 1.45+ | |
|
32 | if value.ends_with(unit) { | |
|
33 | let value_before_unit = &value[..value.len() - unit.len()]; | |
|
34 | let float: f64 = value_before_unit.trim().parse().ok()?; | |
|
35 | if float >= 0.0 { | |
|
36 | return Some((float * multiplier as f64).round() as u64); | |
|
37 | } else { | |
|
38 | return None; | |
|
39 | } | |
|
40 | } | |
|
41 | } | |
|
42 | value.parse().ok() | |
|
43 | } |
@@ -11,5 +11,6 b'' | |||
|
11 | 11 | |
|
12 | 12 | mod config; |
|
13 | 13 | mod layer; |
|
14 | mod values; | |
|
14 | 15 | pub use config::{Config, ConfigValueParseError}; |
|
15 | 16 | pub use layer::{ConfigError, ConfigParseError}; |
@@ -8,6 +8,7 b'' | |||
|
8 | 8 | // GNU General Public License version 2 or any later version. |
|
9 | 9 | |
|
10 | 10 | use super::layer; |
|
11 | use super::values; | |
|
11 | 12 | use crate::config::layer::{ |
|
12 | 13 | ConfigError, ConfigLayer, ConfigOrigin, ConfigValue, |
|
13 | 14 | }; |
@@ -64,40 +65,6 b' pub struct ConfigValueParseError {' | |||
|
64 | 65 | pub expected_type: &'static str, |
|
65 | 66 | } |
|
66 | 67 | |
|
67 | pub fn parse_bool(v: &[u8]) -> Option<bool> { | |
|
68 | match v.to_ascii_lowercase().as_slice() { | |
|
69 | b"1" | b"yes" | b"true" | b"on" | b"always" => Some(true), | |
|
70 | b"0" | b"no" | b"false" | b"off" | b"never" => Some(false), | |
|
71 | _ => None, | |
|
72 | } | |
|
73 | } | |
|
74 | ||
|
75 | pub fn parse_byte_size(value: &[u8]) -> Option<u64> { | |
|
76 | let value = str::from_utf8(value).ok()?.to_ascii_lowercase(); | |
|
77 | const UNITS: &[(&str, u64)] = &[ | |
|
78 | ("g", 1 << 30), | |
|
79 | ("gb", 1 << 30), | |
|
80 | ("m", 1 << 20), | |
|
81 | ("mb", 1 << 20), | |
|
82 | ("k", 1 << 10), | |
|
83 | ("kb", 1 << 10), | |
|
84 | ("b", 1 << 0), // Needs to be last | |
|
85 | ]; | |
|
86 | for &(unit, multiplier) in UNITS { | |
|
87 | // TODO: use `value.strip_suffix(unit)` when we require Rust 1.45+ | |
|
88 | if value.ends_with(unit) { | |
|
89 | let value_before_unit = &value[..value.len() - unit.len()]; | |
|
90 | let float: f64 = value_before_unit.trim().parse().ok()?; | |
|
91 | if float >= 0.0 { | |
|
92 | return Some((float * multiplier as f64).round() as u64); | |
|
93 | } else { | |
|
94 | return None; | |
|
95 | } | |
|
96 | } | |
|
97 | } | |
|
98 | value.parse().ok() | |
|
99 | } | |
|
100 | ||
|
101 | 68 | impl Config { |
|
102 | 69 | /// Load system and user configuration from various files. |
|
103 | 70 | /// |
@@ -324,7 +291,7 b' impl Config {' | |||
|
324 | 291 | section: &[u8], |
|
325 | 292 | item: &[u8], |
|
326 | 293 | ) -> Result<Option<u64>, ConfigValueParseError> { |
|
327 | self.get_parse(section, item, "byte quantity", parse_byte_size) | |
|
294 | self.get_parse(section, item, "byte quantity", values::parse_byte_size) | |
|
328 | 295 | } |
|
329 | 296 | |
|
330 | 297 | /// Returns an `Err` if the first value found is not a valid boolean. |
@@ -335,7 +302,7 b' impl Config {' | |||
|
335 | 302 | section: &[u8], |
|
336 | 303 | item: &[u8], |
|
337 | 304 | ) -> Result<Option<bool>, ConfigValueParseError> { |
|
338 | self.get_parse(section, item, "boolean", parse_bool) | |
|
305 | self.get_parse(section, item, "boolean", values::parse_bool) | |
|
339 | 306 | } |
|
340 | 307 | |
|
341 | 308 | /// Returns the corresponding boolean in the config. Returns `Ok(false)` |
General Comments 0
You need to be logged in to leave comments.
Login now