How to implement a trait with a macro only if a struct has a field

I want to always call a macro on any struct, but only implement TryInto<u8> in the case where such struct has a field named ˋstatusˋ:

#[macro_export]
macro_rules! impl_status {
    (
        struct $name:ident {
            status: $status_type:ty,
            $($rest:tt)*
        }
    ) => {
        #[allow(dead_code)]
        impl TryInto<u8> for $name {
            type Error = ();

            fn try_into(
                self,
            ) -> Result<u8, Self::Error> {
               todo!()
            }
        }
    };
    (
        struct $name:ident {
            $($field:ident : $type:ty),*
        }
    ) => {
        impl TryInto<()> for $name {
            type Error = ();

            fn try_into(self) -> Result<(), Self::Error> {
                Ok(())
            }
        }
    };
}

pub struct HasStatusStruct {
    status: u8
}

impl_status!{HasStatusStruct}

I know why this does not work: ˋHasStatusStructˋ is purely a name and not a struct definition.

How do I solve this?

The only way to do this is if the macro wraps the struct definition. Normally you'd do this with a procedural derive macro, but you could do it with a declarative macro, it would just look a little weird.

impl_status! {
    pub struct HasStatusStruct {
        status: u8
    }
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.