taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

commit 06dd73e56e2893fabdb68e5f4d91bce8a647e453
parent 48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3
Author: Antoine A <>
Date:   Tue,  1 Sep 2026 18:31:43 +0200

common: improve config parsing

Diffstat:
Mcommon/taler-common/src/config.rs | 57+++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 51 insertions(+), 6 deletions(-)

diff --git a/common/taler-common/src/config.rs b/common/taler-common/src/config.rs @@ -770,9 +770,9 @@ macro_rules! map_config { $self.map($ty, $option, |value| { match value { $($key => { - (||Ok($parse))().map_err(|e| ::taler_common::config::MapErr::Err(e)) + (||Ok($parse))().map_err(|e| $crate::config::MapErr::Err(e)) })*, - _ => Err(::taler_common::config::MapErr::Invalid(keys)) + _ => Err($crate::config::MapErr::Invalid(keys)) } }) } @@ -816,7 +816,7 @@ impl<'cfg, 'arg> Section<'cfg, 'arg> { option: &'arg str, transform: impl FnOnce(&'cfg str) -> Result<T, MapErr>, ) -> Value<'arg, T> { - self.value(ty, option, |v| { + self.inner(ty, option, |v| { transform(v).map_err(|e| match e { MapErr::Invalid(keys) => { let mut buf = "expected '".to_owned(); @@ -1207,8 +1207,6 @@ mod test { ); } - const DEFAULT_CONF: &str = "[PATHS]\nDATADIR=mydir\nRECURSIVE=$RECURSIVE"; - #[allow(clippy::type_complexity)] fn routine<T: Debug + Eq>( ty: &str, @@ -1216,7 +1214,12 @@ mod test { wellformed: &[(&[&str], T)], malformed: &[(&[&str], fn(&str) -> String)], ) { - let conf = |content: &str| Config::from_mem(&format!("{DEFAULT_CONF}\n{content}")).unwrap(); + let conf = |content: &str| { + Config::from_mem(&format!( + "[PATHS]\nDATADIR=mydir\nRECURSIVE=$RECURSIVE\n{content}" + )) + .unwrap() + }; // Check missing msg let cfg = conf(""); @@ -1369,4 +1372,46 @@ mod test { ], ) } + + #[test] + fn map() { + #[derive(Debug, PartialEq, Eq)] + enum Mode { + Tcp(u16), + Unix, + Systemd, + } + + fn parse<'cfg, 'arg>(sect: &Section<'cfg, 'arg>, value: &'arg str) -> Value<'arg, Mode> { + map_config!(sect, "mode", value, + "tcp" => { Mode::Tcp(sect.number("PORT").require()?) }, + "unix" => { Mode::Unix }, + "systemd" => { Mode::Systemd }, + ) + } + + routine( + "mode", + parse, + &[(&["unix"], Mode::Unix), (&["systemd"], Mode::Systemd)], + &[(&["udp", "TCP"], |it| { + format!("expected 'tcp', 'unix' or 'systemd' got '{it}'") + })], + ); + + let cfg = Config::from_mem("[section]\nvalue=tcp").unwrap(); + + check_err( + "Missing number option PORT in section [section]", + parse(&cfg.section("section"), "value").require(), + ); + + check_err( + "Invalid mode option VALUE in section [section]: expected 'unix' got 'tcp'", + map_config!(&cfg.section("section"), "mode", "value", + "unix" => { Mode::Unix }, + ) + .require(), + ); + } }