1 // 
2 // 
3 // 
4 
5 module dini.traits;
6 
7 import std.file       : FileException;
8 import std.stdio      : File;
9 import dini.iniconfig : IniConfigs, IniConfigsException;
10 
11 private
12 mixin template setField(string fname)
13 {
14     // retrieves configuration field from file or assigns it by default
15     mixin( `auto ` ~ fname ~ `() const {return _ini.get("` ~ fname ~ `", dflt.` ~ fname ~ `);}` );
16 }
17 
18 struct ConfigsTrait(ConfigsDefault)
19 {
20 private:
21     alias dflt = ConfigsDefault;
22     IniConfigs _ini;
23 
24 public:
25 
26     void init(string ini_filename)
27     {   
28         try {
29             _ini.add(File(ini_filename));
30         } catch (FileException e) {
31             throw new IniConfigsException(e.msg);
32         }
33     }
34     void init(File ini_file)
35     {   
36         _ini.add(ini_file);
37     }
38     void initSrc(string src) pure
39     {   
40         _ini.add(src);
41     }
42 
43 
44     // Automatically generates getters by fields of structure ConfigsDefault
45     static foreach(enum string mmbr_name; __traits(allMembers, ConfigsDefault)) {
46         mixin setField!mmbr_name;
47     }
48 }
49 
50 
51 ///////////////////////////////////////////////////////
52 // cd source 
53 // rdmd -unittest -main  dini/traits
54 unittest {
55     string ini = `
56         value1 = Some text           
57         value2 = 9856428642
58     `;
59 
60     static struct AppConfigsDefault
61     {
62         enum string value1 = "Ultimate Question of Life, the Universe, and Everything";
63         enum size_t value2 = 42;
64     }
65     alias AppConfigs = ConfigsTrait!AppConfigsDefault;
66 
67 
68     AppConfigs cfg;
69     assert(cfg.value1 == AppConfigsDefault.value1);
70     assert(cfg.value2 == AppConfigsDefault.value2);
71 
72 
73     try {
74         cfg.initSrc (ini);
75     } catch (IniConfigsException e) {
76         assert(0);
77     }
78 
79     assert(cfg.value1 == "Some text");
80     assert(cfg.value2 == 9856428642);
81 }