Macro to derive field setters

Hello there!
I've got a quick question, does anyone know about a macro, that automatically derives macros for field setters?

I've got an example, of the code I'd like to have generated

struct Config {                                                                                                                                                                                                                             
      from: String,                                                                                                                                                                                                                           
      to: String,                                                                                                                                                                                                                             
      output: String,                                                                                                                                                                                                                         
  }                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                              
  impl Config {                                                                                                                                                                                                                               
     fn new() -> Config {                                                                                                                                                                                                                    
          Config {                                                                                                                                                                                                                            
              from: String::new(),                                                                                                                                                                                                            
              to: String::new(),                                                                                                                                                                                                              
              output: String::new(),                                                                                                                                                                                                          
          }                                                                                                                                                                                                                                   
      }                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                              
     fn to(mut self, value: String) -> Config {                                                                                                                                                                                              
          self.to = value;                                                                                                                                                                                                                    
          self                                                                                                                                                                                                                                
      }                                                                                                                                                                                                                                       
     fn output(mut self, value: String) -> Config {                                                                                                                                                                                          
          self.output = value;                                                                                                                                                                                                                
          self                                                                                                                                                                                                                                
      }                                                                                                                                                                                                                                       
     fn from(mut self, value: String) -> Config {                                                                                                                                                                                            
          self.from = value;                                                                                                                                                                                                                  
          self                                                                                                                                                                                                                                
      }                                                                                                                                                                                                                                       
  }    

As you see, the to(), output() and from() methods look quite generic and the process of writing them could be automated. Does anyone know about a macro in a crate that does just that?
Thank you!

You can use the crate ::getset if you don't mind the setters names being prefixed with set_ (sadly there does not seem to be a way to override this behavior):

#[derive(::getset::Setters)]
#[set]
struct Config {
    from: String,
    to: String,
    output: String,
}

Note that the generated functions return (), so they cannot be chained.

If you are interested in chaining setters for struct initialization, I recommend instead the ::derive_builder crate.

If you want to customize the macro and don't mind that the struct definition becomes a little bit more ugly, you can even go and roll your own macro_rules!:

/// Use a module to test privacy
mod lib {
    derive_setters! {
        #[derive(Debug, Default)]
        pub
        struct Config {
            pub // setter privacy (field is always private)
            from: String,

            pub // setter privacy (field is always private)
            to: String,

            pub // setter privacy (field is always private)
            output: String,
        }
    }
}
use self::lib::Config;

fn main ()
{
    let mut config = Config::default();
    config
        .from("from".into())
        .to("to".into())
        .output("output".into())
    ;
    dbg!(&config);
}
3 Likes

This is precisely what I’ve hoped to find, thank you very much!

Now with the ::macro_rules_attribute crate you can get the call-site ergonomics of a procedural macro while defining the logic "inline" (within the same crate) by using a macro_rules! macro:

#[macro_rules_attribute(derive_setters!)]
#[derive(Debug, Default)]
pub
struct Config {
    pub // setter privacy (field is always private)
    from: String,

    pub // setter privacy (field is always private)
    to: String,

    pub // setter privacy (field is always private)
    output: String,
}
2 Likes

thanks, I didn't knew about that and I'm definitely glad I caught this!