1

I am trying to make a macro that generates a struct with a new function implementation. The new function needs to call functions based on the type of the field and use the return value as the field value.

The new implementation should end up working like this:

struct foo {
    test: i32,
    other: String,
}

impl foo {
    fn new() -> Self {
        foo {
           test: get_i32(),
           other: get_string(),
        }
    }
}

This is the current code I have:

macro_rules! test {
    (struct $name:ident { $($fname:ident : $ftype:ty),* }) => {
        #[derive(Debug)]
        pub struct $name {
            $(pub $fname : $ftype),*
        }

        impl $name {
            fn new(mut v: Vec<u8>) -> Self {
                $name {
                    $($fname : ),*
                }
            }
        }
    };
}

I have tried putting a match statement but it gives incompatible arms types error.

impl $name {
    fn new(mut v: Vec<u8>) -> Self {
        $name {
            $($fname : match &stringify!($ftype)[..] {
                "i32" => get_i32(),
                "String" => get_string(),
            }),*
        }
    }
}

Thank you.

nnnmmm
  • 7,964
  • 4
  • 22
  • 41
Gus
  • 151
  • 2
  • 15
  • You tried putting a match statement; could you show us what you've tried? Right now it's a bit hard to tell what your problem actually is. – Frxstrem May 10 '20 at 16:26
  • @Frxstrem I added how I attempted to do the match but it gives the error : "`match` arms have incompatible types" and "expected `i32`, found struct `std::string::String`". – Gus May 10 '20 at 16:52

1 Answers1

2

I managed to use another function that returns any to get it to work.

macro_rules! test {
    (struct $name:ident { $($fname:ident : $ftype:ty),* }) => {
        #[derive(Debug)]
        pub struct $name {
            $(pub $fname : $ftype),*
        }

        impl $name {
            fn new(mut v: Vec<u8>) -> Self {
                $name {
                    $($fname : get_feild::<$ftype>(stringify!($ftype)).downcast_ref::<$ftype>().unwrap().clone()),*
                }
            }
        }
    };
}

fn get_feild<T>(t: &str) -> Box<dyn std::any::Any> {
    match t {
        "i32" => Box::new(get_i32()),
        "String" => Box::new(get_string()),
        _ => panic!("UNKNOWN TYPE"),
    }
}
Gus
  • 151
  • 2
  • 15