基本上,目标是能够采用如下结构:
struct Test
{
id : i64,
name : String,
data : HashMap<String, String>,
}
然后让宏返回一个字段类型的元组,按照我们声明test字段的顺序,如下所示:所以它可以用在下面的上下文中,例如scylla::IntoTypedRows;
rows.into_typed::<(get_field_types!(Test))>()
而不是目前的方式,即:
rows.into_typed::<(i64, String, HashMap<String, String>)>()
这样,当结构变得更大时,它不会变得乏味或庞大。
我遇到的问题是,我能够返回一个Vec<&str>,但似乎无法解释如何让它完成上述任务。这是我的尝试:
macro_rules! get_field_types {
($struct_name:ty) => {
{
let mut field_types = Vec::new();
let _ = <$struct_name>::default(); // Ensure the struct is instantiated
let field_values = stringify!($struct_name {
$(field: _type,)*
..
});
let field_pairs = field_values.split(',').filter_map(|field_value| {
let field_type = field_value.split_whitespace().nth(1)?;
Some(field_type.trim_end_matches(',').trim())
});
field_types.extend(field_pairs);
field_types
}
};
}
1条答案
按热度按时间ctehm74n1#
PitaJ在这里是正确的,你应该使用
#[derive(FromRow)]
和rows.into_typed::<Test>()
来做这件事,因为它节省了维护宏的麻烦,并使你的结构更灵活。本着学习的精神,下面是如何使用声明性宏来实现这一点。虽然宏目前还不能做查找(如果它们能做的话,我会很惊讶),但你可以像这样在结构声明中应用它们:
它使用
paste
crate来连接结构名称和FieldTypes
来生成类型定义,这样你就可以用它来定义多个字段元组类型,而不会相互冲突。