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