1 module des.util.data.pdata; 2 3 import std.traits; 4 import std..string; 5 6 import des.util.testsuite; 7 8 version(unittest) 9 { 10 private 11 { 12 struct Msg { string data; } 13 struct Vec { float x,y,z; } 14 struct Arr { int[3] data; } 15 16 struct Some 17 { 18 float f = 8; 19 Vec v = Vec(1,2,3); 20 Arr a = Arr([4,5,6]); 21 } 22 23 struct Bad { int[] data; } 24 } 25 26 void asTest(A,B)( in A val, in B orig ) 27 { 28 assert( (PData(val)).as!B == orig || isPData!B ); 29 assert( (const PData(val)).as!B == orig || isPData!B ); 30 assert( (immutable PData(val)).as!B == orig || isPData!B ); 31 assert( (shared PData(val)).as!B == orig || isPData!B ); 32 assert( (shared const PData(val)).as!B == orig || isPData!B ); 33 } 34 35 void creationTest(T)( in T val ) 36 { 37 asTest( val, val ); 38 39 auto a = PData( val ); 40 auto ac = const PData( val ); 41 auto ai = immutable PData( val ); 42 auto as = shared PData( val ); 43 auto asc = shared const PData( val ); 44 45 asTest( a, val ); 46 asTest( ac, val ); 47 asTest( ai, val ); 48 asTest( as, val ); 49 asTest( asc, val ); 50 } 51 } 52 53 /// 54 template isPureData(T) { enum isPureData = !hasUnsharedAliasing!T && !isArray!T; } 55 56 unittest 57 { 58 static assert( isPureData!int ); 59 static assert( isPureData!float ); 60 static assert( isPureData!Vec ); 61 static assert( isPureData!Arr ); 62 static assert( isPureData!Some ); 63 static assert( !isPureData!string ); 64 static assert( !isPureData!Bad ); 65 } 66 67 /// 68 template isPureType(T) 69 { 70 static if( !isArray!T ) enum isPureType = isPureData!T; 71 else enum isPureType = isPureType!(ForeachType!T); 72 } 73 74 unittest 75 { 76 static assert( isPureType!int ); 77 static assert( isPureType!(int[]) ); 78 static assert( isPureType!float ); 79 static assert( isPureType!(float[]) ); 80 static assert( isPureType!Vec ); 81 static assert( isPureType!Arr ); 82 static assert( isPureType!Some ); 83 static assert( isPureType!string ); 84 static assert( isPureType!(string[]) ); 85 static assert( !isPureType!Bad ); 86 } 87 88 auto pureConv(T)( in immutable(void)[] data ) pure 89 { 90 static if( isPureData!T ) 91 return (cast(T[])(data.dup))[0]; 92 else static if( isPureType!T ) 93 return cast(T)(data.dup); 94 else static assert( 0, format( "unsuported type %s", T.stringof ) ); 95 } 96 97 immutable(void)[] pureDump(T)( in T val ) pure 98 { 99 static assert( !is( T == void[] ) ); 100 static if( isArray!T ) return (cast(void[])val).idup; 101 else return (cast(void[])[val]).idup; 102 } 103 104 /// 105 template isPData(T) { enum isPData = is( typeof( (( PData a ){})( T.init ) ) ); } 106 107 /// 108 struct PData 109 { 110 /// 111 immutable(void)[] data; 112 /// 113 alias data this; 114 115 pure 116 { 117 /// 118 this( in typeof(this) pd ) { data = pd.data; } 119 120 /// 121 this(T)( in T val ) if( isPureData!T ) { data = pureDump(val); } 122 /// 123 this(T)( in T[] val ) if( isPureType!T ) { data = pureDump(val); } 124 125 /// 126 auto opAssign(T)( in T val ) if( isPureData!T ) { data = pureDump(val); return val; } 127 /// 128 auto opAssign(T)( in T[] val ) if( isPureType!T ) { data = pureDump(val); return val; } 129 130 @property 131 { 132 /// 133 auto as(T)() const { return pureConv!T(data); } 134 /// 135 auto as(T)() shared const { return pureConv!T(data); } 136 /// 137 auto as(T)() immutable { return pureConv!T(data); } 138 } 139 } 140 } 141 142 unittest 143 { 144 static assert( isPData!PData ); 145 static assert( isPData!(const(PData)) ); 146 static assert( isPData!(immutable(PData)) ); 147 static assert( isPData!(shared(PData)) ); 148 static assert( isPData!(shared const(PData)) ); 149 static assert( isPureData!PData ); 150 static assert( isPureType!PData ); 151 } 152 153 unittest 154 { 155 creationTest( "hello" ); 156 creationTest( 12.5 ); 157 creationTest( 12 ); 158 creationTest( [1,2,3] ); 159 creationTest( [.1,.2,.3] ); 160 creationTest( Vec(1,2,3) ); 161 creationTest( Arr([1,2,3]) ); 162 creationTest( Some.init ); 163 } 164 165 unittest 166 { 167 auto msg = Msg("ok"); 168 169 auto a = shared PData( PData( msg ) ); 170 assert( a.as!Msg == msg ); 171 172 auto b = immutable PData( PData( [msg] ) ); 173 assert( b.as!(Msg[]) == [msg] ); 174 } 175 176 unittest 177 { 178 static assert( !__traits(compiles, PData( Bad([1,2]) ) ) ); 179 static assert( !__traits(compiles, PData( [Bad([1,2])] ) ) ); 180 } 181 182 /// 183 unittest 184 { 185 auto a = PData( [.1,.2,.3] ); 186 assert( eq( a.as!(double[]), [.1,.2,.3] ) ); 187 a = "hello"; 188 assert( eq( a.as!string, "hello" ) ); 189 } 190 191 unittest // Known problems 192 { 193 // shared or immutable PData can't create from structs or arrays with strings 194 enum arr = ["a","b","c"]; 195 enum msg = Msg("abc"); 196 197 static assert( __traits(compiles, PData( arr ) ) ); 198 static assert( __traits(compiles, PData( msg ) ) ); 199 static assert( __traits(compiles, PData( [arr] ) ) ); 200 static assert( __traits(compiles, PData( [msg] ) ) ); 201 static assert( __traits(compiles, const PData( arr ) ) ); 202 static assert( __traits(compiles, const PData( msg ) ) ); 203 204 static assert( !__traits(compiles, shared PData( arr ) ) ); 205 static assert( !__traits(compiles, shared PData( msg ) ) ); 206 static assert( !__traits(compiles, shared PData( [arr] ) ) ); 207 static assert( !__traits(compiles, shared PData( [msg] ) ) ); 208 static assert( __traits(compiles, shared PData( PData( arr ) ) ) ); 209 static assert( __traits(compiles, shared PData( PData( msg ) ) ) ); 210 211 static assert( !__traits(compiles, shared const PData( arr ) ) ); 212 static assert( !__traits(compiles, shared const PData( msg ) ) ); 213 static assert( !__traits(compiles, shared const PData( [arr] ) ) ); 214 static assert( !__traits(compiles, shared const PData( [msg] ) ) ); 215 static assert( __traits(compiles, shared const PData( PData( arr ) ) ) ); 216 static assert( __traits(compiles, shared const PData( PData( msg ) ) ) ); 217 218 static assert( !__traits(compiles, immutable PData( arr ) ) ); 219 static assert( !__traits(compiles, immutable PData( msg ) ) ); 220 static assert( !__traits(compiles, immutable PData( [arr] ) ) ); 221 static assert( !__traits(compiles, immutable PData( [msg] ) ) ); 222 static assert( __traits(compiles, immutable PData( PData( arr ) ) ) ); 223 static assert( __traits(compiles, immutable PData( PData( msg ) ) ) ); 224 }