根据字段类型有条件地生成 From impl
Conditionally generate a From impl based on field type
我正在尝试创建一个通用实现,用于根据不同的字段类型生成 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,)* } -> ());
);
}
您可以让 Rust 完成繁重的工作:
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>) }}
我正在尝试创建一个通用实现,用于根据不同的字段类型生成 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,)* } -> ());
);
}
您可以让 Rust 完成繁重的工作:
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>) }}