1 module utile.binary.tests;
2 import std, utile.misc, utile.binary, utile.logger, utile.binary.helpers;
3 
4 void ensureResult(T)(in T value, const(ubyte)[] data)
5 {
6 	const res = value.serializeMem;
7 	assert(res == data, res.to!string);
8 
9 	const parsed = data.deserializeMem!T;
10 	assert(parsed == value, parsed.to!string);
11 }
12 
13 unittest
14 {
15 	static struct B
16 	{
17 		uint k;
18 		string s;
19 	}
20 
21 	static struct A
22 	{
23 		B b;
24 		ubyte v;
25 	}
26 
27 	A a;
28 	a.v = 10;
29 	a.b.k = 12;
30 	a.b.s = `hello`;
31 
32 	const(ubyte)[] data = [
33 		12, 0, 0, 0, // a.b.k
34 		104, 101, 108, 108, 111, 0, // a.b.s
35 		10, // a.v
36 	];
37 
38 	ensureResult(a, data);
39 }
40 
41 unittest
42 {
43 	static struct S
44 	{
45 		@ZeroTerminated const(ubyte)[] str;
46 		wstring wstr;
47 
48 		@(ArrayLength!(_ => 6), ZeroTerminated) string st;
49 		@(ArrayLength!(_ => 6), ZeroTerminated) string st2;
50 		@(ArrayLength!(_ => 4), ZeroTerminated) ubyte[] st3;
51 
52 		@ArrayLength!(_ => 6) string st4;
53 		@ToTheEnd string st5;
54 	}
55 
56 	S s;
57 	s.str = [1, 2, 3];
58 	s.wstr = `1234`w;
59 	s.st = `abc`;
60 	s.st2 = `abcdef`;
61 	s.st3 = [1, 2];
62 	s.st4 = "\0qwert";
63 	s.st5 = "\0a";
64 
65 	const(ubyte)[] data = [
66 		1, 2, 3, 0, // str
67 		49, 0, 50, 0, 51, 0, 52, 0, 0, 0, // wstr
68 		97, 98, 99, 0, 0, 0, // st
69 		97, 98, 99, 100, 101, 102, // st2
70 		1, 2, 0, 0, // st3
71 		0, 113, 119, 101, 114, 116, // st4
72 		0, 97, // st5
73 	];
74 
75 	ensureResult(s, data);
76 }
77 
78 unittest
79 {
80 	struct S
81 	{
82 		ubyte a;
83 		@ToTheEnd wstring d;
84 	}
85 
86 	S s;
87 	s.a = 10;
88 	s.d = `hello`w;
89 
90 	const(ubyte)[] data = [
91 		10, // a
92 		104, 0, 101, 0, 108, 0, 108, 0, 111, 0, // d
93 	];
94 
95 	ensureResult(s, data);
96 }
97 
98 unittest
99 {
100 	struct S
101 	{
102 		@(ToTheEnd, ZeroTerminated) wstring d;
103 	}
104 
105 	S s;
106 	s.d = `hello`w;
107 
108 	const(ubyte)[] data = [
109 		104, 0, 101, 0, 108, 0, 108, 0, 111, 0, 0, 0, // d
110 	];
111 
112 	ensureResult(s, data);
113 }
114 
115 unittest
116 {
117 	static struct S
118 	{
119 		ubyte val;
120 		S* next;
121 	}
122 
123 	auto s = S(12);
124 	s.next = new S(13);
125 
126 	auto data = s.serializeMem;
127 	assert(data == [12, 1, 13, 0]);
128 
129 	auto v = data.deserializeMem!S;
130 
131 	assert(v.val == s.val);
132 	assert(v.next && *v.next == *s.next);
133 }
134 
135 unittest
136 {
137 	static struct Test
138 	{
139 		enum X = 10;
140 
141 		enum Y
142 		{
143 			i = 12
144 		}
145 
146 		static struct S
147 		{
148 			uint k = 4;
149 		}
150 
151 		static int sx = 1;
152 		__gshared int gx = 2;
153 
154 		Y y;
155 		static Y sy;
156 
157 		static void f()
158 		{
159 		}
160 
161 		static void f2() pure nothrow @nogc @safe
162 		{
163 		}
164 
165 		shared void g()
166 		{
167 		}
168 
169 		static void function() fp;
170 		__gshared void function() gfp;
171 		void function() fpm;
172 
173 		void delegate() dm;
174 		static void delegate() sd;
175 
176 		void m()
177 		{
178 		}
179 
180 		final void m2() const pure nothrow @nogc @safe
181 		{
182 		}
183 
184 		inout(int) iom() inout
185 		{
186 			return 10;
187 		}
188 
189 		static inout(int) iosf(inout int x)
190 		{
191 			return x;
192 		}
193 
194 		@property int p()
195 		{
196 			return 10;
197 		}
198 
199 		static @property int sp()
200 		{
201 			return 10;
202 		}
203 
204 		union
205 		{
206 			int a;
207 			float b;
208 			long u;
209 			double gg;
210 		}
211 
212 		S s;
213 		static immutable char[4] c = `ABCD`;
214 		string d;
215 
216 		@(ArrayLength!uint) int[] e;
217 		@(ArrayLength!(a => a.that.e.length)) int[] r;
218 
219 		@Ignored int kk;
220 		@(IgnoreIf!(a => a.that.r.length == 3)) int rt;
221 
222 		@(ToTheEnd, Skip!(a => a.that.rt)) byte[] q;
223 	}
224 
225 	static assert(fieldsToProcess!Test == [`y`, `u`, `s`, `c`, `d`, `e`, `r`, `rt`, `q`]);
226 
227 	const(ubyte)[] data = [
228 		12, 0, 0, 0, // y
229 		11, 0, 0, 0, 0, 0, 0, 0, // a
230 		4, 0, 0, 0, // S.k
231 		65, 66, 67, 68, // c
232 		97, 98, 99, 0, // d, null terminated
233 		3, 0, 0, 0, // e.length
234 		1, 0, 0, 0, // e[0]
235 		2, 0, 0, 0, // e[1]
236 		3, 0, 0, 0, // e[3]
237 		4, 0, 0, 0, // r[0], length is set by the user
238 		5, 0, 0, 0, // r[1]
239 		6, 0, 0, 0, // r[2]
240 		1, 2, 3, 4, // q[4]
241 	];
242 
243 	Test t = {a: 11, d: `abc`, e: [1, 2, 3], r: [4, 5, 6], q: [1, 2, 3, 4]};
244 
245 	ensureResult(t, data);
246 
247 	enum File = `__tmp`;
248 	serializeFile(File, t);
249 
250 	scope (exit)
251 		std.file.remove(File);
252 
253 	assert(deserializeFile!Test(File) == t);
254 }