根据字段类型有条件地生成From impl



我正在尝试创建一个通用impl,用于根据不同的字段类型生成From/Into。

链接到游乐场

我看到以下问题:

error[E0425]: cannot find value `item` in this scope
--> src/lib.rs:23:21
|
23 |             $param: item.$param,
|                     ^^^^ not found in this scope
...
65 | create_impl! { TargetStruct, InputStruct, { field1: Option<String>, field2: Option<Uuid> }}
| ------------------------------------------------------------------------------------------- in this macro invocation

如果可能的话,有人能为我指明正确的方向吗。在这一点上,我不确定如何将输入参数传递给规则。

谢谢!


#[macro_use]
macro_rules! create_impl {
( @ $target:ident, $input:ident, { } -> ($($result:tt)*) ) => (
impl From<$input> for $target {
fn from(item: $input) -> Self {
Self {
$($result)*
..Default::default()
}
}
});
( @ $target:ident, $input:ident, { $param:ident : Option<Uuid>, $($rest:tt)* } -> ($($result:tt)*) ) => (
create_impl!(@ $target, $input, { $($rest)* } -> (
$($result)*
$param: item.$param.map(|v| v.to_string()),
));
);
( @ $target:ident, $input:ident, { $param:ident : $type:ty, $($rest:tt)* } -> ($($result:tt)*) ) => (
create_impl!(@ $target, $input, { $($rest)* } -> (
$($result)*
$param: item.$param,
));
);

( @ $target:ident, $input:ident, { $param:ident : $type:ty, $($rest:tt)* } -> ($($result:tt)*) ) => (
create_impl!(@ $target, $input, { $($rest)* } -> (
$($result)*
$param: item.$param,
));
);
( $target:ident, $input:ident, { $( $param:ident : $type:ty ),* $(,)* } ) => (
create_impl!(@ $target, $input, { $($param : $type,)* } -> ());
);
}

你可以让铁锈来承担重任:

macro_rules! memberize_result {
($item: ident, $param:ident : Option<Uuid>) => (
$item.$param.map(|v| v.to_string())
);
($item: ident, $param:ident : Option<String>) => (
$item.$param
);
}
#[macro_use]
macro_rules! create_impl {
( $target:ident, $input:ident, { $( $param:ident : ($($type:tt)*) ),* $(,)* } ) => (
impl From<$input> for $target {
fn from(item: $input) -> Self {
Self {
$($param: memberize_result!(item, $param : $($type)*),)*
..Default::default()
}
}
}
);
}

use uuid::Uuid; // 0.8.1
#[derive(Default)]
pub struct InputStruct {
pub field1: Option<String>,
pub field2: Option<Uuid>,
}
#[derive(Default)]
pub struct TargetStruct {
pub field1: Option<String>,
pub field2: Option<String>,
}
// Trying to turn this into a macro
// impl From<ExampleStruct> for TargetStruct {
//     fn from(item: ExampleStruct) -> Self {
//         let mut res = Self::default();
//         res.field1 = item.field1;
//         res.field2 = item.field2.map(|v| v.to_string());
//         res
//     }
// }
create_impl! { TargetStruct, InputStruct, { field1: (Option<String>), field2: (Option<Uuid>) }}

最新更新