1 /** 2 * Environment variable-based 3 * provider. 4 * 5 * You should use this if you 6 * intend on filling up your 7 * config with values that are 8 * available as environment 9 * variables 10 * 11 * Authors: Tristan Brice Velloza Kildaire (deavmi) 12 */ 13 module hummus.providers.env; 14 15 import hummus.provider : Provider; 16 import std.process : environment; 17 18 /** 19 * A provider which will look for 20 * environment variables based 21 * on a _transformed_ version of 22 * their name. 23 * 24 * This transformation replaces all 25 * `.` with a character of your 26 * choice (default is `__`) and 27 * also ensures all parts of the 28 * name are upper-case. 29 */ 30 public class EnvironmentProvider : Provider 31 { 32 private string _dp; 33 34 /** 35 * Constructs a new environment 36 * provider and uses the given 37 * token to replace all occurrences 38 * of `.` in names 39 * 40 * Params: 41 * dotReplace = the replaceent token 42 */ 43 this(string dotReplace) 44 { 45 this._dp = dotReplace; 46 } 47 48 /** 49 * Constructs a new environment 50 * provider and uses the `__` 51 * token as the replacement 52 * token 53 */ 54 this() 55 { 56 this("__"); 57 } 58 59 /** 60 * Implementation 61 */ 62 protected bool provideImpl(string n, ref string v) 63 { 64 // upper-case everything 65 import std.string : toUpper; 66 auto trans_n = toUpper(n); 67 68 // replace `.` with `_dp` 69 import std.string : replace; 70 trans_n = replace(trans_n, ".", this._dp); 71 72 // todo: switch to nothrow version 73 try 74 { 75 v = environment[trans_n]; 76 return true; 77 } 78 catch(Exception e) 79 { 80 return false; 81 } 82 } 83 } 84 85 private version(unittest) 86 { 87 import hummus.cfg : fieldsOf; 88 import std.stdio : writeln; 89 } 90 91 unittest 92 { 93 writeln(); 94 scope(exit) 95 { 96 writeln(); 97 } 98 99 struct Inner 100 { 101 int z; 102 } 103 104 struct Cfg 105 { 106 string v; 107 Inner i; 108 } 109 110 auto cfg = Cfg(); 111 writeln("Before provisioning: ", cfg); 112 113 // envvars `v` and `i.z` should be present 114 fieldsOf(cfg, new EnvironmentProvider()); 115 116 writeln("After provisioning: ", cfg); 117 118 assert(cfg.v == "1"); 119 assert(cfg.i.z == 2); 120 }