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 }