Skip to content

Commit 78433a7

Browse files
authored
fix: document and fix macro hygiene for config_field! (apache#16473)
1 parent fb01049 commit 78433a7

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

datafusion/common/src/config.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,10 @@ impl<F: ConfigField + Default> ConfigField for Option<F> {
12481248
}
12491249
}
12501250

1251-
fn default_transform<T>(input: &str) -> Result<T>
1251+
/// Default transformation to parse a [`ConfigField`] for a string.
1252+
///
1253+
/// This uses [`FromStr`] to parse the data.
1254+
pub fn default_config_transform<T>(input: &str) -> Result<T>
12521255
where
12531256
T: FromStr,
12541257
<T as FromStr>::Err: Sync + Send + Error + 'static,
@@ -1265,19 +1268,45 @@ where
12651268
})
12661269
}
12671270

1271+
/// Macro that generates [`ConfigField`] for a given type.
1272+
///
1273+
/// # Usage
1274+
/// This always requires [`Display`] to be implemented for the given type.
1275+
///
1276+
/// There are two ways to invoke this macro. The first one uses
1277+
/// [`default_config_transform`]/[`FromStr`] to parse the data:
1278+
///
1279+
/// ```ignore
1280+
/// config_field(MyType);
1281+
/// ```
1282+
///
1283+
/// Note that the parsing error MUST implement [`std::error::Error`]!
1284+
///
1285+
/// Or you can specify how you want to parse an [`str`] into the type:
1286+
///
1287+
/// ```ignore
1288+
/// fn parse_it(s: &str) -> Result<MyType> {
1289+
/// ...
1290+
/// }
1291+
///
1292+
/// config_field(
1293+
/// MyType,
1294+
/// value => parse_it(value)
1295+
/// );
1296+
/// ```
12681297
#[macro_export]
12691298
macro_rules! config_field {
12701299
($t:ty) => {
1271-
config_field!($t, value => default_transform(value)?);
1300+
config_field!($t, value => $crate::config::default_config_transform(value)?);
12721301
};
12731302

12741303
($t:ty, $arg:ident => $transform:expr) => {
1275-
impl ConfigField for $t {
1276-
fn visit<V: Visit>(&self, v: &mut V, key: &str, description: &'static str) {
1304+
impl $crate::config::ConfigField for $t {
1305+
fn visit<V: $crate::config::Visit>(&self, v: &mut V, key: &str, description: &'static str) {
12771306
v.some(key, self, description)
12781307
}
12791308

1280-
fn set(&mut self, _: &str, $arg: &str) -> Result<()> {
1309+
fn set(&mut self, _: &str, $arg: &str) -> $crate::error::Result<()> {
12811310
*self = $transform;
12821311
Ok(())
12831312
}
@@ -1286,7 +1315,7 @@ macro_rules! config_field {
12861315
}
12871316

12881317
config_field!(String);
1289-
config_field!(bool, value => default_transform(value.to_lowercase().as_str())?);
1318+
config_field!(bool, value => default_config_transform(value.to_lowercase().as_str())?);
12901319
config_field!(usize);
12911320
config_field!(f64);
12921321
config_field!(u64);

datafusion/core/tests/macro_hygiene/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,40 @@ mod config_namespace {
6565
}
6666
}
6767
}
68+
69+
mod config_field {
70+
// NO other imports!
71+
use datafusion_common::config_field;
72+
73+
#[test]
74+
fn test_macro() {
75+
#[derive(Debug)]
76+
struct E;
77+
78+
impl std::fmt::Display for E {
79+
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80+
unimplemented!()
81+
}
82+
}
83+
84+
impl std::error::Error for E {}
85+
86+
struct S;
87+
88+
impl std::str::FromStr for S {
89+
type Err = E;
90+
91+
fn from_str(_s: &str) -> Result<Self, Self::Err> {
92+
unimplemented!()
93+
}
94+
}
95+
96+
impl std::fmt::Display for S {
97+
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98+
unimplemented!()
99+
}
100+
}
101+
102+
config_field!(S);
103+
}
104+
}

0 commit comments

Comments
 (0)