##// END OF EJS Templates
rust: Add a `ConfigValueParseError` variant to common errors...
Simon Sapin -
r47340:bc08c233 default
parent child Browse files
Show More
@@ -11,5 +11,5 b''
11 11
12 12 mod config;
13 13 mod layer;
14 pub use config::Config;
14 pub use config::{Config, ConfigValueParseError};
15 15 pub use layer::{ConfigError, ConfigParseError};
@@ -9,7 +9,7 b''
9 9
10 10 use super::layer;
11 11 use crate::config::layer::{
12 ConfigError, ConfigLayer, ConfigParseError, ConfigValue,
12 ConfigError, ConfigLayer, ConfigOrigin, ConfigValue,
13 13 };
14 14 use crate::utils::files::get_bytes_from_os_str;
15 15 use format_bytes::{write_bytes, DisplayBytes};
@@ -54,6 +54,16 b' pub enum ConfigSource {'
54 54 Parsed(layer::ConfigLayer),
55 55 }
56 56
57 #[derive(Debug)]
58 pub struct ConfigValueParseError {
59 pub origin: ConfigOrigin,
60 pub line: Option<usize>,
61 pub section: Vec<u8>,
62 pub item: Vec<u8>,
63 pub value: Vec<u8>,
64 pub expected_type: &'static str,
65 }
66
57 67 pub fn parse_bool(v: &[u8]) -> Option<bool> {
58 68 match v.to_ascii_lowercase().as_slice() {
59 69 b"1" | b"yes" | b"true" | b"on" | b"always" => Some(true),
@@ -262,15 +272,19 b' impl Config {'
262 272 &'config self,
263 273 section: &[u8],
264 274 item: &[u8],
275 expected_type: &'static str,
265 276 parse: impl Fn(&'config [u8]) -> Option<T>,
266 ) -> Result<Option<T>, ConfigParseError> {
277 ) -> Result<Option<T>, ConfigValueParseError> {
267 278 match self.get_inner(&section, &item) {
268 279 Some((layer, v)) => match parse(&v.bytes) {
269 280 Some(b) => Ok(Some(b)),
270 None => Err(ConfigParseError {
281 None => Err(ConfigValueParseError {
271 282 origin: layer.origin.to_owned(),
272 283 line: v.line,
273 bytes: v.bytes.to_owned(),
284 value: v.bytes.to_owned(),
285 section: section.to_owned(),
286 item: item.to_owned(),
287 expected_type,
274 288 }),
275 289 },
276 290 None => Ok(None),
@@ -283,8 +297,10 b' impl Config {'
283 297 &self,
284 298 section: &[u8],
285 299 item: &[u8],
286 ) -> Result<Option<&str>, ConfigParseError> {
287 self.get_parse(section, item, |value| str::from_utf8(value).ok())
300 ) -> Result<Option<&str>, ConfigValueParseError> {
301 self.get_parse(section, item, "ASCII or UTF-8 string", |value| {
302 str::from_utf8(value).ok()
303 })
288 304 }
289 305
290 306 /// Returns an `Err` if the first value found is not a valid unsigned
@@ -293,8 +309,8 b' impl Config {'
293 309 &self,
294 310 section: &[u8],
295 311 item: &[u8],
296 ) -> Result<Option<u32>, ConfigParseError> {
297 self.get_parse(section, item, |value| {
312 ) -> Result<Option<u32>, ConfigValueParseError> {
313 self.get_parse(section, item, "valid integer", |value| {
298 314 str::from_utf8(value).ok()?.parse().ok()
299 315 })
300 316 }
@@ -306,8 +322,8 b' impl Config {'
306 322 &self,
307 323 section: &[u8],
308 324 item: &[u8],
309 ) -> Result<Option<u64>, ConfigParseError> {
310 self.get_parse(section, item, parse_byte_size)
325 ) -> Result<Option<u64>, ConfigValueParseError> {
326 self.get_parse(section, item, "byte quantity", parse_byte_size)
311 327 }
312 328
313 329 /// Returns an `Err` if the first value found is not a valid boolean.
@@ -317,8 +333,8 b' impl Config {'
317 333 &self,
318 334 section: &[u8],
319 335 item: &[u8],
320 ) -> Result<Option<bool>, ConfigParseError> {
321 self.get_parse(section, item, parse_bool)
336 ) -> Result<Option<bool>, ConfigValueParseError> {
337 self.get_parse(section, item, "boolean", parse_bool)
322 338 }
323 339
324 340 /// Returns the corresponding boolean in the config. Returns `Ok(false)`
@@ -327,7 +343,7 b' impl Config {'
327 343 &self,
328 344 section: &[u8],
329 345 item: &[u8],
330 ) -> Result<bool, ConfigError> {
346 ) -> Result<bool, ConfigValueParseError> {
331 347 Ok(self.get_option(section, item)?.unwrap_or(false))
332 348 }
333 349
@@ -1,7 +1,8 b''
1 use crate::config::ConfigValueParseError;
1 2 use std::fmt;
2 3
3 4 /// Common error cases that can happen in many different APIs
4 #[derive(Debug)]
5 #[derive(Debug, derive_more::From)]
5 6 pub enum HgError {
6 7 IoError {
7 8 error: std::io::Error,
@@ -29,6 +30,14 b' pub enum HgError {'
29 30 /// The given string is a short explanation for users, not intended to be
30 31 /// machine-readable.
31 32 Abort(String),
33
34 /// A configuration value is not in the expected syntax.
35 ///
36 /// These errors can happen in many places in the code because values are
37 /// parsed lazily as the file-level parser does not know the expected type
38 /// and syntax of each value.
39 #[from]
40 ConfigValueParseError(ConfigValueParseError),
32 41 }
33 42
34 43 /// Details about where an I/O error happened
@@ -63,6 +72,7 b' impl HgError {'
63 72 impl fmt::Display for HgError {
64 73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 74 match self {
75 HgError::Abort(explanation) => write!(f, "{}", explanation),
66 76 HgError::IoError { error, context } => {
67 77 write!(f, "{}: {}", error, context)
68 78 }
@@ -72,7 +82,25 b' impl fmt::Display for HgError {'
72 82 HgError::UnsupportedFeature(explanation) => {
73 83 write!(f, "unsupported feature: {}", explanation)
74 84 }
75 HgError::Abort(explanation) => explanation.fmt(f),
85 HgError::ConfigValueParseError(ConfigValueParseError {
86 origin: _,
87 line: _,
88 section,
89 item,
90 value,
91 expected_type,
92 }) => {
93 // TODO: add origin and line number information, here and in
94 // corresponding python code
95 write!(
96 f,
97 "config error: {}.{} is not a {} ('{}')",
98 String::from_utf8_lossy(section),
99 String::from_utf8_lossy(item),
100 expected_type,
101 String::from_utf8_lossy(value)
102 )
103 }
76 104 }
77 105 }
78 106 }
General Comments 0
You need to be logged in to leave comments. Login now