1 module autowrap.csharp.common; 2 3 public import std.datetime : DateTime, SysTime, Date, TimeOfDay, Duration; 4 public import std.range.primitives; 5 public import std.traits : Unqual; 6 7 public enum isDateTimeType(T) = is(T == Unqual!Date) || is(T == Unqual!DateTime) || is(T == Unqual!SysTime) || is(T == Unqual!TimeOfDay) || is(T == Unqual!Duration); 8 public enum isDateTimeArrayType(T) = is(T == Unqual!(Date[])) || is(T == Unqual!(DateTime[])) || is(T == Unqual!(SysTime[])) || is(T == Unqual!(TimeOfDay[])) || is(T == Unqual!(Duration[])); 9 10 enum string[] excludedMethods = ["toHash", "opEquals", "opCmp", "factory", "__ctor"]; 11 12 13 package string getDLangInterfaceName(string moduleName, string aggName, string funcName) { 14 import std.algorithm : map; 15 import std..string : split; 16 import std.array : join; 17 18 string name = "autowrap_csharp_"; 19 name ~= moduleName.split(".").map!camelToPascalCase.join("_"); 20 21 if (aggName != string.init) { 22 name ~= camelToPascalCase(aggName) ~ "_"; 23 } 24 name ~= camelToPascalCase(funcName); 25 return name; 26 } 27 28 package string getDLangInterfaceName(string fqn, string funcName) { 29 import std.algorithm : map; 30 import std..string : split; 31 import std.array : join; 32 string name = "autowrap_csharp_"; 33 34 name ~= fqn.split(".").map!camelToPascalCase.join("_"); 35 name ~= camelToPascalCase(funcName); 36 return name; 37 } 38 39 package string getDLangSliceInterfaceName(string fqn, string funcName) { 40 import std.algorithm : map, among; 41 import std..string : split; 42 import std.array : join; 43 44 string name = "autowrap_csharp_slice_"; 45 46 if (fqn.among("core.time.Duration", "autowrap.csharp.dlang.Marshalled_Duration")) 47 fqn = "Autowrap_Csharp_Boilerplate_Marshalled_Duration"; 48 else if (fqn.among("std.datetime.date.DateTime", "std.datetime.date.Date", "std.datetime.date.TimeOfDay", 49 "autowrap.csharp.dlang.Marshalled_std_datetime_date")) { 50 fqn = "Autowrap_Csharp_Boilerplate_Marshalled_std_datetime_date"; 51 } 52 else if (fqn == "std.datetime.systime.SysTime") 53 fqn = "Autowrap_Csharp_Boilerplate_Marshalled_std_datetime_systime"; 54 55 name ~= fqn.split(".").map!camelToPascalCase.join("_"); 56 name ~= camelToPascalCase(funcName); 57 return name; 58 } 59 60 public string camelToPascalCase(string camel) { 61 import std.uni : toUpper; 62 import std.conv : to; 63 import std.range : dropOne; 64 return to!string(camel.front.toUpper()) ~ camel.dropOne(); 65 } 66 67 package template verifySupported(T) 68 { 69 static if(isSupportedType!T) 70 enum verifySupported = true; 71 else 72 { 73 pragma(msg, T.stringof ~ " is not currently supported by autowrap's C#"); 74 enum verifySupported = false; 75 } 76 } 77 78 package template numDefaultArgs(alias func) 79 { 80 import std.meta : Filter; 81 import std.traits : ParameterDefaults; 82 83 enum numDefaultArgs = Filter!(isNotVoid, ParameterDefaults!func).length; 84 85 private static template isNotVoid(values...) 86 if(values.length == 1) 87 { 88 enum isNotVoid = !is(values[0] == void); 89 } 90 } 91 92 // Unfortunately, while these tests have been tested on their own, they don't 93 // currently run as part of autowrap's tests, because dub test doesn't work for 94 // the csharp folder, and the top level one does not run them. 95 unittest 96 { 97 import std.meta : AliasSeq; 98 99 static void foo1() {} 100 static void foo2(int) {} 101 static void foo3(int, string) {} 102 static void foo4(int, string, int) {} 103 104 foreach(f; AliasSeq!(foo1, foo2, foo3, foo4)) 105 static assert(numDefaultArgs!f == 0); 106 107 static void foo5(int i = 42) {} 108 static void foo6(int, string s = "hello") {} 109 static void foo7(int, string, int j = 97) {} 110 111 foreach(f; AliasSeq!(foo5, foo6, foo7)) 112 static assert(numDefaultArgs!f == 1); 113 114 static void foo9(int i = 42, string s = "hello") {} 115 static void foo10(int, string s = "hello", int j = 97) {} 116 117 foreach(f; AliasSeq!(foo9, foo10)) 118 static assert(numDefaultArgs!f == 2); 119 120 static void foo11(int i = 42, string s = "hello", int j = 97) {} 121 122 static assert(numDefaultArgs!foo11 == 3); 123 } 124 125 package template isFunctionType(T) 126 { 127 static if (is(T == function) || is(T == delegate)) 128 enum isFunctionType = true; 129 else 130 { 131 import std.traits : isFunctionPointer; 132 enum isFunctionType = isFunctionPointer!T; 133 } 134 } 135 136 package template isSupportedType(T) 137 { 138 import std.range.primitives : ElementType; 139 import std.traits : isBoolean, isDynamicArray, isIntegral, isSomeChar, Unqual, ReturnType, Parameters; 140 141 static if(isIntegral!T || isBoolean!T || isSomeChar!T || 142 is(Unqual!T == float) || is(Unqual!T == double) || is(T == void)) 143 { 144 enum isSupportedType = true; 145 } 146 else static if(isDynamicArray!T) 147 { 148 alias E = ElementType!T; 149 enum isSupportedType = is(E == string) || is(E == wstring) || is(E == dstring) || 150 !isDynamicArray!E && isSupportedType!E; 151 } 152 else static if(is(T == struct) || is(T == class) || is(T == interface)) 153 { 154 import std.datetime.timezone : TimeZone; 155 import std.traits : TemplateOf; 156 enum isSupportedType = !is(typeof(TemplateOf!T)) && !is(Unqual!T == TimeZone); 157 } 158 else static if (isFunctionType!T) 159 { 160 enum isSupportedType = isSupportedType!(ReturnType!T) && isSupportedTypes!(Parameters!T); 161 } 162 else 163 enum isSupportedType = false; 164 } 165 166 package template isSupportedTypes(T...) 167 { 168 static if (T.length == 0) 169 enum isSupportedTypes = true; 170 else 171 enum isSupportedTypes = isSupportedType!(T[0]) && isSupportedTypes!(T[1..$]); 172 } 173 174 // Unfortunately, while these tests have been tested on their own, they don't 175 // currently run as part of autowrap's tests, because dub test doesn't work for 176 // the csharp folder, and the top level one does not run them. 177 unittest 178 { 179 import std.meta : AliasSeq; 180 import std.typecons : Tuple; 181 182 static struct S {} 183 static class C {} 184 185 foreach(T; AliasSeq!(byte, ubyte, const ubyte, immutable ubyte, short, ushort, int, uint, long, ulong, 186 float, double, bool, char, wchar, dchar, string, wstring, dstring, S, S[], C, int[], 187 string[], wstring[], dstring[], void)) 188 { 189 static assert(isSupportedType!T, T.stringof); 190 } 191 foreach(T; AliasSeq!(int*, int*[], int[][], int[][][], int[int], cfloat, cdouble, creal, ifloat, idouble, ireal, 192 Tuple!int, Tuple!(string, string))) 193 { 194 static assert(!isSupportedType!T, T.stringof); 195 } 196 }