1 module libs.marshal.compact_binary_demarshaller;
2 
3 import libs.marshal.binary_demarshaller, libs.marshal.demarshaller;
4 import std.conv, std.string, std.traits;
5 import std.stdio;
6 
7 alias Demarshaller!(CompactBinaryDemarshallerStrategy, BinaryDemarshallerStorageStrategy) CompactBinaryDemarshaller;
8 
9 package class CompactBinaryDemarshallerStrategy(StorageStrategy) : IDemarshalStrategy
10 {
11 	mixin DemarshalMixinTemplate!(StorageStrategy);
12 	
13 	void BeginArrayDemarshal(T)(string name, ref T val)
14 	{
15 		val.length = m_storer.ReadVal!(typeof(val.length))();
16 	}
17 	
18 	void EndArrayDemarshal(T)(string name, ref T val)
19 	{
20 	}
21 	
22 	void LoopArrayDemarshal(T)(string name, ref T val)
23 	{
24 		foreach (ref item; val)
25 		{
26 			Demarshal("", item); 
27 		}
28 	}
29 	
30 	void BeginDocumentDemarshal(string name)
31 	{
32 	}
33 	
34 	void EndDocumentDemarshal(string name)
35 	{
36 	}
37 	
38 	void BeginObjectDemarshal(T)(string name, ref T val)
39 	{
40 	}
41 	
42 	void EndObjectDemarshal(T)(string name, ref T val)
43 	{
44 	}
45 	
46 	void DemarshalSingleVar(T)(string name, ref T val)
47 	{
48 		static if (isSomeString!(T))
49 		{
50 			Unqual!(ForeachType!(T))[] str;
51 			str.length = m_storer.ReadVal!(typeof(val.length))();
52 			foreach(ref item; str)
53 			{
54 				item = m_storer.ReadVal!(typeof(item))();
55 			}
56 			val = to!(T)(str);
57 		}
58 		else
59 		{
60 			val = m_storer.ReadVal!(T)();
61 		}
62 	}
63 	
64 	void DemarshalEnum(T)(out T val, string name)
65 	{
66 		MarshalSingleVar(val, name);
67 	}
68 		
69 	void DemarshalUnion(T)(out T val, string name)
70 	{
71 		MarshalSingleVar(val, name);
72 	}
73 }
74 
75 unittest {
76 	//Integers
77 	CompactBinaryDemarshaller binary_demarshaller = new CompactBinaryDemarshaller;
78 	binary_demarshaller.SetBuffer([0, 0, 0, 42]);
79 	
80 	int meaning_of_life;
81 	binary_demarshaller.Demarshal("", meaning_of_life);
82 	assert(meaning_of_life == 42);
83 
84 	//Strings
85 	char[] name;
86 	binary_demarshaller = new CompactBinaryDemarshaller;
87 	binary_demarshaller.SetBuffer([0, 0, 0, 8, '1', ' ', 's', 't', 'r', 'i', 'n', 'g']);
88 	binary_demarshaller.Demarshal("", name);
89 //	writefln("name = %s", name);
90 	assert(name == "1 string");
91 	
92 	//Enums
93 	enum MyEnum
94 	{
95 		a = 10,
96 		b,
97 		c
98 	}
99 	MyEnum myenum;
100 	binary_demarshaller = new CompactBinaryDemarshaller;
101 	binary_demarshaller.SetBuffer([0, 0, 0, 11]);
102 	binary_demarshaller.Demarshal("", myenum);
103 	assert(myenum == MyEnum.b);
104 
105 	//Arrays
106 	binary_demarshaller = new CompactBinaryDemarshaller;
107 	binary_demarshaller.SetBuffer([/*length*/0,0,0,5,
108 											 			/*ary[0]*/0,0,0,1,
109 										 				/*ary[1]*/0,0,0,2,
110 										 				/*ary[2]*/0,0,0,3,
111 										 				/*ary[3]*/0,0,0,44,
112 										 				/*ary[4]*/0,0,0,5]);
113 	 
114 	int[] ary_expect = [1, 2, 3, 44, 5];
115 	int[] ary;
116 	binary_demarshaller.Demarshal("", ary);
117 	assert(ary == ary_expect);
118 	
119 	//Structs
120 	binary_demarshaller = new CompactBinaryDemarshaller;
121 	static struct A
122 	{
123 		int x;
124 		float y;
125 		string z;
126 	}
127 	A a_expect;
128 	A a;
129 	a_expect.x = 10;
130 	a_expect.y = 11.2;
131 	a_expect.z = "abc";
132 	binary_demarshaller.SetBuffer([/*x*/0, 0, 0, 10, 
133 								   /*y*/65, 51, 51, 51,
134 								   /*z*/0, 0, 0, 3, 'a', 'b', 'c']);
135 	
136 	binary_demarshaller.Demarshal("", a);
137 	assert(a == a_expect);
138 
139 	//Nested Structs
140 	binary_demarshaller = new CompactBinaryDemarshaller;
141 	static struct B
142 	{
143 		int i1 = 1024;
144 		float f1 = 22.2;
145 		A a;
146 	}
147 	B b_expect;
148 	B b;
149 	b_expect.i1 = 1024;
150 	b_expect.f1 = 22.2;
151 	b_expect.a.x = 10;
152 	b_expect.a.y = 11.2;
153 	b_expect.a.z = "abc";
154 	binary_demarshaller.SetBuffer([/*b.i1 */0, 0, 4, 0,
155 								   /*b.f1 */65, 177, 153, 154,
156 								   /*b.a.x*/0, 0, 0, 10,
157 								   /*b.a.y*/65, 51, 51, 51,
158 								   /*b.a.z*/0, 0, 0, 3, 'a', 'b', 'c']);
159 	
160 	binary_demarshaller.Demarshal("", b);
161 //	writeln(to!string(b));
162 	assert( b == b_expect );
163 	
164 	//Self Defined Marshal Function
165 	binary_demarshaller = new CompactBinaryDemarshaller;
166 	static struct C
167 	{
168 		int x;
169 		int y;
170 		int z;
171 		void Demarshal(DemarshalStrategy : CompactBinaryDemarshallerStrategy!StorageStrategy, 
172 					   StorageStrategy : BinaryDemarshallerStorageStrategy)
173 				   	  (StorageStrategy storer, string name)
174 		{
175 			assert(name == "test");
176 			x = storer.ReadVal!int;
177 			y = 122;
178 			z = 333;
179 		}
180 	}
181 	C c_expect;
182 	C c;
183 	c_expect.x = 1;
184 	c_expect.y = 122;
185 	c_expect.z = 333;
186 	binary_demarshaller.SetBuffer([0, 0, 0, 1]);
187 	binary_demarshaller.Demarshal("test", c);
188 	
189 	assert(c == c_expect);
190 	
191 	//Read in multiple variables
192 	int v1;
193 	char[] s1;
194 	int v2;
195 	binary_demarshaller = new CompactBinaryDemarshaller;
196 	binary_demarshaller.SetBuffer([0,0,0,1,0,0,0,3,'a','b','c',0,0,0,5]);
197 	
198 	binary_demarshaller.Demarshal("", v1);
199 	binary_demarshaller.Demarshal("", s1);
200 	binary_demarshaller.Demarshal("", v2);
201 	
202 	assert( v1 == 1 );
203 	assert( s1 == "abc" );
204 	assert( v2 == 5 );
205 }