Hi,
Goal:
I've spent the entire afternoon trying to write a macro-by-example that:
- expands to an implementation item,
impl From<T> for U
block, for a givenU
w.r.t eachT
supplied - in addition, within the implementation item, adds documentation for the
from()
method
What I achieved now:
I can easily achieve the first goal, with something like this
macro_rules! _impl_from {
($to_type: ty, $($from_type: ty), +) => {
$(
impl From<$from_type> for $to_type {
fn from(value: $from_type) -> Self {
//...omitted
}
}
)+
};
}
So for example, I can use _impl_from!(Foo, Bar, Xyz);
to expands to these implementations
impl From<Bar> for Foo
impl From<Xyz> for Foo
Current challenge:
What I cannot achieve is, I want the macro also adds the documentation string. For example, I wish
_impl_foo!(Foo, Bar);
would expands to
impl From<Bar> for Foo {
#[doc = "Converts Bar to Foo"]
fn from(value: Bar) -> Self {
//...omitted
}
}
But somehow I cannot work this out. I tried to add
#[doc = concat!("Converts ", stringify!($from_type), " to ", stringify!($to_type))
just above the line
fn from(value: $from_type) -> Self {
But it complains something like it's not expecting concat!
.
It seems that writing down my challenge cleared my mind a bit. I've got it working now.
macro_rules! _fn_with_doc {
($doc: expr, $fn_body: item) => {
#[doc = $doc]
$fn_body
};
}
macro_rules! impl_from_via {
($to_type:tt, $via_type:tt, $($from_type:tt), +) => {
$(
impl From<$from_type> for $to_type {
_fn_with_doc!(
concat!(
"Converts `",
stringify!($from_type),
"` to `",
stringify!($to_type),
"` via `",
stringify!($via_type),
"`."
),
fn from(color: $from_type) -> Self {
Self::from(<$via_type>::from(color))
}
);
}
)+
};
}