1 module gfx.core.util; 2 3 /// Down cast of a reference to a child class reference 4 /// runtime check is disabled in release build 5 /// If T is a base class of U, this does a blind cast to the same address. 6 /// If T is an interface implemented by U, it first offset address to the object base address 7 /// and does a blind cast to that address. 8 template unsafeCast(U) if (!is(U == const)) 9 { 10 static assert (!is(U == interface), "unsafeCast cannot be used to return interfaces"); 11 static assert (is(U == class), "unsafeCast can only be used with objects"); 12 13 @system 14 U unsafeCast(T)(T obj) 15 if ((is(T==class) || is(T==interface)) && is(U : T)) 16 { 17 if (!obj) return null; 18 debug { 19 auto uObj = cast(U)obj; 20 assert(uObj, "unsafeCast from "~T.stringof~" to "~U.stringof~" failed"); 21 return uObj; 22 } 23 else { 24 static if (is(T == interface)) { 25 return cast(U)(cast(void*)(cast(Object)obj)); 26 } 27 else { 28 return cast(U)(cast(void*)obj); 29 } 30 } 31 } 32 33 } 34 35 /// ditto 36 template unsafeCast(U) if (is(U == const)) 37 { 38 static assert (!is(U == interface), "unsafeCast cannot be used to return interfaces"); 39 static assert (is(U == class), "unsafeCast can only be used with objects"); 40 41 @system 42 U unsafeCast(T)(const(T) obj) 43 if ((is(T==class) || is(T==interface)) && is(U : const(T))) 44 { 45 if (!obj) return null; 46 debug { 47 auto uObj = cast(U)obj; 48 assert(uObj, "unsafeCast from "~T.stringof~" to "~U.stringof~" failed"); 49 return uObj; 50 } 51 else { 52 static if (is(T == interface)) { 53 return cast(U)(cast(const(void*))(cast(const(Object))obj)); 54 } 55 else { 56 return cast(U)(cast(const(void*))obj); 57 } 58 } 59 } 60 } 61 62 63 /// Return a bit by bit unchecked identical representation of the passed argument 64 template transmute(U) 65 { 66 import std.traits : isDynamicArray; 67 68 static if (!isDynamicArray!U) { 69 @system @nogc nothrow pure 70 U transmute(T)(in T value) 71 { 72 static assert(T.sizeof == U.sizeof, "can only transmute to identical type size"); 73 static assert(!is(T == class) && !is(T == interface), "cannot used transmute on objects"); 74 static assert(!is(U == class) && !is(U == interface), "cannot used transmute on objects"); 75 76 return *cast(U*)cast(void*)&value; 77 } 78 } 79 else { 80 @system @nogc nothrow pure 81 U transmute(T)(T[] value) 82 { 83 import std.traits : isMutable; 84 85 alias V = typeof(U.init[0]); 86 87 static assert(T.sizeof == V.sizeof, "can only transmute to identical type size"); 88 static assert(!is(T == class) && !is(T == interface), "cannot used transmute on objects"); 89 static assert(!is(V == class) && !is(V == interface), "cannot used transmute on objects"); 90 static if (!isMutable!V) { 91 static assert(!isMutable!T, "transmute is not meant to cast constness away"); 92 } 93 94 return (cast(V*)cast(void*)value.ptr)[0 .. value.length]; 95 } 96 } 97 }