1 ///
2 module drmi.core.helpers;
3 
4 package template rmiFunctionName(alias func)
5 {
6     string impl()
7     {
8         import std.meta : staticMap;
9         import std.traits : Parameters;
10         import std..string : join;
11         import std.algorithm : canFind;
12 
13         checkFunction!func;
14 
15         template s4t(X) { enum s4t = X.stringof; }
16 
17         static if (Parameters!func.length)
18             return __traits(identifier, func) ~ "(" ~ [staticMap!(s4t, Parameters!func)].join(",") ~ ")";
19         else
20             return __traits(identifier, func) ~ "()";
21     }
22     enum rmiFunctionName = impl();
23 }
24 
25 package void checkFunction(alias func)()
26 {
27     import std.algorithm : find;
28     import std.traits : hasFunctionAttributes;
29     enum funcstr = __traits(identifier, __traits(parent, __traits(parent, func))) ~ ":" ~ 
30                     __traits(identifier, __traits(parent, func))
31                     ~ "." ~ __traits(identifier, func);
32     static assert(!hasFunctionAttributes!(func, "@safe"), "@safe not allowed: " ~ funcstr);
33     static assert(!hasFunctionAttributes!(func,  "pure"), "pure not allowed: " ~ funcstr);
34     static assert(!hasFunctionAttributes!(func, "@nogc"), "@nogc not allowed: " ~ funcstr);
35 }
36 
37 unittest
38 {
39     static auto i = [0];
40     void foo(int a, double b, string c) @system { i ~= 1; }
41     static assert(rmiFunctionName!foo == "foo(int,double,string)");
42     void bar() @system { i ~= 2; }
43     static assert(rmiFunctionName!bar == "bar()");
44 }