1 module libs.marshal.compact_binary_marshaller; 2 3 import libs.marshal.binary_marshaller, libs.marshal.marshaller; 4 import std.conv, std.string, std.traits; 5 import std.stdio; 6 import std.bitmanip; 7 8 alias Marshaller!(CompactBinaryMarshallerStrategy, BinaryMarshallerStorageStrategy) CompactBinaryMarshaller; 9 10 package class CompactBinaryMarshallerStrategy(StorageStrategy) : IMarshalStrategy 11 { 12 mixin MarshalMixinTemplate!(StorageStrategy); 13 14 void BeginDocumentMarshal(string name) 15 { 16 } 17 18 void EndDocumentMarshal(string name) 19 { 20 } 21 22 void BeginObjectMarshal(T)(T val, string name) 23 { 24 } 25 26 void EndObjectMarshal(T)(T val, string name) 27 { 28 } 29 30 void BeginArrayMarshal(T)(T val, string name) 31 { 32 MarshalSingleVar(val.length, ""); 33 } 34 35 void EndArrayMarshal(T)(T val, string name) 36 { 37 } 38 39 void MarshalSingleVar(T)(T val, string name) 40 { 41 static if (isSomeString!(T)) 42 { 43 //Write the length 44 MarshalSingleVar(val.length, ""); 45 //Write the data 46 ubyte[] bytes = new ubyte[ForeachType!(T).sizeof*val.length]; 47 foreach(i, c; val) 48 { 49 bytes.write!(ForeachType!(T))(c, ForeachType!(T).sizeof * i); 50 } 51 m_storer.AddBytes(bytes); 52 } 53 else 54 { 55 ubyte[] bytes = new ubyte[T.sizeof]; 56 bytes.write!(T)(val, 0); 57 //bytes = cast(byte[])val; 58 m_storer.AddBytes(bytes); 59 } 60 } 61 62 void MarshalEnum(T)(T val, string name) 63 { 64 MarshalSingleVar(val, name); 65 } 66 67 void MarshalUnion(T)(T val, string name) 68 { 69 MarshalSingleVar(val, name); 70 } 71 } 72 73 unittest { 74 //Integers 75 CompactBinaryMarshaller binary_marshaller = new CompactBinaryMarshaller; 76 binary_marshaller.Marshal(42, ""); 77 //writeln(to!string(binary_marshaller.GetBuffer())); 78 assert(binary_marshaller.GetBuffer() == [0, 0, 0, 42]); 79 80 //Strings 81 binary_marshaller = new CompactBinaryMarshaller; 82 binary_marshaller.Marshal("1 string", ""); 83 //writeln(to!string(binary_marshaller.GetBuffer())); 84 assert(binary_marshaller.GetBuffer() == [0, 0, 0, 8, '1', ' ', 's', 't', 'r', 'i', 'n', 'g']); 85 86 //Enums 87 enum MyEnum 88 { 89 a = 10, 90 b, 91 c 92 } 93 MyEnum myenum; 94 myenum = MyEnum.b; 95 binary_marshaller = new CompactBinaryMarshaller; 96 binary_marshaller.Marshal(myenum, ""); 97 //writeln(to!string(binary_marshaller.GetBuffer())); 98 assert(binary_marshaller.GetBuffer() == [0, 0, 0, 11]); 99 100 enum MyEnum2 : ubyte 101 { 102 a = 10, 103 b, 104 c 105 } 106 MyEnum2 myenum2; 107 myenum2 = MyEnum2.b; 108 binary_marshaller = new CompactBinaryMarshaller; 109 binary_marshaller.Marshal(myenum2, ""); 110 //writeln(to!string(binary_marshaller.GetBuffer())); 111 assert(binary_marshaller.GetBuffer() == [11]); 112 113 //Arrays 114 binary_marshaller = new CompactBinaryMarshaller; 115 int[] ary = [1, 2, 3, 44, 5]; 116 binary_marshaller.Marshal(ary, ""); 117 //writeln(to!string(binary_marshaller.GetBuffer())); 118 assert(binary_marshaller.GetBuffer() == [/*length*/0,0,0,5, 119 /*ary[0]*/0,0,0,1, 120 /*ary[1]*/0,0,0,2, 121 /*ary[2]*/0,0,0,3, 122 /*ary[3]*/0,0,0,44, 123 /*ary[4]*/0,0,0,5]); 124 125 //Structs 126 binary_marshaller = new CompactBinaryMarshaller; 127 static struct A 128 { 129 int x = 10; 130 float y = 11.2; 131 string z = "abc"; 132 } 133 A a; 134 binary_marshaller.Marshal(a, ""); 135 //writeln(binary_marshaller.ToString()); 136 assert(binary_marshaller.GetBuffer() == [/*x*/0, 0, 0, 10, 137 /*y*/65, 51, 51, 51, 138 /*z*/0, 0, 0, 3, 'a', 'b', 'c']); 139 140 //Nested Structs 141 binary_marshaller = new CompactBinaryMarshaller; 142 static struct B 143 { 144 int i1 = 1024; 145 float f1 = 22.2; 146 A a; 147 } 148 B b; 149 binary_marshaller.Marshal(b, ""); 150 //writeln(binary_marshaller.ToString()); 151 assert(binary_marshaller.GetBuffer == [/*b.i1 */0, 0, 4, 0, 152 /*b.f1 */65, 177, 153, 154, 153 /*b.a.x*/0, 0, 0, 10, 154 /*b.a.y*/65, 51, 51, 51, 155 /*b.a.z*/0, 0, 0, 3, 'a', 'b', 'c']); 156 157 //Self Defined Marshal Function 158 binary_marshaller = new CompactBinaryMarshaller; 159 static struct C 160 { 161 void Marshal(MarshalStrategy : CompactBinaryMarshallerStrategy!StorageStrategy, StorageStrategy : BinaryMarshallerStorageStrategy)(StorageStrategy storer, string name) 162 { 163 assert(name == "cab"); 164 storer.AddBytes([1, 2, 3]); 165 } 166 } 167 C c; 168 binary_marshaller.Marshal(c, "cab"); 169 assert(binary_marshaller.GetBuffer() == [1, 2, 3]); 170 }