我正在尝试创建一个宏以生成可以从postgres数据库填充的结构。 现在,由于db中有一些可为空和不可为空的字段,因此我想在宏中以不同的方式处理它们。
输出应该是这样的结构:
#[derive(Debug, Default)]
pub struct MyStruct {
pub attrib_a: i64,
pub attrib_b: Option<i64>,
}
impl MyStruct {
pub fn get_row(&self, row: &postgres::rows::Row) -> MyStruct {
MyStruct {
// the non-nullable attrib_a, where I can for sure take the value out of the Option and assign it
attrib_a: match row.get::<_, Option<i64>>("attrib_a") {
Some(x) => x,
None => 0,
},
// here for the nullable attrib_b I just want to return the Option as is
attrib_b: row.get::<_, Option<i64>>("attrib_b"),
}
}
}
这是当前的宏代码:
macro_rules! make_table_struct {
($tname: stmt => $sname: ident; $($fname: ident: $ftype: ty),+) => {
#[derive(Debug, Clone, Default)]
pub struct $sname {
$(
pub $fname: $ftype,
)+
}
impl $sname
{
pub fn get_row(&self,row:&postgres::rows::Row)->$sname
{
$sname
{
//How do I know if I have an Option here or not and act then accordingly?
$(
$fname: row.get::<_,Option<$ftype>>(stringify!($fname)),
)+
}
}
}
}
}
宏呼叫:
make_table_struct! ("source_table_name" => MyStruct; attrib_a: i64, attrib_b: Option<i64>)
答案 0 :(得分:3)
这是一个带有$fname
和一个类型的宏,它可以是可选的。如果类型是可选的,则它将生成另一个函数,如果不是,则该函数:
macro_rules! make_get_row {
($fname: ident, Option<$ftype: ty>) => {
fn $fname(i: Option<$ftype>) -> i64 {
i.unwrap_or(0)
}
};
($fname: ident, $ftype: ty) => {
fn $fname(i: $ftype) -> i64 {
i
}
};
}
make_get_row!(direct, i64);
make_get_row!(via_op, Option<i64>);
fn main() {
direct(1);
via_op(Some(1));
}
您应该可以在make_table_struct
中使用此宏的(可能已调整)变体。
以下内容不是生产质量,但可能会带您到某个地方:
macro_rules! get_table_row {
($row: ident, nonnullable $fname:ident: $ftype:ty) => {
$row.get::<_,$ftype>(stringify!($fname))
};
($row: ident, nullable $fname:ident: $ftype:ty) => {
match $row.get::<_,Option<Option<$ftype>>>(stringify!($fname)) { Some(x) => x, None => Some(0) }
}
}
type nullable<T> = Option<T>;
type nonnullable<T> = T;
macro_rules! make_table_struct {
($tname:stmt => $sname:ident; $($nul: ident $fname:ident: $ftype:tt),+) => {
#[derive(Debug, Clone, Default)]
pub struct $sname {
$(
pub $fname: $nul < $ftype >,
)+
}
impl $sname {
pub fn get_row(&self, row: &postgres::rows::Row) -> $sname {
$(
let $fname = get_table_row!(row, $nul $fname: $ftype);
)+
$sname {
$($fname,)+
}
}
}
}
}
make_table_struct! ("source_table_name" => MyStruct; nonnullable attrib_a: i64, nullable attrib_b: i64);