Refactor toml destructure matching.

Use accessor functionality and function chaining now.
This commit is contained in:
Matthias Beyer 2018-01-04 23:08:14 +01:00
parent 4184a1e5d0
commit d5ce99b170

View file

@ -238,16 +238,16 @@ fn aggregate_global_loglevel(matches: &ArgMatches, config: Option<&Value>)
} }
if let Some(cfg) = config { if let Some(cfg) = config {
let cfg_loglevel = match cfg.read("imag.logging.level") { let cfg_loglevel = cfg
Ok(Some(&Value::String(ref s))) => match_log_level_str(s), .read("imag.logging.level")?
Ok(Some(_)) => { .ok_or(RE::from_kind(EK::GlobalLogLevelConfigMissing))?
.as_str()
.ok_or_else(|| {
let path = "imag.logging.level".to_owned(); let path = "imag.logging.level".to_owned();
let ty = "String"; let ty = "String";
return Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })
Ok(None) => return Err(RE::from_kind(EK::GlobalLogLevelConfigMissing)), .and_then(match_log_level_str)?;
Err(e) => return Err(e).map_err(From::from),
}?;
if let Some(cli_loglevel) = get_arg_loglevel(matches)? { if let Some(cli_loglevel) = get_arg_loglevel(matches)? {
if cli_loglevel > cfg_loglevel { if cli_loglevel > cfg_loglevel {
@ -285,14 +285,13 @@ fn translate_destinations(raw: &Vec<Value>) -> Result<Vec<LogDestination>> {
raw.iter() raw.iter()
.fold(Ok(vec![]), |acc, val| { .fold(Ok(vec![]), |acc, val| {
acc.and_then(|mut v| { acc.and_then(|mut v| {
let dest = match *val { let dest = val.as_str()
Value::String(ref s) => translate_destination(s)?, .ok_or_else(|| {
_ => {
let path = "imag.logging.modules.<mod>.destinations".to_owned(); let path = "imag.logging.modules.<mod>.destinations".to_owned();
let ty = "Array<String>"; let ty = "Array<String>";
return Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })
}; .and_then(translate_destination)?;
v.push(dest); v.push(dest);
Ok(v) Ok(v)
}) })
@ -304,16 +303,16 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Value>)
{ {
match config { match config {
Some(cfg) => match cfg.read("imag.logging.destinations") { Some(cfg) => cfg
Ok(Some(&Value::Array(ref a))) => translate_destinations(a), .read("imag.logging.destinations")?
Ok(Some(_)) => { .ok_or_else(|| RE::from_kind(EK::GlobalDestinationConfigMissing))?
.as_array()
.ok_or_else(|| {
let path = "imag.logging.destinations".to_owned(); let path = "imag.logging.destinations".to_owned();
let ty = "Array"; let ty = "Array";
Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })
Ok(None) => Err(RE::from_kind(EK::GlobalDestinationConfigMissing)), .and_then(translate_destinations),
Err(e) => Err(e).map_err(From::from),
},
None => { None => {
if let Some(values) = matches.value_of(Runtime::arg_logdest_name()) { if let Some(values) = matches.value_of(Runtime::arg_logdest_name()) {
// parse logdest specification from commandline // parse logdest specification from commandline
@ -334,12 +333,12 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Value>)
macro_rules! aggregate_global_format { macro_rules! aggregate_global_format {
($read_str:expr, $error_kind_if_missing:expr, $config:expr) => { ($read_str:expr, $error_kind_if_missing:expr, $config:expr) => {
match try!($config.ok_or(RE::from_kind($error_kind_if_missing))).read($read_str) { try!($config.ok_or(RE::from_kind($error_kind_if_missing)))
Ok(Some(&Value::String(ref s))) => Ok(s.clone()), .read($read_str)?
Ok(Some(_)) => Err(RE::from_kind(EK::ConfigTypeError($read_str.to_owned(), "String"))), .ok_or_else(|| RE::from_kind($error_kind_if_missing))?
Ok(None) => Err(RE::from_kind($error_kind_if_missing)), .as_str()
Err(e) => Err(e).map_err(From::from), .map(String::from)
} .ok_or_else(|| RE::from_kind(EK::ConfigTypeError($read_str.to_owned(), "String")))
}; };
} }
@ -386,6 +385,18 @@ fn aggregate_global_format_error(config: Option<&Value>)
fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>) fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
-> Result<BTreeMap<ModuleName, ModuleSettings>> -> Result<BTreeMap<ModuleName, ModuleSettings>>
{ {
// Helper macro to return the error from Some(Err(_)) and map everything else to an
// Option<_>
macro_rules! inner_try {
($v:expr) => {
match $v {
Some(Ok(v)) => Some(v),
Some(Err(e)) => return Err(e),
None => None,
}
}
};
match config { match config {
Some(cfg) => match cfg.read("imag.logging.modules") { Some(cfg) => match cfg.read("imag.logging.modules") {
Ok(Some(&Value::Table(ref t))) => { Ok(Some(&Value::Table(ref t))) => {
@ -393,35 +404,39 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
let mut settings = BTreeMap::new(); let mut settings = BTreeMap::new();
for (module_name, v) in t { for (module_name, v) in t {
let destinations = match v.read("destinations")? { let destinations = inner_try! {
Some(&Value::Array(ref a)) => Some(translate_destinations(a)?), v.read("destinations")?
None => None, .map(|val| {
Some(_) => { val.as_array()
.ok_or_else(|| {
let path = "imag.logging.modules.<mod>.destinations".to_owned(); let path = "imag.logging.modules.<mod>.destinations".to_owned();
let ty = "Array"; let ty = "Array";
return Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })
.and_then(translate_destinations)
})
}; };
let level = match v.read("level")? { let level = inner_try! {
Some(&Value::String(ref s)) => Some(match_log_level_str(s)?), v.read("level")?
None => None, .map(|val| {
Some(_) => { val.as_str()
.ok_or_else(|| {
let path = "imag.logging.modules.<mod>.level".to_owned(); let path = "imag.logging.modules.<mod>.level".to_owned();
let ty = "String"; let ty = "String";
return Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })
.and_then(match_log_level_str)
})
}; };
let enabled = match v.read("enabled")? { let enabled = v.read("enabled")?
Some(&Value::Boolean(b)) => b, .map(|v| v.as_bool().unwrap_or(false))
None => false, .ok_or_else(|| {
Some(_) => {
let path = "imag.logging.modules.<mod>.enabled".to_owned(); let path = "imag.logging.modules.<mod>.enabled".to_owned();
let ty = "Boolean"; let ty = "Boolean";
return Err(RE::from_kind(EK::ConfigTypeError(path, ty))) RE::from_kind(EK::ConfigTypeError(path, ty))
}, })?;
};
let module_settings = ModuleSettings { let module_settings = ModuleSettings {
enabled: enabled, enabled: enabled,