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 long parse = 0; 588 mixin(unserializeMembers!T()); 589 590 return t; 591 } 592 593 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == struct)) 594 { 595 long total = 1; 596 597 mixin(getsizeMembers!T()); 598 599 total += getbytenum(total); 600 return cast(uint) total; 601 } 602 603 // TClass 604 // 1 type 11 605 // [uint] len variant 606 // data 607 608 // TClass ref 609 // 1 type 12 610 // id variant 611 612 byte[] serialize(T, bool isRecursive=true)(T t, RefClass stack, uint level) if (is(T == class)) 613 { 614 byte[1] header; 615 size_t* id = null; 616 617 if (t !is null) 618 { 619 id = t.toHash() in stack.map; 620 } 621 622 if (id == null) 623 { 624 header[0] = 11; 625 byte[] data; 626 byte[] dh = cast(byte[]) header; 627 if (t !is null) 628 { 629 stack.map[t.toHash()] = stack.map.length; 630 static if(isRecursive) { 631 static foreach(S; BaseClassesTuple!(T)) { 632 mixin(serializeMembers!S()); 633 } 634 } 635 mixin(serializeMembers!T()); 636 } 637 uint len = cast(uint) data.length; 638 dh ~= toVariant(len); 639 640 return dh ~ data; 641 } 642 else 643 { 644 header[0] = 12; 645 byte[] dh = cast(byte[]) header; 646 dh ~= toVariant(*id); 647 return dh; 648 } 649 650 } 651 652 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 653 if (is(T == class) && !isAbstractClass!T) 654 { 655 if(data.length < 2) 656 return T.init; 657 658 assert(data[0] == 11 || data[0] == 12); 659 660 if (data[0] == 11) 661 { 662 long index1; 663 uint len = toT!uint(data[1 .. $], index1); 664 if (len == 0) 665 return null; 666 T t = new T; 667 parse_index = index1 + 1 + len; 668 long index = index1 + 1; 669 stack.arr ~= cast(void*) t; 670 671 long parse = 0; 672 673 static foreach(S; BaseClassesTuple!(T)) { 674 mixin(unserializeMembers!S()); 675 } 676 mixin(unserializeMembers!T()); 677 678 return t; 679 } 680 else 681 { 682 long index1; 683 size_t id = toT!size_t(data[1 .. $], index1); 684 parse_index += index1 + 1; 685 return cast(T) stack.arr[id]; 686 } 687 688 } 689 690 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == class)) 691 { 692 long total = 1; 693 694 size_t* id = null; 695 696 if (t !is null) 697 { 698 id = t.toHash() in stack.map; 699 } 700 701 if (id == null) 702 { 703 if (t !is null) 704 { 705 stack.map[t.toHash()] = stack.map.length; 706 mixin(getsizeMembers!T()); 707 } 708 709 total += getbytenum(total - 1); 710 return total; 711 } 712 else 713 { 714 return getbytenum(*id) + 1; 715 } 716 717 } 718 719 // AssociativeArray 720 // 1 type 13 721 // [uint] len variant 722 // (k,v) 723 724 byte[] serialize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 725 { 726 byte[1] header; 727 header[0] = 13; 728 byte[] dh; 729 dh ~= cast(byte[]) header; 730 byte[] data; 731 foreach (k, v; t) 732 { 733 data ~= serialize(k, stack, level + 1); 734 data ~= serialize(v, stack, level + 1); 735 } 736 uint len = cast(uint) data.length; 737 dh ~= toVariant(len); 738 return dh ~ data; 739 } 740 741 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 742 if (isAssociativeArray!T) 743 { 744 assert(data[0] == 13); 745 746 T t; 747 long index1; 748 uint len = toT!uint(data[1 .. $], index1); 749 750 parse_index = index1 + 1 + len; 751 long index = index1 + 1; 752 while (index < parse_index) 753 { 754 long out_len; 755 auto k = unserialize!(KeyType!T)(data[index .. $], out_len, stack); 756 index += out_len; 757 out_len = 0; 758 auto v = unserialize!(ValueType!T)(data[index .. $], out_len, stack); 759 index += out_len; 760 t[k] = v; 761 } 762 return t; 763 } 764 765 size_t getsize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 766 { 767 long total = 1; 768 foreach (k, v; t) 769 { 770 total += serialize(k).length; 771 total += serialize(v).length; 772 } 773 total += getbytenum(total - 1); 774 return total; 775 } 776 777 // named enum 778 // 1 type 14 779 // 2 [uint] len 780 // 3 other 781 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == enum)) 782 { 783 byte[1] header; 784 header[0] = 14; 785 byte[] dh; 786 dh ~= cast(byte[]) header; 787 OriginalType!T v = cast(OriginalType!T)t; 788 byte[] data = serialize(v); 789 uint len = cast(uint)data.length; 790 dh ~= toVariant(len); 791 return dh ~ data; 792 } 793 794 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 795 if (is(T == enum)) 796 { 797 assert(data[0] == 14); 798 799 T t; 800 long index1; 801 uint len = toT!uint(data[1 .. $], index1); 802 803 parse_index = index1 + 1 + len; 804 long index = index1 + 1; 805 while (index < parse_index) 806 { 807 long out_len = 0; 808 t = cast(T)unserialize!(OriginalType!T)(data[index .. $], out_len, stack); 809 index += out_len; 810 } 811 return t; 812 } 813 814 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == enum)) 815 { 816 long total = 1; 817 818 total += serialize(cast(OriginalType!T)t).length; 819 820 total += getbytenum(total - 1); 821 return total; 822 } 823 824 825 826 public: 827 828 T unserialize(T)(const(ubyte)[] data ) { 829 return unserialize!(T)(cast(const byte[])data); 830 } 831 832 T unserialize(T)(const byte[] data ) 833 { 834 long parse_index; 835 return unserialize!T(data, parse_index); 836 } 837 838 T unserialize(T)(const(ubyte)[] data, out long parse_index ) { 839 return unserialize!(T)(cast(const byte[])data, parse_index); 840 } 841 842 T unserialize(T)(const byte[] data, out long parse_index ) 843 { 844 RefClass stack = new RefClass(); 845 return unserialize!T(data, parse_index, stack); 846 } 847 848 byte[] serialize(T)(T t ) if (!is(T == class)) 849 { 850 RefClass stack = new RefClass(); 851 return serialize!T(t, stack, 0); 852 } 853 854 byte[] serialize(T, bool isRecursive=true)(T t ) if (is(T == class)) 855 { 856 RefClass stack = new RefClass(); 857 return serialize!(T, isRecursive)(t, stack, 0); 858 } 859 860 size_t getsize(T)(T t ) 861 { 862 RefClass stack = new RefClass(); 863 return getsize!T(t, stack, 0); 864 } 865 866 //////////////////////////////////////////////////////////////////json/////////////////////////// 867 private: 868 enum bool isFloatType(T) = isType!(T, float) || isType!(T, double); 869 870 JSONValue toJson(T)(T t, RefClass stack, uint level) 871 if (isSignedType!T || isUnsignedType!T || is(T == string) || is(T == bool) || isFloatType!T) 872 { 873 return JSONValue(t); 874 } 875 876 // uinteger 877 T toObject(T)(JSONValue v, RefClass stack) if (isUnsignedType!T) 878 { 879 if(v.type() == JSONType.uinteger) 880 return cast(T) v.uinteger; 881 else 882 return T.init; 883 } 884 885 // integer 886 T toObject(T)(JSONValue v, RefClass stack) if (isSignedType!T) 887 { 888 if(v.type() == JSONType.integer) 889 return cast(T) v.integer; 890 else 891 return T.init; 892 } 893 894 // string 895 T toObject(T)(JSONValue v, RefClass stack) if (is(T == string)) 896 { 897 if(v.type() == JSONType..string) 898 return v.str; 899 else 900 return T.init; 901 } 902 903 // bool 904 T toObject(T)(JSONValue v, RefClass stack) if (is(T == bool)) 905 { 906 if(v.type() == JSONType.true_ || v.type() == JSONType.false_) 907 return v.type() == JSONType.true_; 908 else 909 return T.init; 910 } 911 912 // floating 913 T toObject(T)(JSONValue v, RefClass stack) if (isFloatType!T) 914 { 915 if(v.type() == JSONType.float_) 916 return cast(T) v.floating; 917 else 918 return T.init; 919 } 920 921 922 // array 923 JSONValue toJson(T)(T t, RefClass stack, uint level) 924 if (isStaticArray!T || (isDynamicArray!T && !is(T == string) && !is(T == enum))) 925 { 926 JSONValue[] j; 927 foreach (e; t) 928 { 929 j ~= toJson(e, stack, level); 930 } 931 932 return JSONValue(j); 933 } 934 935 T toObject(T)(JSONValue v, RefClass stack) if (isStaticArray!T) 936 { 937 T t; 938 if(v.type() == JSONType.array) 939 { 940 for (size_t i = 0; i < t.length; i++) 941 { 942 t[i] = toObject!(typeof(t[i]))(v.array[i], stack); 943 } 944 } 945 return t; 946 947 } 948 949 T toObject(T)(JSONValue v, RefClass stack) if (isDynamicArray!T && !is(T == string)&& !is(T == enum)) 950 { 951 T t; 952 if(v.type() == JSONType.array) 953 { 954 t.length = v.array.length; 955 for (size_t i = 0; i < t.length; i++) 956 { 957 t[i] = toObject!(typeof(t[i]))(v.array[i], stack); 958 } 959 } 960 return t; 961 } 962 963 // struct & class 964 965 string toJsonMembers(T , bool ignore)() 966 { 967 string str; 968 foreach (m; FieldNameTuple!T) 969 { 970 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 971 { 972 if(!ignore || !hasUDA!(__traits(getMember , T , m) ,IGNORE )) 973 { 974 str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);"; 975 } 976 } 977 } 978 return str; 979 } 980 981 string toJsonMembersAll(T)() 982 { 983 string str; 984 foreach (m; FieldNameTuple!T) 985 { 986 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 987 { 988 str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);"; 989 } 990 } 991 return str; 992 } 993 994 995 996 string toObjectMembers(T)() 997 { 998 string str; 999 foreach (m; FieldNameTuple!T) 1000 { 1001 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 1002 { 1003 str ~= " if ( \"" ~ m ~ "\" in j )"; 1004 str ~= "t." ~ m ~ " = toObject!(typeof(t." ~ m ~ "))(j[\"" ~ m ~ "\"] , stack);"; 1005 } 1006 1007 } 1008 return str; 1009 } 1010 1011 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == struct)) 1012 { 1013 JSONValue j; 1014 1015 static if (is(T == JSONValue)) 1016 { 1017 return t; 1018 } 1019 else{ 1020 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 1021 1022 if(ignore) 1023 mixin(toJsonMembers!(T,true)); 1024 else 1025 mixin(toJsonMembers!(T,false)); 1026 return j; 1027 } 1028 } 1029 1030 T toObject(T)(JSONValue j, RefClass stack) if (is(T == struct)) 1031 { 1032 static if (is(T == JSONValue)) 1033 { 1034 return j; 1035 } 1036 else 1037 { 1038 T t; 1039 if(j.type() == JSONType.object) 1040 { 1041 mixin(toObjectMembers!T); 1042 } 1043 return t; 1044 } 1045 } 1046 1047 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == class)) 1048 { 1049 if (t is null || level >= stack.level) 1050 { 1051 return JSONValue(null); 1052 } 1053 1054 auto id = t.toHash() in stack.map; 1055 if (id == null) 1056 { 1057 stack.map[t.toHash()] = stack.map.length; 1058 JSONValue j; 1059 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 1060 1061 if(ignore) 1062 mixin(toJsonMembers!(T,true)); 1063 else 1064 mixin(toJsonMembers!(T,false)); 1065 return j; 1066 } 1067 else 1068 { 1069 JSONValue j; 1070 j[MAGIC_KEY] = *id; 1071 return j; 1072 } 1073 } 1074 1075 T toObject(T)(JSONValue j, RefClass stack) if (is(T == class)) 1076 { 1077 if ( j.type() != JSONType.object) 1078 return T.init; 1079 assert(j.type() == JSONType.object); 1080 1081 if (MAGIC_KEY in j) 1082 { 1083 return cast(T) stack.arr[j[MAGIC_KEY].uinteger]; 1084 } 1085 else 1086 { 1087 T t = new T; 1088 stack.arr ~= cast(void*) t; 1089 mixin(toObjectMembers!T); 1090 return t; 1091 } 1092 } 1093 1094 //AssociativeArray 1095 JSONValue toJson(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 1096 { 1097 JSONValue j; 1098 import std.conv; 1099 1100 foreach (k, v; t) 1101 j[to!string(k)] = toJson(v, stack, level); 1102 return j; 1103 } 1104 1105 T toObject(T)(JSONValue j, RefClass stack) if (isAssociativeArray!T) 1106 { 1107 import std.conv; 1108 if ( j.type() != JSONType.object) 1109 return T.init; 1110 T t; 1111 foreach (k, v; j.object) 1112 { 1113 t[to!(KeyType!T)(k)] = toObject!(ValueType!T)(v, stack); 1114 } 1115 return t; 1116 } 1117 1118 //enum 1119 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == enum)) 1120 { 1121 1122 auto j = JSONValue(cast(OriginalType!T)t); 1123 writeln(j.type()); 1124 return j; 1125 } 1126 1127 T toObject(T)(JSONValue j, RefClass stack) if (is(T == enum)) 1128 { 1129 import std.conv; 1130 writeln(j , " " , j.type() , typeid(T)); 1131 OriginalType!T val; 1132 static if (is(OriginalType!T == string )) 1133 { 1134 if(j.type() == JSONType..string) 1135 val = cast(OriginalType!T)j.str; 1136 else 1137 return T.init; 1138 } 1139 else static if (is(OriginalType!T == int)) 1140 { 1141 if(j.type() == JSONType.integer) 1142 val = cast(OriginalType!T)j.integer; 1143 else if(j.type() == JSONType.uinteger) 1144 val = cast(OriginalType!T)j.uinteger; 1145 else 1146 return T.init; 1147 } 1148 1149 return cast(T)val; 1150 } 1151 1152 public: 1153 1154 JSONValue toJson(T)(T t , uint level = uint.max , bool ignore = true) 1155 { 1156 RefClass stack = new RefClass(); 1157 stack.level = level; 1158 stack.ignore = ignore; 1159 return toJson!T(t, stack, 0); 1160 } 1161 1162 JSONValue toJson(T)(T t , UnIgnoreArray array , uint level = uint.max) 1163 { 1164 RefClass stack = new RefClass(); 1165 stack.level = level; 1166 stack.unIgnore = array; 1167 return toJson!T(t, stack, 0); 1168 } 1169 1170 T toObject(T)(JSONValue j) 1171 { 1172 RefClass stack = new RefClass(); 1173 return toObject!T(j, stack); 1174 } 1175 1176 deprecated("Using toJson instead.") 1177 alias toJSON = toJson; 1178 1179 deprecated("Using toObject instead.") 1180 alias toOBJ = toObject; 1181 1182 ////------------------------- toTextString ------ 1183 /** 1184 Takes a tree of JSON values and returns the serialized string. 1185 1186 Any Object types will be serialized in a key-sorted order. 1187 1188 If `pretty` is false no whitespaces are generated. 1189 If `pretty` is true serialized string is formatted to be human-readable. 1190 Set the $(LREF JSONOptions.specialFloatLiterals) flag is set in `options` to encode NaN/Infinity as strings. 1191 */ 1192 string toTextString(const ref JSONValue root, in bool pretty = false, in JSONOptions options = JSONOptions.none) @safe 1193 { 1194 import std.array; 1195 import std.conv; 1196 import std.string; 1197 1198 auto json = appender!string(); 1199 1200 void toStringImpl(Char)(string str) @safe 1201 { 1202 json.put('"'); 1203 1204 foreach (Char c; str) 1205 { 1206 switch (c) 1207 { 1208 case '"': json.put("\\\""); break; 1209 case '\\': json.put("\\\\"); break; 1210 1211 case '/': 1212 if (!(options & JSONOptions.doNotEscapeSlashes)) 1213 json.put('\\'); 1214 json.put('/'); 1215 break; 1216 1217 case '\b': json.put("\\b"); break; 1218 case '\f': json.put("\\f"); break; 1219 case '\n': json.put("\\n"); break; 1220 case '\r': json.put("\\r"); break; 1221 case '\t': json.put("\\t"); break; 1222 default: 1223 { 1224 import std.ascii : isControl; 1225 import std.utf : encode; 1226 1227 // Make sure we do UTF decoding iff we want to 1228 // escape Unicode characters. 1229 assert(((options & JSONOptions.escapeNonAsciiChars) != 0) 1230 == is(Char == dchar), "JSONOptions.escapeNonAsciiChars needs dchar strings"); 1231 1232 with (JSONOptions) if (isControl(c) || 1233 ((options & escapeNonAsciiChars) >= escapeNonAsciiChars && c >= 0x80)) 1234 { 1235 // Ensure non-BMP characters are encoded as a pair 1236 // of UTF-16 surrogate characters, as per RFC 4627. 1237 wchar[2] wchars; // 1 or 2 UTF-16 code units 1238 size_t wNum = encode(wchars, c); // number of UTF-16 code units 1239 foreach (wc; wchars[0 .. wNum]) 1240 { 1241 json.put("\\u"); 1242 foreach_reverse (i; 0 .. 4) 1243 { 1244 char ch = (wc >>> (4 * i)) & 0x0f; 1245 ch += ch < 10 ? '0' : 'A' - 10; 1246 json.put(ch); 1247 } 1248 } 1249 } 1250 else 1251 { 1252 json.put(c); 1253 } 1254 } 1255 } 1256 } 1257 1258 json.put('"'); 1259 } 1260 1261 void toString(string str) @safe 1262 { 1263 // Avoid UTF decoding when possible, as it is unnecessary when 1264 // processing JSON. 1265 if (options & JSONOptions.escapeNonAsciiChars) 1266 toStringImpl!dchar(str); 1267 else 1268 toStringImpl!char(str); 1269 } 1270 1271 void toValue(ref in JSONValue value, ulong indentLevel) @safe 1272 { 1273 void putTabs(ulong additionalIndent = 0) 1274 { 1275 if (pretty) 1276 foreach (i; 0 .. indentLevel + additionalIndent) 1277 json.put(" "); 1278 } 1279 void putEOL() 1280 { 1281 if (pretty) 1282 json.put('\n'); 1283 } 1284 void putCharAndEOL(char ch) 1285 { 1286 json.put(ch); 1287 putEOL(); 1288 } 1289 1290 final switch (value.type) 1291 { 1292 case JSONType.object: 1293 auto obj = value.objectNoRef; 1294 if (!obj.length) 1295 { 1296 json.put("{}"); 1297 } 1298 else 1299 { 1300 putCharAndEOL('{'); 1301 bool first = true; 1302 1303 void emit(R)(R names) 1304 { 1305 foreach (name; names) 1306 { 1307 auto member = obj[name]; 1308 if (!first) 1309 putCharAndEOL(','); 1310 first = false; 1311 putTabs(1); 1312 toString(name); 1313 json.put(':'); 1314 if (pretty) 1315 json.put(' '); 1316 toValue(member, indentLevel + 1); 1317 } 1318 } 1319 1320 import std.algorithm.sorting : sort; 1321 // @@@BUG@@@ 14439 1322 // auto names = obj.keys; // aa.keys can't be called in @safe code 1323 auto names = new string[obj.length]; 1324 size_t i = 0; 1325 foreach (k, v; obj) 1326 { 1327 names[i] = k; 1328 i++; 1329 } 1330 sort(names); 1331 emit(names); 1332 1333 putEOL(); 1334 putTabs(); 1335 json.put('}'); 1336 } 1337 break; 1338 1339 case JSONType.array: 1340 auto arr = value.arrayNoRef; 1341 if (arr.empty) 1342 { 1343 json.put("[]"); 1344 } 1345 else 1346 { 1347 putCharAndEOL('['); 1348 foreach (i, el; arr) 1349 { 1350 if (i) 1351 putCharAndEOL(','); 1352 putTabs(1); 1353 toValue(el, indentLevel + 1); 1354 } 1355 putEOL(); 1356 putTabs(); 1357 json.put(']'); 1358 } 1359 break; 1360 1361 case JSONType..string: 1362 toString(value.str); 1363 break; 1364 1365 case JSONType.integer: 1366 json.put(to!string(value.integer)); 1367 break; 1368 1369 case JSONType.uinteger: 1370 json.put(to!string(value.uinteger)); 1371 break; 1372 1373 case JSONType.float_: 1374 import std.math : isNaN, isInfinity; 1375 1376 auto val = value.floating; 1377 1378 if (val.isNaN) 1379 { 1380 if (options & JSONOptions.specialFloatLiterals) 1381 { 1382 toString(JSONFloatLiteral.nan); 1383 } 1384 else 1385 { 1386 throw new JSONException( 1387 "Cannot encode NaN. Consider passing the specialFloatLiterals flag."); 1388 } 1389 } 1390 else if (val.isInfinity) 1391 { 1392 if (options & JSONOptions.specialFloatLiterals) 1393 { 1394 toString((val > 0) ? JSONFloatLiteral.inf : JSONFloatLiteral.negativeInf); 1395 } 1396 else 1397 { 1398 throw new JSONException( 1399 "Cannot encode Infinity. Consider passing the specialFloatLiterals flag."); 1400 } 1401 } 1402 else 1403 { 1404 import std.format : format; 1405 // The correct formula for the number of decimal digits needed for lossless round 1406 // trips is actually: 1407 // ceil(log(pow(2.0, double.mant_dig - 1)) / log(10.0) + 1) == (double.dig + 2) 1408 // Anything less will round off (1 + double.epsilon) 1409 json.put("%s".format(val)); 1410 } 1411 break; 1412 1413 case JSONType.true_: 1414 json.put("true"); 1415 break; 1416 1417 case JSONType.false_: 1418 json.put("false"); 1419 break; 1420 1421 case JSONType.null_: 1422 json.put("null"); 1423 break; 1424 } 1425 } 1426 1427 toValue(root, 0); 1428 return json.data; 1429 } 1430 1431 1432 /** 1433 */ 1434 mixin template SerializationMember(T) { 1435 import std.traits; 1436 debug(HUNT_DEBUG_MORE) import hunt.logging.ConsoleLogger; 1437 1438 alias baseClasses = BaseClassesTuple!T; 1439 1440 static if(baseClasses.length == 1 && is(baseClasses[0] == Object)) { 1441 ubyte[] serialize() { 1442 ubyte[] bytes = cast(ubyte[]).serialize!(T, false)(this); 1443 debug(HUNT_DEBUG_MORE) 1444 tracef("this level (%s), length: %d, data: %(%02X %)", T.stringof, bytes.length, bytes); 1445 return bytes; 1446 } 1447 1448 // void deserialize(ubyte[] data) { 1449 1450 // } 1451 } else { 1452 // pragma(msg, T.stringof); 1453 override ubyte[] serialize() { 1454 auto bytes = cast(ubyte[])hunt.util.Serialize.serialize!(T, false)(this); 1455 debug(HUNT_DEBUG_MORE) 1456 tracef("current level (%s), length: %d, data: %(%02X %)", T.stringof, bytes.length, bytes); 1457 1458 ubyte[] data = super.serialize(); 1459 data[1] = cast(ubyte)(data[1] + bytes.length - 2); 1460 data ~= bytes[2..$]; 1461 debug(HUNT_DEBUG_MORE) 1462 tracef("all levels (%s), length: %d, data: %(%02X %)", T.stringof, data.length, data); 1463 1464 // auto bytes = cast(ubyte[])hunt.util.Serialize.serialize(this); 1465 // tracef("length: %d, data: %(%02X %)", bytes.length, bytes); 1466 return data; 1467 } 1468 1469 // override void deserialize(ubyte[] data) { 1470 1471 // } 1472 } 1473 1474 1475 } 1476 1477 1478 // only for , nested , new T 1479 /* 1480 version (unittest) 1481 { 1482 //test struct 1483 void test1(T)(T t) 1484 { 1485 assert(unserialize!T(serialize(t)) == t); 1486 assert(serialize(t).length == getsize(t)); 1487 assert(toObject!T(toJson(t)) == t); 1488 } 1489 struct T1 1490 { 1491 bool b; 1492 byte ib; 1493 ubyte ub; 1494 short ish; 1495 ushort ush; 1496 int ii; 1497 uint ui; 1498 long il; 1499 ulong ul; 1500 string s; 1501 uint[10] sa; 1502 long[] sb; 1503 } 1504 struct T2 1505 { 1506 string n; 1507 T1[] t; 1508 } 1509 struct T3 1510 { 1511 T1 t1; 1512 T2 t2; 1513 string[] name; 1514 } 1515 //test class 1516 class C 1517 { 1518 int age; 1519 string name; 1520 T3 t3; 1521 override bool opEquals(Object c) 1522 { 1523 auto c1 = cast(C) c; 1524 return age == c1.age && name == c1.name && t3 == c1.t3; 1525 } 1526 C clone() 1527 { 1528 auto c = new C(); 1529 c.age = age; 1530 c.name = name; 1531 c.t3 = t3; 1532 return c; 1533 } 1534 } 1535 class C2 1536 { 1537 C[] c; 1538 C c1; 1539 T1 t1; 1540 override bool opEquals(Object c) 1541 { 1542 auto c2 = cast(C2) c; 1543 return this.c == c2.c && c1 == c2.c1 && t1 == c2.t1; 1544 } 1545 } 1546 //ref test 1547 class School 1548 { 1549 string name; 1550 User[] users; 1551 override bool opEquals(Object c) 1552 { 1553 auto school = cast(School) c; 1554 return school.name == this.name; 1555 } 1556 } 1557 class User 1558 { 1559 int age; 1560 string name; 1561 School school; 1562 override bool opEquals(Object c) 1563 { 1564 auto user = cast(User) c; 1565 return user.age == this.age && user.name == this.name && user.school == this.school; 1566 } 1567 } 1568 struct J{ 1569 string data; 1570 JSONValue val; 1571 1572 } 1573 1574 enum MONTH 1575 { 1576 M1, 1577 M2 1578 } 1579 1580 enum WEEK : int 1581 { 1582 K1 = 1, 1583 K2 = 2 1584 } 1585 1586 enum DAY : string 1587 { 1588 D1 = "one", 1589 D2 = "two" 1590 } 1591 1592 class Date1 1593 { 1594 MONTH month; 1595 WEEK week; 1596 DAY day; 1597 override bool opEquals(Object c) 1598 { 1599 auto date = cast(Date1) c; 1600 return date.month == this.month && date.week == this.week && date.day == this.day; 1601 } 1602 1603 } 1604 1605 void test_enum_ser() 1606 { 1607 Date1 date = new Date1(); 1608 date.month = MONTH.M2; 1609 date.week = WEEK.K2; 1610 date.day = DAY.D2; 1611 test1(date); 1612 1613 } 1614 1615 void test_json_ser() 1616 { 1617 J j; 1618 j.data = "test"; 1619 j.val = "FUC"; 1620 toObject!J(toJson(j)); 1621 } 1622 void test_ref_class() 1623 { 1624 School school = new School(); 1625 User user1 = new User(); 1626 user1.age = 30; 1627 user1.name = "zhangyuchun"; 1628 user1.school = school; 1629 User user2 = new User(); 1630 user2.age = 31; 1631 user2.name = "wulishan"; 1632 user2.school = school; 1633 school.name = "putao"; 1634 school.users ~= user1; 1635 school.users ~= user2; 1636 test1(user1); 1637 test1(user2); 1638 } 1639 void test_struct_class_array() 1640 { 1641 T1 t; 1642 t.b = true; 1643 t.ib = -11; 1644 t.ub = 128 + 50; 1645 t.ish = -50; 1646 t.ush = (1 << 15) + 50; 1647 t.ii = -50; 1648 t.ui = (1 << 31) + 50; 1649 t.il = (cast(long) 1 << 63) - 50; 1650 t.ul = (cast(long) 1 << 63) + 50; 1651 t.s = "test"; 1652 t.sa[0] = 10; 1653 t.sa[1] = 100; 1654 t.sb ~= 10; 1655 t.sb ~= 100; 1656 test1(t); 1657 T2 t2; 1658 t2.t ~= t; 1659 t2.t ~= t; 1660 t2.n = "testt2"; 1661 test1(t2); 1662 T3 t3; 1663 t3.t1 = t; 1664 t3.t2 = t2; 1665 t3.name ~= "123"; 1666 t3.name ~= "456"; 1667 test1(t3); 1668 C c1 = new C(); 1669 c1.age = 100; 1670 c1.name = "test"; 1671 c1.t3 = t3; 1672 test1(c1); 1673 C2 c2 = new C2(); 1674 c2.c ~= c1; 1675 c2.c ~= c1.clone(); 1676 c2.c1 = c1.clone(); 1677 c2.t1 = t; 1678 test1(c2); 1679 C2 c3 = null; 1680 test1(c3); 1681 string[string] map1 = ["1" : "1", "2" : "2"]; 1682 string[int] map2 = [1 : "1", 2 : "2"]; 1683 T1[string] map3; 1684 T1 a1; 1685 a1.ib = 1; 1686 T1 a2; 1687 a2.ib = 2; 1688 map3["1"] = a1; 1689 map3["2"] = a2; 1690 test1(map1); 1691 test1(map2); 1692 test1(map3); 1693 } 1694 1695 } 1696 unittest 1697 { 1698 import std.stdio; 1699 long index; 1700 void test(T)(T v) 1701 { 1702 long index; 1703 byte[] bs = toVariant(v); 1704 long length = bs.length; 1705 bs ~= ['x', 'y']; 1706 assert(toT!T(bs, index) == v && index == length); 1707 assert(toObject!T(toJson(v)) == v); 1708 } 1709 //test variant 1710 //unsigned 1711 { 1712 ubyte j0 = 0; 1713 ubyte j1 = 50; 1714 ubyte j2 = (1 << 7) + 50; 1715 ubyte j3 = 0xFF; 1716 ushort j4 = (1 << 14) + 50; 1717 ushort j5 = 0xFFFF; 1718 uint j6 = (1 << 21) + 50; 1719 uint j7 = (1 << 28) + 50; 1720 uint j8 = 128; 1721 uint j9 = 0xFFFFFFFF; 1722 { 1723 } 1724 ulong j10 = (cast(ulong) 1 << 35) + 50; 1725 ulong j11 = (cast(ulong) 1 << 42) + 50; 1726 ulong j12 = (cast(ulong) 1 << 49) + 50; 1727 ulong j13 = (cast(ulong) 1 << 56) + 50; 1728 ulong j14 = j9 + j10 + j11 + j12; 1729 ulong j15 = 0xFFFFFFFFFFFFFFFF; 1730 test(j0); 1731 test(j1); 1732 test(j2); 1733 test(j3); 1734 test(j4); 1735 test(j5); 1736 test(j6); 1737 test(j7); 1738 test(j8); 1739 test(j9); 1740 test(j10); 1741 test(j11); 1742 test(j12); 1743 test(j13); 1744 test(j14); 1745 test(j15); 1746 } 1747 //signed 1748 { 1749 byte i0 = 0; 1750 byte i1 = (1 << 6) + 50; 1751 byte i2 = (1 << 7) - 1; 1752 byte i3 = -i2; 1753 byte i4 = -i1; 1754 test(i0); 1755 test(i1); 1756 test(i2); 1757 test(i3); 1758 test(i4); 1759 short i5 = (1 << 7) + 50; 1760 short i6 = (1 << 14) + 50; 1761 short i7 = -i5; 1762 short i8 = -i6; 1763 test(i5); 1764 test(i6); 1765 test(i7); 1766 test(i8); 1767 int i9 = (1 << 16) + 50; 1768 int i10 = (1 << 25) + 50; 1769 int i11 = (1 << 30) + 50; 1770 int i12 = 64; 1771 int i13 = -i10; 1772 int i14 = -i11; 1773 int i15 = i9 + i10 + i11; 1774 int i16 = -i15; 1775 test(i9); 1776 test(i10); 1777 test(i11); 1778 test(i12); 1779 test(i13); 1780 test(i14); 1781 test(i15); 1782 test(i16); 1783 long i17 = (cast(long) 1 << 32) + 50; 1784 long i18 = (cast(long) 1 << 48) + 50; 1785 long i19 = (cast(long) 1 << 63) + 50; 1786 long i20 = i17 + i18 + i19; 1787 long i21 = -i17; 1788 long i22 = -i20; 1789 test(i17); 1790 test(i18); 1791 test(i19); 1792 test(i20); 1793 test(i21); 1794 test(i22); 1795 int i23 = -11; 1796 test(i23); 1797 } 1798 //test serialize 1799 //basic: byte ubyte short ushort int uint long ulong 1800 { 1801 byte b1 = 123; 1802 byte b2 = -11; 1803 ubyte b3 = 233; 1804 short s1 = -11; 1805 short s2 = (1 << 8) + 50; 1806 short s3 = (1 << 15) - 50; 1807 ushort s4 = (1 << 16) - 50; 1808 int i1 = -11; 1809 int i2 = (1 << 16) + 50; 1810 int i3 = (1 << 31) - 50; 1811 uint i4 = (1 << 31) + 50; 1812 long l1 = -11; 1813 long l2 = (cast(long) 1 << 32) + 50; 1814 long l3 = (cast(long) 1 << 63) - 50; 1815 ulong l4 = (cast(long) 1 << 63) + 50; 1816 test1(b1); 1817 test1(b2); 1818 test1(b3); 1819 test1(s1); 1820 test1(s2); 1821 test1(s3); 1822 test1(s4); 1823 test1(i1); 1824 test1(i2); 1825 test1(i3); 1826 test1(i4); 1827 test1(l1); 1828 test1(l2); 1829 test1(l3); 1830 test1(l4); 1831 } 1832 //test string 1833 { 1834 string s1 = ""; 1835 string s2 = "1"; 1836 string s3 = "123"; 1837 test1(s1); 1838 test1(s2); 1839 test1(s3); 1840 } 1841 //test static arrary 1842 { 1843 string[5] sa; 1844 sa[0] = "test0"; 1845 sa[1] = "test1"; 1846 sa[2] = "test2"; 1847 sa[3] = "test3"; 1848 sa[4] = "test4"; 1849 test1(sa); 1850 } 1851 //test dynamic arrary 1852 { 1853 string[] sa; 1854 sa ~= "test1"; 1855 sa ~= "test2"; 1856 sa ~= "test3"; 1857 sa ~= "test4"; 1858 test1(sa); 1859 string[] sa2; 1860 test1(sa2); 1861 } 1862 //test enum \ struct \ class \ associative array 1863 test_enum_ser(); 1864 test_struct_class_array(); 1865 test_ref_class(); 1866 test_json_ser(); 1867 ////unsigned 1868 uint ut1 = 1 << 7; 1869 uint ut2 = 1 << 14; 1870 uint ut3 = 1 << 21; 1871 uint ut4 = 1 << 28; 1872 //signed 1873 int it1 = 1 << 6; 1874 int it2 = 1 << 13; 1875 int it3 = 1 << 20; 1876 int it4 = 1 << 27; 1877 test1(ut1); 1878 test1(ut2); 1879 test1(ut3); 1880 test1(ut4); 1881 test1(it1); 1882 test1(it2); 1883 test1(it3); 1884 test1(it4); 1885 } 1886 */