1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.util.Serialize;
13 
14 import std.traits;
15 import std.string;
16 import core.stdc.string;
17 import std.stdio;
18 import std.bitmanip;
19 import std.math;
20 public import std.json;
21 
22 public:
23 enum IGNORE = 1024;
24 
25 class UnIgnoreArray{
26 	
27 	void setUnIgnore(T)()
28 	{
29 		_unIgnore[T.stringof] = true;
30 	}
31 
32 	bool ignore(T)()
33 	{
34 		return T.stringof !in _unIgnore;
35 	}
36 
37 private:
38 	bool[string] _unIgnore;
39 }
40 
41 
42 private:
43 
44 class RefClass
45 {
46 	size_t[size_t] map;
47 	void*[] arr;
48 	uint level;
49 	bool ignore;	 				///  all class or struct ignore or not. 
50 	UnIgnoreArray unIgnore;			///  part class unignore. 
51 }
52 
53 enum MAGIC_KEY = "o0o0o";
54 
55 enum bool isType(T1, T2) = is(T1 == T2) || is(T1 == ImmutableOf!T2)
56 		|| is(T1 == ConstOf!T2) || is(T1 == InoutOf!T2)
57 		|| is(T1 == SharedOf!T2) || is(T1 == SharedConstOf!T2) || is(T1 == SharedInoutOf!T2);
58 
59 enum bool isSignedType(T) = isType!(T, byte) || isType!(T, short) || isType!(T,
60 			int) || isType!(T, long);
61 enum bool isUnsignedType(T) = isType!(T, ubyte) || isType!(T, ushort)
62 		|| isType!(T, uint) || isType!(T, ulong);
63 enum bool isBigSignedType(T) = isType!(T, int) || isType!(T, long);
64 enum bool isBigUnsignedType(T) = isType!(T, uint) || isType!(T, ulong);
65 
66 //unsigned
67 ulong[] byte_dots = [1 << 7, 1 << 14, 1 << 21, 1 << 28, cast(ulong) 1 << 35,
68 	cast(ulong) 1 << 42, cast(ulong) 1 << 49, cast(ulong) 1 << 56, cast(ulong) 1 << 63,];
69 
70 //signed
71 ulong[] byte_dots_s = [1 << 6, 1 << 13, 1 << 20, 1 << 27, cast(ulong) 1 << 34,
72 	cast(ulong) 1 << 41, cast(ulong) 1 << 48, cast(ulong) 1 << 55, cast(ulong) 1 << 62,];
73 
74 ubyte getbytenum(ulong v)
75 {
76 	ubyte i = 0;
77 	for (; i < byte_dots.length; i++)
78 	{
79 		if (v < byte_dots[i])
80 		{
81 			break;
82 		}
83 	}
84 	return cast(ubyte)(i + 1);
85 }
86 
87 ubyte getbytenums(ulong v)
88 {
89 	ubyte i = 0;
90 	for (; i < byte_dots_s.length; i++)
91 	{
92 		if (v < byte_dots_s[i])
93 		{
94 			break;
95 		}
96 	}
97 
98 	return cast(ubyte)(i + 1);
99 }
100 
101 //signed
102 byte[] toVariant(T)(T t) if (isSignedType!T)
103 {
104 	bool symbol = false;
105 	if (t < 0)
106 		symbol = true;
107 
108 	ulong val = cast(ulong) abs(t);
109 
110 	ubyte num = getbytenums(val);
111 
112 	ubyte[] var;
113 	if(num == 1)
114 	{
115 		if (symbol)
116 			val = val | 0x40;
117 	}
118 	else{
119 		for (size_t i = num; i > 1; i--)
120 		{
121 			auto n = val / (byte_dots_s[i - 2] * 2);
122 			if (symbol && i == num)
123 				n = n | 0x40;
124 			var ~= cast(ubyte) n;
125 			val = (val % (byte_dots_s[i - 2] * 2));
126 		}
127 	}
128 
129 	var ~= cast(ubyte)(val | 0x80);
130 	return cast(byte[]) var;
131 }
132 
133 T toT(T)(const byte[] b, out long index) if (isSignedType!T)
134 {
135 	T val = 0;
136 	ubyte i = 0;
137 	bool symbol = false;
138 
139 	if(b.length == 1)
140 	{
141 		val = (b[i] & 0x3F);
142 		if (b[i] & 0x40)
143 			symbol = true;
144 	}
145 	else
146 	{
147 		for (i = 0; i < b.length; i++)
148 		{
149 			if (i == 0)
150 			{
151 				val = (b[i] & 0x3F);
152 				if (b[i] & 0x40)
153 					symbol = true;			
154 			}
155 			else
156 			{
157 				val = cast(T)((val << 7) + (b[i] & 0x7F));
158 			}
159 		
160 			if (b[i] & 0x80)
161 				break;
162 		}
163 	}
164 
165 	index = i + 1;
166 	if (symbol)
167 		return cast(T)(val * -1);
168 	else
169 		return val;
170 }
171 
172 //unsigned
173 byte[] toVariant(T)(T t) if (isUnsignedType!T)
174 {
175 	ubyte num = getbytenum(cast(ulong) t);
176 	T val = t;
177 	ubyte[] var;
178 	for (size_t i = num; i > 1; i--)
179 	{
180 		auto n = val / (byte_dots[i - 2]);
181 		var ~= cast(ubyte) n;
182 		val = val % (byte_dots[i - 2]);
183 	}
184 	var ~= cast(ubyte)(val | 0x80);
185 	return cast(byte[]) var;
186 }
187 
188 //unsigned
189 T toT(T)(const byte[] b, out long index) if (isUnsignedType!T)
190 {
191 	T val = 0;
192 	ubyte i = 0;
193 	for (i = 0; i < b.length; i++)
194 	{
195 
196 		val = cast(T)((val << 7) + (b[i] & 0x7F));
197 		if (b[i] & 0x80)
198 			break;
199 	}
200 	index = i + 1;
201 	return val;
202 }
203 
204 byte getbasictype(long size)
205 {
206 	if (size == 1)
207 		return 0;
208 	else if (size == 2)
209 		return 1;
210 	else if (size == 4)
211 		return 2;
212 	else if (size == 8)
213 		return 3;
214 	else
215 		assert(0);
216 }
217 
218 byte getbasicsize(byte type)
219 {
220 	if (type == 0)
221 		return 1;
222 	else if (type == 1)
223 		return 2;
224 	else if (type == 2)
225 		return 4;
226 	else if (type == 3)
227 		return 8;
228 	else
229 		assert(0);
230 }
231 
232 string serializeMembers(T)()
233 {
234 	string str;
235 	foreach (m; FieldNameTuple!T)
236 	{
237 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
238 		{
239 			str ~= "data ~= serialize(t." ~ m ~ " , stack , level + 1);";
240 		}
241 	}
242 	return str;
243 }
244 
245 string unserializeMembers(T)()
246 {
247 	string str;
248 	str ~= "long parse = 0; ";
249 	foreach (m; FieldNameTuple!T)
250 	{
251 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
252 		{
253 			str ~= " if ( index < parse_index)";
254 			str ~= "{";
255 			str ~= "t." ~ m ~ " = unserialize!(typeof(t." ~ m
256 				~ "))(data[cast(uint)index .. data.length] , parse , stack); ";
257 			str ~= "index += parse; }";
258 		}
259 
260 	}
261 	return str;
262 }
263 
264 string getsizeMembers(T)()
265 {
266 	string str;
267 	foreach (m; FieldNameTuple!T)
268 	{
269 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
270 		{
271 		str ~= "total += getsize(t." ~ m ~ " , stack , level + 1);";
272 		}		
273 	}
274 	return str;
275 }
276 
277 ///////////////////////////////////////////////////////////
278 // basic
279 // type 		  size
280 //  0     - 		1
281 //  1	 -			2
282 //  2	 -			4
283 //  3	 - 			8
284 //	data
285 ///////////////////////////////////////////////////////////
286 ///
287 byte[] serialize(T)(T t, RefClass stack, uint level)
288 		if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum))
289 {
290 	byte[] data;
291 	data.length = T.sizeof + 1;
292 	data[0] = getbasictype(T.sizeof);
293 	memcpy(data.ptr + 1, &t, T.sizeof);
294 	return data;
295 }
296 
297 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
298 		if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum))
299 {
300 	assert(cast(byte) T.sizeof == getbasicsize(data[0]));
301 
302 	T value;
303 	memcpy(&value, data.ptr + 1, T.sizeof);
304 
305 	parse_index = T.sizeof + 1;
306 	return value;
307 }
308 
309 size_t getsize(T)(T t, RefClass stack, uint level)
310 		if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum))
311 {
312 	return T.sizeof + 1;
313 }
314 
315 ///////////////////////////////////////////////////////////
316 // variant
317 // type 		  size
318 //  5 (4)    - 		
319 //  6 (8)	 -
320 //	data
321 ///////////////////////////////////////////////////////////
322 byte[] serialize(T)(T t, RefClass stack, uint level)
323 		if (isBigSignedType!T || isBigUnsignedType!T)
324 {
325 	byte[] data = toVariant!T(t);
326 	long index;
327 	byte[1] h;
328 	h[0] = (T.sizeof == 4) ? 5 : 8;
329 	return h ~ data;
330 }
331 
332 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
333 		if (isBigSignedType!T || isBigUnsignedType!T)
334 {
335 	assert((T.sizeof == 4 ? 5 : 8) == data[0]);
336 	long index;
337 	T t = toT!T(data[1 .. $], index);
338 	parse_index = index + 1;
339 	return t;
340 }
341 
342 size_t getsize(T)(T t, RefClass stack, uint level) if (isBigSignedType!T)
343 {
344 	return getbytenums(abs(t)) + 1;
345 }
346 
347 size_t getsize(T)(T t, RefClass stack, uint level) if (isBigUnsignedType!T)
348 {
349 	return getbytenum(abs(t)) + 1;
350 }
351 
352 // TString
353 // 1 type 7
354 // [uint] variant 
355 //  data
356 
357 byte[] serialize(T)(T str, RefClass stack, uint level) if (is(T == string))
358 {
359 	byte[] data;
360 	uint len = cast(uint) str.length;
361 	byte[] dlen = toVariant(len);
362 	data.length = 1 + dlen.length + len;
363 
364 	data[0] = 7;
365 	memcpy(data.ptr + 1, dlen.ptr, dlen.length);
366 	memcpy(data.ptr + 1 + dlen.length, str.ptr, len);
367 	return data;
368 }
369 
370 string unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
371 		if (is(T == string))
372 {
373 	assert(data[0] == 7);
374 	long index;
375 	uint len = toT!uint(data[1 .. $], index);
376 	parse_index += 1 + index + len;
377 	return cast(T)(data[cast(size_t)(1 + index) .. cast(size_t) parse_index].dup);
378 }
379 
380 size_t getsize(T)(T str, RefClass stack, uint level) if (is(T == string))
381 {
382 	uint len = cast(uint) str.length;
383 	return cast(size_t)(1 + toVariant(len).length + str.length);
384 }
385 
386 // TUnion			don't support TUnion
387 // 1 type 6
388 // 1 len 
389 // 	 data
390 
391 /*
392 byte[] serialize(T)(T t) if(is(T == union))
393 {
394 	byte[] data;
395 	data.length = T.sizeof + 2;
396 	data[0] = 5;
397 	data[1] = T.sizeof;
398 	memcpy(data.ptr + 2 , &t , T.sizeof);
399 	return data;
400 }
401 T unserialize(T)(const byte[] data ) if(is(T == union))
402 {
403 	long parser_index;
404 	return unserialize!T(data , parser_index);
405 }
406 T unserialize(T)(const byte[] data , out long parse_index) if(is(T == union))
407 {
408 	assert(data[0] == 5);
409 	
410 	T value;
411 	byte len;
412 	memcpy(&len , data.ptr + 1 , 1);
413 	parse_index = 2 + len;
414 	memcpy(&value , data.ptr + 2 , len);
415 	return value;
416 }
417 size_t getsize(T)(T t) if(is(T == union))
418 {
419 	return 2 + T.sizeof;
420 }
421 */
422 
423 // TSArray
424 // 1 type 8
425 // size[uint] variant
426 // len[uint] variant
427 // data
428 
429 byte[] serialize(T)(T t, RefClass stack, uint level) if (isStaticArray!T)
430 {
431 	byte[1] header;
432 	header[0] = 8;
433 	uint uSize = cast(uint) t.length;
434 	byte[] dh = cast(byte[]) header;
435 	dh ~= toVariant(uSize);
436 
437 	byte[] data;
438 	for (size_t i = 0; i < uSize; i++)
439 	{
440 		data ~= serialize(t[i], stack, level + 1);
441 	}
442 	uint len = cast(uint) data.length;
443 	dh ~= toVariant(len);
444 	return dh ~ data;
445 }
446 
447 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
448 		if (isStaticArray!T)
449 {
450 	assert(data[0] == 8);
451 	T value;
452 	uint uSize;
453 	uint len;
454 	long index1;
455 	long index2;
456 	uSize = toT!uint(data[1 .. $], index1);
457 
458 	len = toT!uint(data[cast(size_t)(index1 + 1) .. $], index2);
459 	parse_index += 1 + index1 + index2;
460 
461 	long index = parse_index;
462 	long parse = 0;
463 	for (size_t i = 0; i < uSize; i++)
464 	{
465 		parse = 0;
466 		value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length],
467 				parse, stack);
468 		index += parse;
469 	}
470 
471 	parse_index += len;
472 
473 	return value;
474 }
475 
476 size_t getsize(T)(T t, RefClass stack, uint level) if (isStaticArray!T)
477 {
478 	long total = 1;
479 	total += getbytenum(t.length);
480 	uint uSize = cast(uint) t.length;
481 	for (size_t i = 0; i < uSize; i++)
482 	{
483 		total += getsize(t[i], stack, level + 1);
484 	}
485 	total += getbytenum(total);
486 	return total;
487 }
488 
489 //  TDArray
490 // 1  type 9
491 // size[uint]	variant
492 // length[uint]	variant
493 // data
494 
495 byte[] serialize(T)(T t, RefClass stack, uint level)
496 		if (isDynamicArray!T && !is(T == string) && !is(T == enum))
497 {
498 	byte[1] header;
499 	header[0] = 9;
500 
501 	uint uSize = cast(uint) t.length;
502 	byte[] dh = cast(byte[]) header;
503 	dh ~= toVariant(uSize);
504 
505 	byte[] data;
506 	for (size_t i = 0; i < uSize; i++)
507 	{
508 		data ~= serialize(t[i], stack, level + 1);
509 	}
510 	uint len = cast(uint) data.length;
511 	dh ~= toVariant(len);
512 
513 	return dh ~ data;
514 }
515 
516 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
517 		if (isDynamicArray!T && !is(T == string) && !is(T == enum))
518 {
519 	assert(data[0] == 9);
520 
521 	T value;
522 	uint uSize;
523 	uint len;
524 	long index1;
525 	long index2;
526 	uSize = toT!uint(data[1 .. $], index1);
527 	len = toT!uint(data[cast(size_t)(1 + index1) .. $], index2);
528 
529 	parse_index += 1 + index1 + index2;
530 	value.length = uSize;
531 	ulong index = parse_index;
532 	long parse = 0;
533 	for (size_t i = 0; i < uSize; i++)
534 	{
535 		value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length],
536 				parse, stack);
537 		index += parse;
538 	}
539 	parse_index += len;
540 
541 	return value;
542 }
543 
544 size_t getsize(T)(T t, RefClass stack, uint level)
545 		if (isDynamicArray!T && !is(T == string) && !is(T == enum) )
546 {
547 	long total = 1;
548 	total += getbytenum(t.length);
549 	uint uSize = cast(uint) t.length;
550 	for (size_t i = 0; i < uSize; i++)
551 	{
552 		total += getsize(t[i], stack, level + 1);
553 	}
554 	total += getbytenum(total);
555 	return total;
556 }
557 
558 // TStruct
559 // 1 type 10
560 // [uint] variant
561 // data
562 
563 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == struct))
564 {
565 	byte[1] header;
566 	header[0] = 10;
567 	byte[] data;
568 
569 	mixin(serializeMembers!T());
570 	byte[] dh = cast(byte[]) header;
571 	uint len = cast(uint) data.length;
572 	dh ~= toVariant(len);
573 	return dh ~ data;
574 }
575 
576 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
577 		if (is(T == struct))
578 {
579 	assert(data[0] == 10);
580 
581 	T t;
582 	long index1;
583 	uint len = toT!uint(data[1 .. $], index1);
584 
585 	parse_index = 1 + index1 + len;
586 	long index = 1 + index1;
587 	mixin(unserializeMembers!T());
588 
589 	return t;
590 }
591 
592 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == struct))
593 {
594 	long total = 1;
595 
596 	mixin(getsizeMembers!T());
597 
598 	total += getbytenum(total);
599 	return cast(uint) total;
600 }
601 
602 // TClass 
603 // 1 type 11
604 // [uint] len variant
605 //	data
606 
607 // TClass ref
608 // 1 type 12
609 // id variant
610 
611 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == class))
612 {
613 	byte[1] header;
614 	size_t* id = null;
615 
616 	if (t !is null)
617 	{
618 		id = t.toHash() in stack.map;
619 	}
620 
621 	if (id == null)
622 	{
623 		header[0] = 11;
624 		byte[] data;
625 		byte[] dh = cast(byte[]) header;
626 		if (t !is null)
627 		{
628 			stack.map[t.toHash()] = stack.map.length;
629 			mixin(serializeMembers!T());
630 		}
631 		uint len = cast(uint) data.length;
632 		dh ~= toVariant(len);
633 
634 		return dh ~ data;
635 	}
636 	else
637 	{
638 		header[0] = 12;
639 		byte[] dh = cast(byte[]) header;
640 		dh ~= toVariant(*id);
641 		return dh;
642 	}
643 
644 }
645 
646 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
647 		if (is(T == class))
648 {
649 	assert(data[0] == 11 || data[0] == 12);
650 
651 	if (data[0] == 11)
652 	{
653 		long index1;
654 		uint len = toT!uint(data[1 .. $], index1);
655 		if (len == 0)
656 			return null;
657 		T t = new T;
658 		parse_index = index1 + 1 + len;
659 		long index = index1 + 1;
660 		stack.arr ~= cast(void*) t;
661 		mixin(unserializeMembers!T());
662 		return t;
663 	}
664 	else
665 	{
666 		long index1;
667 		size_t id = toT!size_t(data[1 .. $], index1);
668 		parse_index += index1 + 1;
669 		return cast(T) stack.arr[id];
670 	}
671 
672 }
673 
674 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == class))
675 {
676 	long total = 1;
677 
678 	size_t* id = null;
679 
680 	if (t !is null)
681 	{
682 		id = t.toHash() in stack.map;
683 	}
684 
685 	if (id == null)
686 	{
687 		if (t !is null)
688 		{
689 			stack.map[t.toHash()] = stack.map.length;
690 			mixin(getsizeMembers!T());
691 		}
692 
693 		total += getbytenum(total - 1);
694 		return total;
695 	}
696 	else
697 	{
698 		return getbytenum(*id) + 1;
699 	}
700 
701 }
702 
703 // AssociativeArray
704 // 1 type 13
705 // [uint] len variant
706 // (k,v)
707 
708 byte[] serialize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T)
709 {
710 	byte[1] header;
711 	header[0] = 13;
712 	byte[] dh;
713 	dh ~= cast(byte[]) header;
714 	byte[] data;
715 	foreach (k, v; t)
716 	{
717 		data ~= serialize(k, stack, level + 1);
718 		data ~= serialize(v, stack, level + 1);
719 	}
720 	uint len = cast(uint) data.length;
721 	dh ~= toVariant(len);
722 	return dh ~ data;
723 }
724 
725 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
726 		if (isAssociativeArray!T)
727 {
728 	assert(data[0] == 13);
729 
730 	T t;
731 	long index1;
732 	uint len = toT!uint(data[1 .. $], index1);
733 
734 	parse_index = index1 + 1 + len;
735 	long index = index1 + 1;
736 	while (index < parse_index)
737 	{
738 		long out_len;
739 		auto k = unserialize!(KeyType!T)(data[index .. $], out_len, stack);
740 		index += out_len;
741 		out_len = 0;
742 		auto v = unserialize!(ValueType!T)(data[index .. $], out_len, stack);
743 		index += out_len;
744 		t[k] = v;
745 	}
746 	return t;
747 }
748 
749 size_t getsize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T)
750 {
751 	long total = 1;
752 	foreach (k, v; t)
753 	{
754 		total += serialize(k).length;
755 		total += serialize(v).length;
756 	}
757 	total += getbytenum(total - 1);
758 	return total;
759 }
760 
761 // named enum
762 // 1 type 14
763 // 2 [uint] len 
764 // 3 other
765 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == enum))
766 {
767 	byte[1] header;
768 	header[0] = 14;
769 	byte[] dh;
770 	dh ~= cast(byte[]) header;
771 	OriginalType!T v = cast(OriginalType!T)t;
772 	byte[] data =  serialize(v);
773 	uint len = cast(uint)data.length;
774 	dh ~= toVariant(len);
775 	return dh ~ data;
776 }
777 
778 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack)
779 		if (is(T == enum))
780 {
781 	assert(data[0] == 14);
782 
783 	T t;
784 	long index1;
785 	uint len = toT!uint(data[1 .. $], index1);
786 
787 	parse_index = index1 + 1 + len;
788 	long index = index1 + 1;
789 	while (index < parse_index)
790 	{
791 		long out_len = 0;
792 		t = cast(T)unserialize!(OriginalType!T)(data[index .. $], out_len, stack);
793 		index += out_len;
794 	}
795 	return t;
796 }
797 
798 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == enum))
799 {
800 	long total = 1;
801 	
802 	total += serialize(cast(OriginalType!T)t).length;
803 	
804 	total += getbytenum(total - 1);
805 	return total;
806 }
807 
808 
809 
810 public:
811 
812 T unserialize(T)(const byte[] data )
813 {
814 	long parse_index;
815 	return unserialize!T(data, parse_index);
816 }
817 
818 T unserialize(T)(const byte[] data, out long parse_index )
819 {
820 	RefClass stack = new RefClass();
821 	return unserialize!T(data, parse_index, stack);
822 }
823 
824 byte[] serialize(T)(T t )
825 {
826 	RefClass stack = new RefClass();
827 	return serialize!T(t, stack, 0);
828 }
829 
830 size_t getsize(T)(T t )
831 {
832 	RefClass stack = new RefClass();
833 	return getsize!T(t, stack, 0);
834 }
835 
836 //////////////////////////////////////////////////////////////////json///////////////////////////
837 private:
838 enum bool isFloatType(T) = isType!(T, float) || isType!(T, double);
839 
840 JSONValue toJson(T)(T t, RefClass stack, uint level)
841 		if (isSignedType!T || isUnsignedType!T || is(T == string) || is(T == bool) || isFloatType!T)
842 {
843 	return JSONValue(t);
844 }
845 
846 // uinteger
847 T toObject(T)(JSONValue v, RefClass stack) if (isUnsignedType!T)
848 {
849 	if(v.type() == JSON_TYPE.UINTEGER)
850 		return cast(T) v.uinteger;
851 	else
852 		return T.init;
853 }
854 
855 // integer
856 T toObject(T)(JSONValue v, RefClass stack) if (isSignedType!T)
857 {
858 	if(v.type() == JSON_TYPE.INTEGER)
859 		return cast(T) v.integer;
860 	else
861 		return T.init;
862 }
863 
864 // string
865 T toObject(T)(JSONValue v, RefClass stack) if (is(T == string))
866 {
867 	if(v.type() == JSON_TYPE.STRING)
868 		return v.str;
869 	else
870 		return T.init;
871 }
872 
873 // bool
874 T toObject(T)(JSONValue v, RefClass stack) if (is(T == bool))
875 {
876 	if(v.type() == JSON_TYPE.TRUE || v.type() == JSON_TYPE.FALSE)
877 		return v.type() == JSON_TYPE.TRUE;
878 	else
879 		return T.init;
880 }
881 
882 // floating
883 T toObject(T)(JSONValue v, RefClass stack) if (isFloatType!T)
884 {
885 	if(v.type() == JSON_TYPE.FLOAT)
886 		return cast(T) v.floating;
887 	else
888 		return  T.init;
889 }
890 
891 
892 // array
893 JSONValue toJson(T)(T t, RefClass stack, uint level)
894 		if (isStaticArray!T || (isDynamicArray!T && !is(T == string) && !is(T == enum)))
895 {
896 	JSONValue[] j;
897 	foreach (e; t)
898 	{
899 		j ~= toJson(e, stack, level);
900 	}
901 
902 	return JSONValue(j);
903 }
904 
905 T toObject(T)(JSONValue v, RefClass stack) if (isStaticArray!T)
906 {
907 	T t;
908 	if(v.type() == JSON_TYPE.ARRAY)
909 	{
910 		for (size_t i = 0; i < t.length; i++)
911 		{
912 			t[i] = toObject!(typeof(t[i]))(v.array[i], stack);
913 		}
914 	}
915 	return t;
916 	
917 }
918 
919 T toObject(T)(JSONValue v, RefClass stack) if (isDynamicArray!T && !is(T == string)&& !is(T == enum))
920 {
921 	T t;
922 	if(v.type() == JSON_TYPE.ARRAY)
923 	{
924 		t.length = v.array.length;
925 		for (size_t i = 0; i < t.length; i++)
926 		{
927 			t[i] = toObject!(typeof(t[i]))(v.array[i], stack);
928 		}
929 	}
930 	return t;
931 }
932 
933 // struct & class
934 
935 string toJsonMembers(T , bool ignore)()
936 {
937 	string str;
938 	foreach (m; FieldNameTuple!T)
939 	{
940 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
941 		{
942 			if(!ignore || !hasUDA!(__traits(getMember , T , m) ,IGNORE ))
943 			{
944 				str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);";
945 			}	
946 		}
947 	}
948 	return str;
949 }
950 
951 string toJsonMembersAll(T)()
952 {
953 	string str;
954 	foreach (m; FieldNameTuple!T)
955 	{
956 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
957 		{		
958 			str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);";
959 		}
960 	}
961 	return str;
962 }
963 
964 
965 
966 string toObjectMembers(T)()
967 {
968 	string str;
969 	foreach (m; FieldNameTuple!T)
970 	{
971 		static if (__traits(getProtection, __traits(getMember, T, m)) == "public")
972 		{
973 			str ~= " if ( \"" ~ m ~ "\"  in j )";
974 			str ~= "t." ~ m ~ " = toObject!(typeof(t." ~ m ~ "))(j[\"" ~ m ~ "\"] , stack);";
975 		}
976 
977 	}
978 	return str;
979 }
980 
981 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == struct))
982 {
983 	JSONValue j;
984 
985 	static if (is(T == JSONValue))
986 	{
987 		return t;
988 	}
989 	else{
990 		bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T);
991 
992 		if(ignore)
993 			mixin(toJsonMembers!(T,true));
994 		else
995 			mixin(toJsonMembers!(T,false));
996 
997 
998 
999 
1000 		
1001 		return j;
1002 	}
1003 }
1004 
1005 T toObject(T)(JSONValue j, RefClass stack) if (is(T == struct))
1006 {
1007 	static if (is(T == JSONValue))
1008 	{
1009 		return j;
1010 	}
1011 	else
1012 	{
1013 		T t;
1014 		if(j.type() == JSON_TYPE.OBJECT)
1015 		{
1016 			mixin(toObjectMembers!T);
1017 		}
1018 		return t;
1019 	}
1020 }
1021 
1022 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == class))
1023 {
1024 	if (t is null || level >= stack.level)
1025 	{
1026 		return JSONValue(null);
1027 	}
1028 
1029 	auto id = t.toHash() in stack.map;
1030 	if (id == null)
1031 	{
1032 		stack.map[t.toHash()] = stack.map.length;
1033 		JSONValue j;
1034 		bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T);
1035 
1036 		if(ignore)
1037 			mixin(toJsonMembers!(T,true));
1038 		else
1039 			mixin(toJsonMembers!(T,false));
1040 		return j;
1041 	}
1042 	else
1043 	{
1044 		JSONValue j;
1045 		j[MAGIC_KEY] = *id;
1046 		return j;
1047 	}
1048 }
1049 
1050 T toObject(T)(JSONValue j, RefClass stack) if (is(T == class))
1051 {
1052 	if ( j.type() != JSON_TYPE.OBJECT)
1053 		return T.init;
1054 	assert(j.type() == JSON_TYPE.OBJECT);
1055 
1056 	if (MAGIC_KEY in j)
1057 	{
1058 		return cast(T) stack.arr[j[MAGIC_KEY].uinteger];
1059 	}
1060 	else
1061 	{
1062 		T t = new T;
1063 		stack.arr ~= cast(void*) t;
1064 		mixin(toObjectMembers!T);
1065 		return t;
1066 	}
1067 }
1068 
1069 //AssociativeArray
1070 JSONValue toJson(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T)
1071 {
1072 	JSONValue j;
1073 	import std.conv;
1074 
1075 	foreach (k, v; t)
1076 		j[to!string(k)] = toJson(v, stack, level);
1077 	return j;
1078 }
1079 
1080 T toObject(T)(JSONValue j, RefClass stack) if (isAssociativeArray!T)
1081 {
1082 	import std.conv;
1083 	if ( j.type() != JSON_TYPE.OBJECT)
1084 		return T.init;
1085 	T t;
1086 	foreach (k, v; j.object)
1087 	{
1088 		t[to!(KeyType!T)(k)] = toObject!(ValueType!T)(v, stack);
1089 	}
1090 	return t;
1091 }
1092 
1093 //enum
1094 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == enum))
1095 {
1096 	
1097 	auto j =  JSONValue(cast(OriginalType!T)t);
1098 	writeln(j.type());
1099 	return j;
1100 }
1101 
1102 T toObject(T)(JSONValue j, RefClass stack) if (is(T == enum))
1103 {
1104 	import std.conv;
1105 	writeln(j , " " , j.type() , typeid(T));
1106 	OriginalType!T val;
1107 	static if (is(OriginalType!T == string ))
1108 	{
1109 		if(j.type() == JSON_TYPE.STRING)
1110 			val = cast(OriginalType!T)j.str;
1111 		else
1112 			return T.init;
1113 	}
1114 	else static if (is(OriginalType!T == int))
1115 	{
1116 		if(j.type() == JSON_TYPE.integer)
1117 			val = cast(OriginalType!T)j.integer;
1118 		else if(j.type() == JSON_TYPE.uinteger)
1119 			val = cast(OriginalType!T)j.uinteger;
1120 		else
1121 			return T.init;
1122 	}
1123 
1124 	return cast(T)val;	
1125 }
1126 
1127 public:
1128 
1129 JSONValue toJson(T)(T t , uint level = uint.max , bool ignore = true)
1130 {
1131 	RefClass stack = new RefClass();
1132 	stack.level = level;
1133 	stack.ignore = ignore;
1134 	return toJson!T(t, stack, 0);
1135 }
1136 
1137 JSONValue toJson(T)(T t   , UnIgnoreArray array  ,  uint level = uint.max)
1138 {
1139 	RefClass stack = new RefClass();
1140 	stack.level = level;
1141 	stack.unIgnore = array;
1142 	return toJson!T(t, stack, 0);
1143 }
1144 
1145 T toObject(T)(JSONValue j)
1146 {
1147 	RefClass stack = new RefClass();
1148 	return toObject!T(j, stack);
1149 }
1150 
1151 deprecated("Using toJson instead.")
1152 alias toJSON = toJson;
1153 
1154 deprecated("Using toObject instead.")
1155 alias toOBJ = toObject;
1156 
1157 ////------------------------- toTextString ------
1158 /**
1159 Takes a tree of JSON values and returns the serialized string.
1160 
1161 Any Object types will be serialized in a key-sorted order.
1162 
1163 If `pretty` is false no whitespaces are generated.
1164 If `pretty` is true serialized string is formatted to be human-readable.
1165 Set the $(LREF JSONOptions.specialFloatLiterals) flag is set in `options` to encode NaN/Infinity as strings.
1166 */
1167 string toTextString(const ref JSONValue root, in bool pretty = false, in JSONOptions options = JSONOptions.none) @safe
1168 {
1169 	import std.array;
1170 	import std.conv;
1171 	import std.string;
1172 
1173     auto json = appender!string();
1174 
1175     void toStringImpl(Char)(string str) @safe
1176     {
1177         json.put('"');
1178 
1179         foreach (Char c; str)
1180         {
1181             switch (c)
1182             {
1183                 case '"':       json.put("\\\"");       break;
1184                 case '\\':      json.put("\\\\");       break;
1185 
1186                 case '/':
1187                     if (!(options & JSONOptions.doNotEscapeSlashes))
1188                         json.put('\\');
1189                     json.put('/');
1190                     break;
1191 
1192                 case '\b':      json.put("\\b");        break;
1193                 case '\f':      json.put("\\f");        break;
1194                 case '\n':      json.put("\\n");        break;
1195                 case '\r':      json.put("\\r");        break;
1196                 case '\t':      json.put("\\t");        break;
1197                 default:
1198                 {
1199                     import std.ascii : isControl;
1200                     import std.utf : encode;
1201 
1202                     // Make sure we do UTF decoding iff we want to
1203                     // escape Unicode characters.
1204                     assert(((options & JSONOptions.escapeNonAsciiChars) != 0)
1205                         == is(Char == dchar), "JSONOptions.escapeNonAsciiChars needs dchar strings");
1206 
1207                     with (JSONOptions) if (isControl(c) ||
1208                         ((options & escapeNonAsciiChars) >= escapeNonAsciiChars && c >= 0x80))
1209                     {
1210                         // Ensure non-BMP characters are encoded as a pair
1211                         // of UTF-16 surrogate characters, as per RFC 4627.
1212                         wchar[2] wchars; // 1 or 2 UTF-16 code units
1213                         size_t wNum = encode(wchars, c); // number of UTF-16 code units
1214                         foreach (wc; wchars[0 .. wNum])
1215                         {
1216                             json.put("\\u");
1217                             foreach_reverse (i; 0 .. 4)
1218                             {
1219                                 char ch = (wc >>> (4 * i)) & 0x0f;
1220                                 ch += ch < 10 ? '0' : 'A' - 10;
1221                                 json.put(ch);
1222                             }
1223                         }
1224                     }
1225                     else
1226                     {
1227                         json.put(c);
1228                     }
1229                 }
1230             }
1231         }
1232 
1233         json.put('"');
1234     }
1235 
1236     void toString(string str) @safe
1237     {
1238         // Avoid UTF decoding when possible, as it is unnecessary when
1239         // processing JSON.
1240         if (options & JSONOptions.escapeNonAsciiChars)
1241             toStringImpl!dchar(str);
1242         else
1243             toStringImpl!char(str);
1244     }
1245 
1246     void toValue(ref in JSONValue value, ulong indentLevel) @safe
1247     {
1248         void putTabs(ulong additionalIndent = 0)
1249         {
1250             if (pretty)
1251                 foreach (i; 0 .. indentLevel + additionalIndent)
1252                     json.put("    ");
1253         }
1254         void putEOL()
1255         {
1256             if (pretty)
1257                 json.put('\n');
1258         }
1259         void putCharAndEOL(char ch)
1260         {
1261             json.put(ch);
1262             putEOL();
1263         }
1264 
1265         final switch (value.type)
1266         {
1267             case JSON_TYPE.OBJECT:
1268                 auto obj = value.objectNoRef;
1269                 if (!obj.length)
1270                 {
1271                     json.put("{}");
1272                 }
1273                 else
1274                 {
1275                     putCharAndEOL('{');
1276                     bool first = true;
1277 
1278                     void emit(R)(R names)
1279                     {
1280                         foreach (name; names)
1281                         {
1282                             auto member = obj[name];
1283                             if (!first)
1284                                 putCharAndEOL(',');
1285                             first = false;
1286                             putTabs(1);
1287                             toString(name);
1288                             json.put(':');
1289                             if (pretty)
1290                                 json.put(' ');
1291                             toValue(member, indentLevel + 1);
1292                         }
1293                     }
1294 
1295                     import std.algorithm.sorting : sort;
1296                     // @@@BUG@@@ 14439
1297                     // auto names = obj.keys;  // aa.keys can't be called in @safe code
1298                     auto names = new string[obj.length];
1299                     size_t i = 0;
1300                     foreach (k, v; obj)
1301                     {
1302                         names[i] = k;
1303                         i++;
1304                     }
1305                     sort(names);
1306                     emit(names);
1307 
1308                     putEOL();
1309                     putTabs();
1310                     json.put('}');
1311                 }
1312                 break;
1313 
1314             case JSON_TYPE.ARRAY:
1315                 auto arr = value.arrayNoRef;
1316                 if (arr.empty)
1317                 {
1318                     json.put("[]");
1319                 }
1320                 else
1321                 {
1322                     putCharAndEOL('[');
1323                     foreach (i, el; arr)
1324                     {
1325                         if (i)
1326                             putCharAndEOL(',');
1327                         putTabs(1);
1328                         toValue(el, indentLevel + 1);
1329                     }
1330                     putEOL();
1331                     putTabs();
1332                     json.put(']');
1333                 }
1334                 break;
1335 
1336             case JSON_TYPE.STRING:
1337                 toString(value.str);
1338                 break;
1339 
1340             case JSON_TYPE.INTEGER:
1341                 json.put(to!string(value.integer));
1342                 break;
1343 
1344             case JSON_TYPE.UINTEGER:
1345                 json.put(to!string(value.uinteger));
1346                 break;
1347 
1348             case JSON_TYPE.FLOAT:
1349                 import std.math : isNaN, isInfinity;
1350 
1351                 auto val = value.floating;
1352 
1353                 if (val.isNaN)
1354                 {
1355                     if (options & JSONOptions.specialFloatLiterals)
1356                     {
1357                         toString(JSONFloatLiteral.nan);
1358                     }
1359                     else
1360                     {
1361                         throw new JSONException(
1362                             "Cannot encode NaN. Consider passing the specialFloatLiterals flag.");
1363                     }
1364                 }
1365                 else if (val.isInfinity)
1366                 {
1367                     if (options & JSONOptions.specialFloatLiterals)
1368                     {
1369                         toString((val > 0) ?  JSONFloatLiteral.inf : JSONFloatLiteral.negativeInf);
1370                     }
1371                     else
1372                     {
1373                         throw new JSONException(
1374                             "Cannot encode Infinity. Consider passing the specialFloatLiterals flag.");
1375                     }
1376                 }
1377                 else
1378                 {
1379                     import std.format : format;
1380                     // The correct formula for the number of decimal digits needed for lossless round
1381                     // trips is actually:
1382                     //     ceil(log(pow(2.0, double.mant_dig - 1)) / log(10.0) + 1) == (double.dig + 2)
1383                     // Anything less will round off (1 + double.epsilon)
1384                     json.put("%s".format(val));
1385                 }
1386                 break;
1387 
1388             case JSON_TYPE.TRUE:
1389                 json.put("true");
1390                 break;
1391 
1392             case JSON_TYPE.FALSE:
1393                 json.put("false");
1394                 break;
1395 
1396             case JSON_TYPE.NULL:
1397                 json.put("null");
1398                 break;
1399         }
1400     }
1401 
1402     toValue(root, 0);
1403     return json.data;
1404 }
1405 
1406 
1407 
1408 // only for , nested , new T
1409 /*
1410 version (unittest)
1411 {
1412 	//test struct
1413 		void test1(T)(T t)
1414 		{
1415 			assert(unserialize!T(serialize(t)) == t);
1416 			assert(serialize(t).length == getsize(t));
1417 			assert(toObject!T(toJson(t)) == t);
1418 		}
1419 		struct T1
1420 		{
1421 			bool b;
1422 			byte ib;
1423 			ubyte ub;
1424 			short ish;
1425 			ushort ush;
1426 			int ii;
1427 			uint ui;
1428 			long il;
1429 			ulong ul;
1430 			string s;
1431 			uint[10] sa;
1432 			long[] sb;
1433 		}
1434 		struct T2
1435 		{
1436 			string n;
1437 			T1[] t;
1438 		}
1439 		struct T3
1440 		{
1441 			T1 t1;
1442 			T2 t2;
1443 			string[] name;
1444 		}
1445 		//test class
1446 		class C
1447 		{
1448 			int age;
1449 			string name;
1450 			T3 t3;
1451 			override bool opEquals(Object c)
1452 			{
1453 				auto c1 = cast(C) c;
1454 				return age == c1.age && name == c1.name && t3 == c1.t3;
1455 			}
1456 			C clone()
1457 			{
1458 				auto c = new C();
1459 				c.age = age;
1460 				c.name = name;
1461 				c.t3 = t3;
1462 				return c;
1463 			}
1464 		}
1465 		class C2
1466 		{
1467 			C[] c;
1468 			C c1;
1469 			T1 t1;
1470 			override bool opEquals(Object c)
1471 			{
1472 				auto c2 = cast(C2) c;
1473 				return this.c == c2.c && c1 == c2.c1 && t1 == c2.t1;
1474 			}
1475 		}
1476 		//ref test
1477 		class School
1478 		{
1479 			string name;
1480 			User[] users;
1481 			override bool opEquals(Object c)
1482 			{
1483 				auto school = cast(School) c;
1484 				return school.name == this.name;
1485 			}
1486 		}
1487 		class User
1488 		{
1489 			int age;
1490 			string name;
1491 			School school;
1492 			override bool opEquals(Object c)
1493 			{
1494 				auto user = cast(User) c;
1495 				return user.age == this.age && user.name == this.name && user.school == this.school;
1496 			}
1497 		}
1498 		struct J{
1499 			string data;
1500 			JSONValue val;
1501 		
1502 		}
1503 
1504 		enum MONTH
1505 		{
1506 			M1,
1507 			M2
1508 		}
1509 
1510 		enum WEEK : int
1511 		{
1512 			K1 = 1,
1513 			K2 = 2
1514 		}
1515 
1516 		enum DAY : string
1517 		{
1518 			D1 = "one",
1519 			D2 = "two"
1520 		}
1521 
1522 		class Date1
1523 		{
1524 			MONTH month;
1525 			WEEK week;
1526 			DAY day;
1527 			override bool opEquals(Object c)
1528 			{
1529 				auto date = cast(Date1) c;
1530 				return date.month == this.month && date.week == this.week && date.day == this.day;
1531 			}
1532 
1533 		}
1534 
1535 		void test_enum_ser()
1536 		{
1537 			Date1 date = new Date1();
1538 			date.month = MONTH.M2;
1539 			date.week = WEEK.K2;
1540 			date.day = DAY.D2;
1541 			test1(date);
1542 			
1543 		}
1544 
1545 		void test_json_ser()
1546 		{
1547 			J j;
1548 			j.data = "test";
1549 			j.val = "FUC";
1550 			toObject!J(toJson(j));
1551 		}
1552 		void test_ref_class()
1553 		{
1554 			School school = new School();
1555 			User user1 = new User();
1556 			user1.age = 30;
1557 			user1.name = "zhangyuchun";
1558 			user1.school = school;
1559 			User user2 = new User();
1560 			user2.age = 31;
1561 			user2.name = "wulishan";
1562 			user2.school = school;
1563 			school.name = "putao";
1564 			school.users ~= user1;
1565 			school.users ~= user2;
1566 			test1(user1);
1567 			test1(user2);
1568 		}
1569 		void test_struct_class_array()
1570 		{
1571 			T1 t;
1572 			t.b = true;
1573 			t.ib = -11;
1574 			t.ub = 128 + 50;
1575 			t.ish = -50;
1576 			t.ush = (1 << 15) + 50;
1577 			t.ii = -50;
1578 			t.ui = (1 << 31) + 50;
1579 			t.il = (cast(long) 1 << 63) - 50;
1580 			t.ul = (cast(long) 1 << 63) + 50;
1581 			t.s = "test";
1582 			t.sa[0] = 10;
1583 			t.sa[1] = 100;
1584 			t.sb ~= 10;
1585 			t.sb ~= 100;
1586 			test1(t);
1587 			T2 t2;
1588 			t2.t ~= t;
1589 			t2.t ~= t;
1590 			t2.n = "testt2";
1591 			test1(t2);
1592 			T3 t3;
1593 			t3.t1 = t;
1594 			t3.t2 = t2;
1595 			t3.name ~= "123";
1596 			t3.name ~= "456";
1597 			test1(t3);
1598 			C c1 = new C();
1599 			c1.age = 100;
1600 			c1.name = "test";
1601 			c1.t3 = t3;
1602 			test1(c1);
1603 			C2 c2 = new C2();
1604 			c2.c ~= c1;
1605 			c2.c ~= c1.clone();
1606 			c2.c1 = c1.clone();
1607 			c2.t1 = t;
1608 			test1(c2);
1609 			C2 c3 = null;
1610 			test1(c3);
1611 			string[string] map1 = ["1" : "1", "2" : "2"];
1612 			string[int] map2 = [1 : "1", 2 : "2"];
1613 			T1[string] map3;
1614 			T1 a1;
1615 			a1.ib = 1;
1616 			T1 a2;
1617 			a2.ib = 2;
1618 			map3["1"] = a1;
1619 			map3["2"] = a2;
1620 			test1(map1);
1621 			test1(map2);
1622 			test1(map3);
1623 		}
1624 	
1625 }
1626 unittest
1627 {
1628 	import std.stdio;
1629 	long index;
1630 	void test(T)(T v)
1631 	{
1632 		long index;
1633 		byte[] bs = toVariant(v);
1634 		long length = bs.length;
1635 		bs ~= ['x', 'y'];
1636 		assert(toT!T(bs, index) == v && index == length);
1637 		assert(toObject!T(toJson(v)) == v);
1638 	}
1639 	//test variant
1640 	//unsigned
1641 	{
1642 		ubyte j0 = 0;
1643 		ubyte j1 = 50;
1644 		ubyte j2 = (1 << 7) + 50;
1645 		ubyte j3 = 0xFF;
1646 		ushort j4 = (1 << 14) + 50;
1647 		ushort j5 = 0xFFFF;
1648 		uint j6 = (1 << 21) + 50;
1649 		uint j7 = (1 << 28) + 50;
1650 		uint j8 = 128;
1651 		uint j9 = 0xFFFFFFFF;
1652 		{
1653 		}
1654 		ulong j10 = (cast(ulong) 1 << 35) + 50;
1655 		ulong j11 = (cast(ulong) 1 << 42) + 50;
1656 		ulong j12 = (cast(ulong) 1 << 49) + 50;
1657 		ulong j13 = (cast(ulong) 1 << 56) + 50;
1658 		ulong j14 = j9 + j10 + j11 + j12;
1659 		ulong j15 = 0xFFFFFFFFFFFFFFFF;
1660 		test(j0);
1661 		test(j1);
1662 		test(j2);
1663 		test(j3);
1664 		test(j4);
1665 		test(j5);
1666 		test(j6);
1667 		test(j7);
1668 		test(j8);
1669 		test(j9);
1670 		test(j10);
1671 		test(j11);
1672 		test(j12);
1673 		test(j13);
1674 		test(j14);
1675 		test(j15);
1676 	}
1677 	//signed
1678 	{
1679 		byte i0 = 0;
1680 		byte i1 = (1 << 6) + 50;
1681 		byte i2 = (1 << 7) - 1;
1682 		byte i3 = -i2;
1683 		byte i4 = -i1;
1684 		test(i0);
1685 		test(i1);
1686 		test(i2);
1687 		test(i3);
1688 		test(i4);
1689 		short i5 = (1 << 7) + 50;
1690 		short i6 = (1 << 14) + 50;
1691 		short i7 = -i5;
1692 		short i8 = -i6;
1693 		test(i5);
1694 		test(i6);
1695 		test(i7);
1696 		test(i8);
1697 		int i9 = (1 << 16) + 50;
1698 		int i10 = (1 << 25) + 50;
1699 		int i11 = (1 << 30) + 50;
1700 		int i12 = 64;
1701 		int i13 = -i10;
1702 		int i14 = -i11;
1703 		int i15 = i9 + i10 + i11;
1704 		int i16 = -i15;
1705 		test(i9);
1706 		test(i10);
1707 		test(i11);
1708 		test(i12);
1709 		test(i13);
1710 		test(i14);
1711 		test(i15);
1712 		test(i16);
1713 		long i17 = (cast(long) 1 << 32) + 50;
1714 		long i18 = (cast(long) 1 << 48) + 50;
1715 		long i19 = (cast(long) 1 << 63) + 50;
1716 		long i20 = i17 + i18 + i19;
1717 		long i21 = -i17;
1718 		long i22 = -i20;
1719 		test(i17);
1720 		test(i18);
1721 		test(i19);
1722 		test(i20);
1723 		test(i21);
1724 		test(i22);
1725 		int i23 = -11;
1726 		test(i23);
1727 	}
1728 	//test serialize
1729 	//basic: byte ubyte short ushort int uint long ulong
1730 	{
1731 		byte b1 = 123;
1732 		byte b2 = -11;
1733 		ubyte b3 = 233;
1734 		short s1 = -11;
1735 		short s2 = (1 << 8) + 50;
1736 		short s3 = (1 << 15) - 50;
1737 		ushort s4 = (1 << 16) - 50;
1738 		int i1 = -11;
1739 		int i2 = (1 << 16) + 50;
1740 		int i3 = (1 << 31) - 50;
1741 		uint i4 = (1 << 31) + 50;
1742 		long l1 = -11;
1743 		long l2 = (cast(long) 1 << 32) + 50;
1744 		long l3 = (cast(long) 1 << 63) - 50;
1745 		ulong l4 = (cast(long) 1 << 63) + 50;
1746 		test1(b1);
1747 		test1(b2);
1748 		test1(b3);
1749 		test1(s1);
1750 		test1(s2);
1751 		test1(s3);
1752 		test1(s4);
1753 		test1(i1);
1754 		test1(i2);
1755 		test1(i3);
1756 		test1(i4);
1757 		test1(l1);
1758 		test1(l2);
1759 		test1(l3);
1760 		test1(l4);
1761 	}
1762 	//test string
1763 	{
1764 		string s1 = "";
1765 		string s2 = "1";
1766 		string s3 = "123";
1767 		test1(s1);
1768 		test1(s2);
1769 		test1(s3);
1770 	}
1771 	//test static arrary
1772 	{
1773 		string[5] sa;
1774 		sa[0] = "test0";
1775 		sa[1] = "test1";
1776 		sa[2] = "test2";
1777 		sa[3] = "test3";
1778 		sa[4] = "test4";
1779 		test1(sa);
1780 	}
1781 	//test dynamic arrary
1782 	{
1783 		string[] sa;
1784 		sa ~= "test1";
1785 		sa ~= "test2";
1786 		sa ~= "test3";
1787 		sa ~= "test4";
1788 		test1(sa);
1789 		string[] sa2;
1790 		test1(sa2);
1791 	}
1792 	//test enum \ struct \ class \ associative array
1793 	test_enum_ser();
1794 	test_struct_class_array();
1795 	test_ref_class();
1796 	test_json_ser();
1797 	////unsigned
1798 		uint ut1 = 1 << 7;
1799 		uint ut2 = 1 << 14;
1800 		uint ut3 = 1 << 21;
1801 		uint ut4 = 1 << 28;
1802 //signed
1803 		int it1 = 1 << 6;
1804 		int it2 = 1 << 13;
1805 		int it3 = 1 << 20;
1806 		int it4 = 1 << 27;
1807 		test1(ut1);
1808 		test1(ut2);
1809 		test1(ut3);
1810 		test1(ut4);
1811 		test1(it1);
1812 		test1(it2);
1813 		test1(it3);
1814 		test1(it4);
1815 }
1816 */