0

I have a configuration struct like this:

pub struct Configuration {
    flag1: bool,
    flag2: String,
    flag3: i32,
    flag4: String
}

I want to generate a configuration file template that users can edit with values. I will allow users to pass the configuration file on startup and load it to the config struct.

Is there a way to generate this artifact through some sort of annotations?

I'm imaging something similar to "serde" but which generates the file:

#[derive(Template)] // create the file during build
pub struct Configuration {
    #[template(default = true)] // set some sort of defaults for the template file
    flag1: bool,
    #[template(default = "yes")]
    flag2: String,
    #[template(default = 42)]
    flag3: i32,
    #[template(default = "no")]
    flag4: String
}

The result will be a file like:

flag1: true
flag2: "yes"
flag3: 42
flag4: "no"
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
Avba
  • 14,822
  • 20
  • 92
  • 192
  • According to what I understand, you have a configuration file according to which you want to determine the default values for your struct? Maybe you can write a proc macro that implements the Default trait for the struct according to the file? – Mihir Luthra Nov 11 '20 at 09:20
  • the other way around. I want to provide default files which are aligned to my struct – Avba Nov 11 '20 at 09:24
  • Okay, correct me if I am wrong, you mean to associate a file with your struct such that if you make any changes to the struct, they are reflected in that file? If that's the case, what do you mean to do by placing `#[template(default = "yes")]` on each field? – Mihir Luthra Nov 11 '20 at 09:25
  • yes. so if i were to add another field to the struct, the template file would be generated again with that field added to it – Avba Nov 11 '20 at 09:27
  • AFAIK it's not possible to track changes to a field of `struct`. You could define setter methods like `fn set_flag1(&mut self, new_val: bool) {}` inside which you can have code to update struct & file. You could keep struct fields private so that modifications can only be done by these setter methods. Setter methods can be quite easily auto-generated by proc-macro (#[derive(..)]). – Mihir Luthra Nov 11 '20 at 09:53

1 Answers1

0

This looks like askama. It features an extensible template syntax and special support for HTML.

Rust example:

#[derive(Template)] ​// this will generate the code...​
#[template(path = ​"sample.conf", escape = "none"​)]
​struct​ ​SampleConfig<​'​a​> { ​// the name of the struct can be anything​
    b: &​'​a​ ​str​,
    c: Some(&'a str),​// the field name should match the variable name​
                   ​// in your template​
}

Template (in /templates/sample.conf):

field b: {{ b }}
{% match c %}
  {% when Some with (val) %}
    field c: {{ val }}
  {% when None %}
    field c: some default
{% endmatch %}

You can see more examples in the book

PS: As far as I know the default syntax isn't possible and need to be handled with match. Though keep in mind your templates will be preprocessed on compile time and packaged into your binary.

Cobalt
  • 447
  • 5
  • 9