1 /* 2 * Kiss - A refined core library for D programming language. 3 * 4 * Copyright (C) 2015-2018 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs.cn 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module kiss.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) 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) 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) 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 402 T unserialize(T)(const byte[] data ) if(is(T == union)) 403 { 404 long parser_index; 405 return unserialize!T(data , parser_index); 406 } 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 420 size_t getsize(T)(T t) if(is(T == union)) 421 { 422 return 2 + T.sizeof; 423 } 424 425 */ 426 427 // TSArray 428 // 1 type 8 429 // size[uint] variant 430 // len[uint] variant 431 // data 432 433 byte[] serialize(T)(T t, RefClass stack, uint level) if (isStaticArray!T) 434 { 435 byte[1] header; 436 header[0] = 8; 437 uint uSize = cast(uint) t.length; 438 byte[] dh = cast(byte[]) header; 439 dh ~= toVariant(uSize); 440 441 byte[] data; 442 for (size_t i = 0; i < uSize; i++) 443 { 444 data ~= serialize(t[i], stack, level + 1); 445 } 446 uint len = cast(uint) data.length; 447 dh ~= toVariant(len); 448 return dh ~ data; 449 } 450 451 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 452 if (isStaticArray!T) 453 { 454 assert(data[0] == 8); 455 T value; 456 uint uSize; 457 uint len; 458 long index1; 459 long index2; 460 uSize = toT!uint(data[1 .. $], index1); 461 462 len = toT!uint(data[cast(size_t)(index1 + 1) .. $], index2); 463 parse_index += 1 + index1 + index2; 464 465 long index = parse_index; 466 long parse = 0; 467 for (size_t i = 0; i < uSize; i++) 468 { 469 parse = 0; 470 value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length], 471 parse, stack); 472 index += parse; 473 } 474 475 parse_index += len; 476 477 return value; 478 } 479 480 size_t getsize(T)(T t, RefClass stack, uint level) if (isStaticArray!T) 481 { 482 long total = 1; 483 total += getbytenum(t.length); 484 uint uSize = cast(uint) t.length; 485 for (size_t i = 0; i < uSize; i++) 486 { 487 total += getsize(t[i], stack, level + 1); 488 } 489 total += getbytenum(total); 490 return total; 491 } 492 493 // TDArray 494 // 1 type 9 495 // size[uint] variant 496 // length[uint] variant 497 // data 498 499 byte[] serialize(T)(T t, RefClass stack, uint level) 500 if (isDynamicArray!T && !is(T == string)) 501 { 502 byte[1] header; 503 header[0] = 9; 504 505 uint uSize = cast(uint) t.length; 506 byte[] dh = cast(byte[]) header; 507 dh ~= toVariant(uSize); 508 509 byte[] data; 510 for (size_t i = 0; i < uSize; i++) 511 { 512 data ~= serialize(t[i], stack, level + 1); 513 } 514 uint len = cast(uint) data.length; 515 dh ~= toVariant(len); 516 517 return dh ~ data; 518 } 519 520 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 521 if (isDynamicArray!T && !is(T == string)) 522 { 523 assert(data[0] == 9); 524 525 T value; 526 uint uSize; 527 uint len; 528 long index1; 529 long index2; 530 uSize = toT!uint(data[1 .. $], index1); 531 len = toT!uint(data[cast(size_t)(1 + index1) .. $], index2); 532 533 parse_index += 1 + index1 + index2; 534 value.length = uSize; 535 ulong index = parse_index; 536 long parse = 0; 537 for (size_t i = 0; i < uSize; i++) 538 { 539 value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length], 540 parse, stack); 541 index += parse; 542 } 543 parse_index += len; 544 545 return value; 546 } 547 548 size_t getsize(T)(T t, RefClass stack, uint level) 549 if (isDynamicArray!T && !is(T == string)) 550 { 551 long total = 1; 552 total += getbytenum(t.length); 553 uint uSize = cast(uint) t.length; 554 for (size_t i = 0; i < uSize; i++) 555 { 556 total += getsize(t[i], stack, level + 1); 557 } 558 total += getbytenum(total); 559 return total; 560 } 561 562 // TStruct 563 // 1 type 10 564 // [uint] variant 565 // data 566 567 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == struct)) 568 { 569 byte[1] header; 570 header[0] = 10; 571 byte[] data; 572 573 mixin(serializeMembers!T()); 574 byte[] dh = cast(byte[]) header; 575 uint len = cast(uint) data.length; 576 dh ~= toVariant(len); 577 return dh ~ data; 578 } 579 580 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 581 if (is(T == struct)) 582 { 583 assert(data[0] == 10); 584 585 T t; 586 long index1; 587 uint len = toT!uint(data[1 .. $], index1); 588 589 parse_index = 1 + index1 + len; 590 long index = 1 + index1; 591 mixin(unserializeMembers!T()); 592 593 return t; 594 } 595 596 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == struct)) 597 { 598 long total = 1; 599 600 mixin(getsizeMembers!T()); 601 602 total += getbytenum(total); 603 return cast(uint) total; 604 } 605 606 // TClass 607 // 1 type 11 608 // [uint] len variant 609 // data 610 611 // TClass ref 612 // 1 type 12 613 // id variant 614 615 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == class)) 616 { 617 byte[1] header; 618 size_t* id = null; 619 620 if (t !is null) 621 { 622 id = t.toHash() in stack.map; 623 } 624 625 if (id == null) 626 { 627 header[0] = 11; 628 byte[] data; 629 byte[] dh = cast(byte[]) header; 630 if (t !is null) 631 { 632 stack.map[t.toHash()] = stack.map.length; 633 mixin(serializeMembers!T()); 634 } 635 uint len = cast(uint) data.length; 636 dh ~= toVariant(len); 637 638 return dh ~ data; 639 } 640 else 641 { 642 header[0] = 12; 643 byte[] dh = cast(byte[]) header; 644 dh ~= toVariant(*id); 645 return dh; 646 } 647 648 } 649 650 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 651 if (is(T == class)) 652 { 653 assert(data[0] == 11 || data[0] == 12); 654 655 if (data[0] == 11) 656 { 657 long index1; 658 uint len = toT!uint(data[1 .. $], index1); 659 if (len == 0) 660 return null; 661 T t = new T; 662 parse_index = index1 + 1 + len; 663 long index = index1 + 1; 664 stack.arr ~= cast(void*) t; 665 mixin(unserializeMembers!T()); 666 return t; 667 } 668 else 669 { 670 long index1; 671 size_t id = toT!size_t(data[1 .. $], index1); 672 parse_index += index1 + 1; 673 return cast(T) stack.arr[id]; 674 } 675 676 } 677 678 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == class)) 679 { 680 long total = 1; 681 682 size_t* id = null; 683 684 if (t !is null) 685 { 686 id = t.toHash() in stack.map; 687 } 688 689 if (id == null) 690 { 691 if (t !is null) 692 { 693 stack.map[t.toHash()] = stack.map.length; 694 mixin(getsizeMembers!T()); 695 } 696 697 total += getbytenum(total - 1); 698 return total; 699 } 700 else 701 { 702 return getbytenum(*id) + 1; 703 } 704 705 } 706 707 // AssociativeArray 708 // 1 type 13 709 // [uint] len variant 710 // (k,v) 711 712 byte[] serialize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 713 { 714 byte[1] header; 715 header[0] = 13; 716 byte[] dh; 717 dh ~= cast(byte[]) header; 718 byte[] data; 719 foreach (k, v; t) 720 { 721 data ~= serialize(k, stack, level + 1); 722 data ~= serialize(v, stack, level + 1); 723 } 724 uint len = cast(uint) data.length; 725 dh ~= toVariant(len); 726 return dh ~ data; 727 } 728 729 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 730 if (isAssociativeArray!T) 731 { 732 assert(data[0] == 13); 733 734 T t; 735 long index1; 736 uint len = toT!uint(data[1 .. $], index1); 737 738 parse_index = index1 + 1 + len; 739 long index = index1 + 1; 740 while (index < parse_index) 741 { 742 long out_len; 743 auto k = unserialize!(KeyType!T)(data[index .. $], out_len, stack); 744 index += out_len; 745 out_len = 0; 746 auto v = unserialize!(ValueType!T)(data[index .. $], out_len, stack); 747 index += out_len; 748 t[k] = v; 749 } 750 return t; 751 } 752 753 size_t getsize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 754 { 755 long total = 1; 756 foreach (k, v; t) 757 { 758 total += serialize(k).length; 759 total += serialize(v).length; 760 } 761 total += getbytenum(total - 1); 762 return total; 763 } 764 765 public: 766 767 T unserialize(T)(const byte[] data ) 768 { 769 long parse_index; 770 return unserialize!T(data, parse_index); 771 } 772 773 T unserialize(T)(const byte[] data, out long parse_index ) 774 { 775 RefClass stack = new RefClass(); 776 return unserialize!T(data, parse_index, stack); 777 } 778 779 byte[] serialize(T)(T t ) 780 { 781 RefClass stack = new RefClass(); 782 return serialize!T(t, stack, 0); 783 } 784 785 size_t getsize(T)(T t ) 786 { 787 RefClass stack = new RefClass(); 788 return getsize!T(t, stack, 0); 789 } 790 791 //////////////////////////////////////////////////////////////////json/////////////////////////// 792 private: 793 enum bool isFloatType(T) = isType!(T, float) || isType!(T, double); 794 795 JSONValue toJSON(T)(T t, RefClass stack, uint level) 796 if (isSignedType!T || isUnsignedType!T || is(T == string) || is(T == bool) || isFloatType!T) 797 { 798 return JSONValue(t); 799 } 800 801 // uinteger 802 T toOBJ(T)(JSONValue v, RefClass stack) if (isUnsignedType!T) 803 { 804 if(v.type() == JSON_TYPE.UINTEGER) 805 return cast(T) v.uinteger; 806 else 807 return T.init; 808 } 809 810 // integer 811 T toOBJ(T)(JSONValue v, RefClass stack) if (isSignedType!T) 812 { 813 if(v.type() == JSON_TYPE.INTEGER) 814 return cast(T) v.integer; 815 else 816 return T.init; 817 } 818 819 // string 820 T toOBJ(T)(JSONValue v, RefClass stack) if (is(T == string)) 821 { 822 if(v.type() == JSON_TYPE.STRING) 823 return v.str; 824 else 825 return T.init; 826 } 827 828 // bool 829 T toOBJ(T)(JSONValue v, RefClass stack) if (is(T == bool)) 830 { 831 if(v.type() == JSON_TYPE.TRUE || v.type() == JSON_TYPE.FALSE) 832 return v.type() == JSON_TYPE.TRUE; 833 else 834 return T.init; 835 } 836 837 // floating 838 T toOBJ(T)(JSONValue v, RefClass stack) if (isFloatType!T) 839 { 840 if(v.type() == JSON_TYPE.FLOAT) 841 return cast(T) v.floating; 842 else 843 return T.init; 844 } 845 846 847 // array 848 JSONValue toJSON(T)(T t, RefClass stack, uint level) 849 if (isStaticArray!T || (isDynamicArray!T && !is(T == string))) 850 { 851 JSONValue[] j; 852 foreach (e; t) 853 { 854 j ~= toJSON(e, stack, level); 855 } 856 857 return JSONValue(j); 858 } 859 860 T toOBJ(T)(JSONValue v, RefClass stack) if (isStaticArray!T) 861 { 862 T t; 863 if(v.type() == JSON_TYPE.ARRAY) 864 { 865 for (size_t i = 0; i < t.length; i++) 866 { 867 t[i] = toOBJ!(typeof(t[i]))(v.array[i], stack); 868 } 869 } 870 return t; 871 872 } 873 874 T toOBJ(T)(JSONValue v, RefClass stack) if (isDynamicArray!T && !is(T == string)) 875 { 876 T t; 877 if(v.type() == JSON_TYPE.ARRAY) 878 { 879 t.length = v.array.length; 880 for (size_t i = 0; i < t.length; i++) 881 { 882 t[i] = toOBJ!(typeof(t[i]))(v.array[i], stack); 883 } 884 } 885 return t; 886 } 887 888 // struct & class 889 890 string toJSONMembers(T , bool ignore)() 891 { 892 string str; 893 foreach (m; FieldNameTuple!T) 894 { 895 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 896 { 897 if(!ignore || !hasUDA!(__traits(getMember , T , m) ,IGNORE )) 898 { 899 str ~= "j[\"" ~ m ~ "\"] = toJSON(t." ~ m ~ " , stack , level + 1);"; 900 } 901 } 902 } 903 return str; 904 } 905 906 string toJSONMembersAll(T)() 907 { 908 string str; 909 foreach (m; FieldNameTuple!T) 910 { 911 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 912 { 913 str ~= "j[\"" ~ m ~ "\"] = toJSON(t." ~ m ~ " , stack , level + 1);"; 914 } 915 } 916 return str; 917 } 918 919 920 921 string toOBJMembers(T)() 922 { 923 string str; 924 foreach (m; FieldNameTuple!T) 925 { 926 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 927 { 928 str ~= " if ( \"" ~ m ~ "\" in j )"; 929 str ~= "t." ~ m ~ " = toOBJ!(typeof(t." ~ m ~ "))(j[\"" ~ m ~ "\"] , stack);"; 930 } 931 932 } 933 return str; 934 } 935 936 JSONValue toJSON(T)(T t, RefClass stack, uint level) if (is(T == struct)) 937 { 938 JSONValue j; 939 940 static if (is(T == JSONValue)) 941 { 942 return t; 943 } 944 else{ 945 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 946 947 if(ignore) 948 mixin(toJSONMembers!(T,true)); 949 else 950 mixin(toJSONMembers!(T,false)); 951 952 953 954 955 956 return j; 957 } 958 } 959 960 T toOBJ(T)(JSONValue j, RefClass stack) if (is(T == struct)) 961 { 962 static if (is(T == JSONValue)) 963 { 964 return j; 965 } 966 else 967 { 968 T t; 969 if(j.type() == JSON_TYPE.OBJECT) 970 { 971 mixin(toOBJMembers!T); 972 } 973 return t; 974 } 975 } 976 977 JSONValue toJSON(T)(T t, RefClass stack, uint level) if (is(T == class)) 978 { 979 if (t is null || level >= stack.level) 980 { 981 return JSONValue(null); 982 } 983 984 auto id = t.toHash() in stack.map; 985 if (id == null) 986 { 987 stack.map[t.toHash()] = stack.map.length; 988 JSONValue j; 989 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 990 991 if(ignore) 992 mixin(toJSONMembers!(T,true)); 993 else 994 mixin(toJSONMembers!(T,false)); 995 return j; 996 } 997 else 998 { 999 JSONValue j; 1000 j[MAGIC_KEY] = *id; 1001 return j; 1002 } 1003 } 1004 1005 T toOBJ(T)(JSONValue j, RefClass stack) if (is(T == class)) 1006 { 1007 if ( j.type() != JSON_TYPE.OBJECT) 1008 return T.init; 1009 assert(j.type() == JSON_TYPE.OBJECT); 1010 1011 if (MAGIC_KEY in j) 1012 { 1013 return cast(T) stack.arr[j[MAGIC_KEY].uinteger]; 1014 } 1015 else 1016 { 1017 T t = new T; 1018 stack.arr ~= cast(void*) t; 1019 mixin(toOBJMembers!T); 1020 return t; 1021 } 1022 } 1023 1024 //AssociativeArray 1025 JSONValue toJSON(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 1026 { 1027 JSONValue j; 1028 import std.conv; 1029 1030 foreach (k, v; t) 1031 j[to!string(k)] = toJSON(v, stack, level); 1032 return j; 1033 } 1034 1035 T toOBJ(T)(JSONValue j, RefClass stack) if (isAssociativeArray!T) 1036 { 1037 import std.conv; 1038 if ( j.type() != JSON_TYPE.OBJECT) 1039 return T.init; 1040 T t; 1041 foreach (k, v; j.object) 1042 { 1043 t[to!(KeyType!T)(k)] = toOBJ!(ValueType!T)(v, stack); 1044 } 1045 return t; 1046 } 1047 1048 public: 1049 1050 JSONValue toJSON(T)(T t , uint level = uint.max , bool ignore = true) 1051 { 1052 RefClass stack = new RefClass(); 1053 stack.level = level; 1054 stack.ignore = ignore; 1055 return toJSON!T(t, stack, 0); 1056 } 1057 1058 JSONValue toJSON(T)(T t , UnIgnoreArray array , uint level = uint.max) 1059 { 1060 RefClass stack = new RefClass(); 1061 stack.level = level; 1062 stack.unIgnore = array; 1063 return toJSON!T(t, stack, 0); 1064 } 1065 1066 1067 1068 T toOBJ(T)(JSONValue j) 1069 { 1070 RefClass stack = new RefClass(); 1071 return toOBJ!T(j, stack); 1072 } 1073 1074 alias toJson = toJSON; 1075 alias toObject = toOBJ; 1076 1077 // only for , nested , new T 1078 /* 1079 version (unittest) 1080 { 1081 //test struct 1082 1083 void test1(T)(T t) 1084 { 1085 assert(unserialize!T(serialize(t)) == t); 1086 1087 assert(serialize(t).length == getsize(t)); 1088 1089 assert(toOBJ!T(toJSON(t)) == t); 1090 } 1091 1092 struct T1 1093 { 1094 bool b; 1095 byte ib; 1096 ubyte ub; 1097 short ish; 1098 ushort ush; 1099 int ii; 1100 uint ui; 1101 long il; 1102 ulong ul; 1103 string s; 1104 uint[10] sa; 1105 long[] sb; 1106 } 1107 1108 struct T2 1109 { 1110 string n; 1111 T1[] t; 1112 } 1113 1114 struct T3 1115 { 1116 T1 t1; 1117 T2 t2; 1118 string[] name; 1119 } 1120 1121 //test class 1122 class C 1123 { 1124 int age; 1125 string name; 1126 T3 t3; 1127 override bool opEquals(Object c) 1128 { 1129 auto c1 = cast(C) c; 1130 return age == c1.age && name == c1.name && t3 == c1.t3; 1131 } 1132 1133 C clone() 1134 { 1135 auto c = new C(); 1136 c.age = age; 1137 c.name = name; 1138 c.t3 = t3; 1139 return c; 1140 } 1141 1142 } 1143 1144 class C2 1145 { 1146 C[] c; 1147 C c1; 1148 T1 t1; 1149 1150 override bool opEquals(Object c) 1151 { 1152 auto c2 = cast(C2) c; 1153 return this.c == c2.c && c1 == c2.c1 && t1 == c2.t1; 1154 } 1155 } 1156 1157 //ref test 1158 class School 1159 { 1160 string name; 1161 User[] users; 1162 override bool opEquals(Object c) 1163 { 1164 auto school = cast(School) c; 1165 return school.name == this.name; 1166 } 1167 } 1168 1169 class User 1170 { 1171 int age; 1172 string name; 1173 School school; 1174 override bool opEquals(Object c) 1175 { 1176 auto user = cast(User) c; 1177 return user.age == this.age && user.name == this.name && user.school == this.school; 1178 } 1179 } 1180 1181 struct J{ 1182 string data; 1183 JSONValue val; 1184 1185 } 1186 1187 void test_json_ser() 1188 { 1189 J j; 1190 j.data = "test"; 1191 j.val = "FUC"; 1192 1193 toObject!J(toJson(j)); 1194 1195 } 1196 1197 void test_ref_class() 1198 { 1199 School school = new School(); 1200 1201 User user1 = new User(); 1202 user1.age = 30; 1203 user1.name = "zhangyuchun"; 1204 user1.school = school; 1205 1206 User user2 = new User(); 1207 user2.age = 31; 1208 user2.name = "wulishan"; 1209 user2.school = school; 1210 1211 school.name = "putao"; 1212 school.users ~= user1; 1213 school.users ~= user2; 1214 1215 test1(user1); 1216 test1(user2); 1217 } 1218 1219 void test_struct_class_array() 1220 { 1221 T1 t; 1222 t.b = true; 1223 t.ib = -11; 1224 t.ub = 128 + 50; 1225 t.ish = -50; 1226 t.ush = (1 << 15) + 50; 1227 t.ii = -50; 1228 t.ui = (1 << 31) + 50; 1229 t.il = (cast(long) 1 << 63) - 50; 1230 t.ul = (cast(long) 1 << 63) + 50; 1231 t.s = "test"; 1232 t.sa[0] = 10; 1233 t.sa[1] = 100; 1234 t.sb ~= 10; 1235 t.sb ~= 100; 1236 test1(t); 1237 1238 T2 t2; 1239 t2.t ~= t; 1240 t2.t ~= t; 1241 t2.n = "testt2"; 1242 test1(t2); 1243 1244 T3 t3; 1245 t3.t1 = t; 1246 t3.t2 = t2; 1247 t3.name ~= "123"; 1248 t3.name ~= "456"; 1249 test1(t3); 1250 1251 C c1 = new C(); 1252 c1.age = 100; 1253 c1.name = "test"; 1254 c1.t3 = t3; 1255 1256 test1(c1); 1257 1258 C2 c2 = new C2(); 1259 c2.c ~= c1; 1260 c2.c ~= c1.clone(); 1261 c2.c1 = c1.clone(); 1262 c2.t1 = t; 1263 1264 test1(c2); 1265 1266 C2 c3 = null; 1267 1268 test1(c3); 1269 1270 string[string] map1 = ["1" : "1", "2" : "2"]; 1271 string[int] map2 = [1 : "1", 2 : "2"]; 1272 T1[string] map3; 1273 T1 a1; 1274 a1.ib = 1; 1275 T1 a2; 1276 a2.ib = 2; 1277 map3["1"] = a1; 1278 map3["2"] = a2; 1279 test1(map1); 1280 test1(map2); 1281 test1(map3); 1282 } 1283 1284 } 1285 1286 unittest 1287 { 1288 import std.stdio; 1289 1290 long index; 1291 1292 void test(T)(T v) 1293 { 1294 long index; 1295 byte[] bs = toVariant(v); 1296 long length = bs.length; 1297 bs ~= ['x', 'y']; 1298 assert(toT!T(bs, index) == v && index == length); 1299 1300 assert(toOBJ!T(toJSON(v)) == v); 1301 1302 } 1303 1304 //test variant 1305 1306 //unsigned 1307 { 1308 ubyte j0 = 0; 1309 ubyte j1 = 50; 1310 ubyte j2 = (1 << 7) + 50; 1311 ubyte j3 = 0xFF; 1312 1313 ushort j4 = (1 << 14) + 50; 1314 ushort j5 = 0xFFFF; 1315 1316 uint j6 = (1 << 21) + 50; 1317 uint j7 = (1 << 28) + 50; 1318 uint j8 = 128; 1319 uint j9 = 0xFFFFFFFF; 1320 1321 { 1322 1323 1324 } 1325 1326 ulong j10 = (cast(ulong) 1 << 35) + 50; 1327 ulong j11 = (cast(ulong) 1 << 42) + 50; 1328 ulong j12 = (cast(ulong) 1 << 49) + 50; 1329 ulong j13 = (cast(ulong) 1 << 56) + 50; 1330 ulong j14 = j9 + j10 + j11 + j12; 1331 ulong j15 = 0xFFFFFFFFFFFFFFFF; 1332 test(j0); 1333 test(j1); 1334 test(j2); 1335 test(j3); 1336 test(j4); 1337 test(j5); 1338 test(j6); 1339 test(j7); 1340 test(j8); 1341 test(j9); 1342 test(j10); 1343 test(j11); 1344 test(j12); 1345 test(j13); 1346 test(j14); 1347 test(j15); 1348 } 1349 1350 //signed 1351 { 1352 byte i0 = 0; 1353 byte i1 = (1 << 6) + 50; 1354 byte i2 = (1 << 7) - 1; 1355 byte i3 = -i2; 1356 byte i4 = -i1; 1357 1358 test(i0); 1359 test(i1); 1360 test(i2); 1361 test(i3); 1362 test(i4); 1363 1364 short i5 = (1 << 7) + 50; 1365 short i6 = (1 << 14) + 50; 1366 short i7 = -i5; 1367 short i8 = -i6; 1368 1369 test(i5); 1370 test(i6); 1371 test(i7); 1372 test(i8); 1373 1374 int i9 = (1 << 16) + 50; 1375 int i10 = (1 << 25) + 50; 1376 int i11 = (1 << 30) + 50; 1377 int i12 = 64; 1378 int i13 = -i10; 1379 int i14 = -i11; 1380 int i15 = i9 + i10 + i11; 1381 int i16 = -i15; 1382 1383 1384 1385 test(i9); 1386 test(i10); 1387 test(i11); 1388 test(i12); 1389 test(i13); 1390 test(i14); 1391 test(i15); 1392 test(i16); 1393 1394 long i17 = (cast(long) 1 << 32) + 50; 1395 long i18 = (cast(long) 1 << 48) + 50; 1396 long i19 = (cast(long) 1 << 63) + 50; 1397 long i20 = i17 + i18 + i19; 1398 long i21 = -i17; 1399 long i22 = -i20; 1400 1401 test(i17); 1402 test(i18); 1403 test(i19); 1404 test(i20); 1405 test(i21); 1406 test(i22); 1407 1408 int i23 = -11; 1409 test(i23); 1410 } 1411 1412 //test serialize 1413 1414 //basic: byte ubyte short ushort int uint long ulong 1415 { 1416 byte b1 = 123; 1417 byte b2 = -11; 1418 ubyte b3 = 233; 1419 1420 short s1 = -11; 1421 short s2 = (1 << 8) + 50; 1422 short s3 = (1 << 15) - 50; 1423 ushort s4 = (1 << 16) - 50; 1424 1425 int i1 = -11; 1426 int i2 = (1 << 16) + 50; 1427 int i3 = (1 << 31) - 50; 1428 uint i4 = (1 << 31) + 50; 1429 1430 long l1 = -11; 1431 long l2 = (cast(long) 1 << 32) + 50; 1432 long l3 = (cast(long) 1 << 63) - 50; 1433 ulong l4 = (cast(long) 1 << 63) + 50; 1434 1435 test1(b1); 1436 test1(b2); 1437 test1(b3); 1438 1439 test1(s1); 1440 test1(s2); 1441 test1(s3); 1442 test1(s4); 1443 1444 test1(i1); 1445 test1(i2); 1446 test1(i3); 1447 test1(i4); 1448 1449 test1(l1); 1450 test1(l2); 1451 test1(l3); 1452 test1(l4); 1453 } 1454 1455 //test string 1456 { 1457 string s1 = ""; 1458 string s2 = "1"; 1459 string s3 = "123"; 1460 test1(s1); 1461 test1(s2); 1462 test1(s3); 1463 } 1464 1465 //test static arrary 1466 { 1467 string[5] sa; 1468 sa[0] = "test0"; 1469 sa[1] = "test1"; 1470 sa[2] = "test2"; 1471 sa[3] = "test3"; 1472 sa[4] = "test4"; 1473 test1(sa); 1474 } 1475 1476 //test dynamic arrary 1477 { 1478 string[] sa; 1479 sa ~= "test1"; 1480 sa ~= "test2"; 1481 sa ~= "test3"; 1482 sa ~= "test4"; 1483 1484 test1(sa); 1485 1486 string[] sa2; 1487 test1(sa2); 1488 } 1489 1490 //test struct \ class \ associative array 1491 test_struct_class_array(); 1492 test_ref_class(); 1493 test_json_ser(); 1494 1495 ////unsigned 1496 uint ut1 = 1 << 7; 1497 uint ut2 = 1 << 14; 1498 uint ut3 = 1 << 21; 1499 uint ut4 = 1 << 28; 1500 1501 //signed 1502 int it1 = 1 << 6; 1503 int it2 = 1 << 13; 1504 int it3 = 1 << 20; 1505 int it4 = 1 << 27; 1506 1507 test1(ut1); 1508 test1(ut2); 1509 test1(ut3); 1510 test1(ut4); 1511 1512 test1(it1); 1513 test1(it2); 1514 test1(it3); 1515 test1(it4); 1516 } 1517 */