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