1 module autowrap.csharp.common; 2 3 public import std.datetime : DateTime, SysTime, Date, TimeOfDay, Duration, TimeZone; 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) || is(T == Unqual!TimeZone); 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[])) || is(T == Unqual!(TimeZone[])); 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", "std.datetime.systime.SysTime", "std.datetime.date.DateTime", "autowrap.csharp.dlang.datetime")) { 58 fqn = "Autowrap_Csharp_Boilerplate_Datetime"; 59 } 60 61 name ~= fqn.split(".").map!camelToPascalCase.join("_"); 62 name ~= camelToPascalCase(funcName); 63 return name; 64 } 65 66 public string camelToPascalCase(string camel) { 67 import std.uni : toUpper; 68 import std.conv : to; 69 import std.range : dropOne; 70 return to!string(camel.front.toUpper()) ~ camel.dropOne(); 71 } 72 73 package template verifySupported(T) 74 { 75 static if(isSupportedType!T) 76 enum verifySupported = true; 77 else 78 { 79 pragma(msg, T.stringof ~ " is not currently supported by autowrap's C#"); 80 enum verifySupported = false; 81 } 82 } 83 84 package template numDefaultArgs(alias func) 85 { 86 import std.meta : Filter; 87 import std.traits : ParameterDefaults; 88 89 enum numDefaultArgs = Filter!(isNotVoid, ParameterDefaults!func).length; 90 91 private static template isNotVoid(values...) 92 if(values.length == 1) 93 { 94 enum isNotVoid = !is(values[0] == void); 95 } 96 } 97 98 // Unfortunately, while these tests have been tested on their own, they don't 99 // currently run as part of autowrap's tests, because dub test doesn't work for 100 // the csharp folder, and the top level one does not run them. 101 unittest 102 { 103 import std.meta : AliasSeq; 104 105 static void foo1() {} 106 static void foo2(int) {} 107 static void foo3(int, string) {} 108 static void foo4(int, string, int) {} 109 110 foreach(f; AliasSeq!(foo1, foo2, foo3, foo4)) 111 static assert(numDefaultArgs!f == 0); 112 113 static void foo5(int i = 42) {} 114 static void foo6(int, string s = "hello") {} 115 static void foo7(int, string, int j = 97) {} 116 117 foreach(f; AliasSeq!(foo5, foo6, foo7)) 118 static assert(numDefaultArgs!f == 1); 119 120 static void foo9(int i = 42, string s = "hello") {} 121 static void foo10(int, string s = "hello", int j = 97) {} 122 123 foreach(f; AliasSeq!(foo9, foo10)) 124 static assert(numDefaultArgs!f == 2); 125 126 static void foo11(int i = 42, string s = "hello", int j = 97) {} 127 128 static assert(numDefaultArgs!foo11 == 3); 129 } 130 131 package template isSupportedType(T) 132 { 133 import std.range.primitives : ElementType; 134 import std.traits : isBoolean, isDynamicArray, isIntegral, isSomeChar, TemplateOf, Unqual; 135 136 static if(isIntegral!T || isBoolean!T || isSomeChar!T || 137 is(Unqual!T == float) || is(Unqual!T == double) || is(T == void)) 138 { 139 enum isSupportedType = true; 140 } 141 else static if(isDynamicArray!T) 142 { 143 alias E = ElementType!T; 144 enum isSupportedType = is(E == string) || is(E == wstring) || is(E == dstring) || 145 !isDynamicArray!E && isSupportedType!E; 146 } 147 else static if(is(T == struct) || is(T == class) || is(T == interface)) 148 enum isSupportedType = !is(typeof(TemplateOf!T)); 149 else 150 enum isSupportedType = false; 151 } 152 153 // Unfortunately, while these tests have been tested on their own, they don't 154 // currently run as part of autowrap's tests, because dub test doesn't work for 155 // the csharp folder, and the top level one does not run them. 156 unittest 157 { 158 import std.meta : AliasSeq; 159 import std.typecons : Tuple; 160 161 static struct S {} 162 static class C {} 163 164 foreach(T; AliasSeq!(byte, ubyte, const ubyte, immutable ubyte, short, ushort, int, uint, long, ulong, 165 float, double, bool, char, wchar, dchar, string, wstring, dstring, S, S[], C, int[], 166 string[], wstring[], dstring[], void)) 167 { 168 static assert(isSupportedType!T, T.stringof); 169 } 170 foreach(T; AliasSeq!(int*, int*[], int[][], int[][][], int[int], cfloat, cdouble, creal, ifloat, idouble, ireal, 171 Tuple!int, Tuple!(string, string))) 172 { 173 static assert(!isSupportedType!T, T.stringof); 174 } 175 }