1 /**********************************************************\
2 |                                                          |
3 |                          hprose                          |
4 |                                                          |
5 | Official WebSite: http://www.hprose.com/                 |
6 |                   http://www.hprose.org/                 |
7 |                                                          |
8 \**********************************************************/
9 
10 /**********************************************************\
11  *                                                        *
12  * hprose/io/common.d                                     *
13  *                                                        *
14  * hprose common library for D.                           *
15  *                                                        *
16  * LastModified: Jul 15, 2015                             *
17  * Author: Ma Bingyao <andot@hprose.com>                  *
18  *                                                        *
19 \**********************************************************/
20 
21 module hprose.io.common;
22 @safe:
23 
24 import std.stdio;
25 import std.traits;
26 import std.typecons;
27 import std.typetuple;
28 
29 template make(T)
30 if (is(T == struct) || is(T == class)) {
31     T make(Args...)(Args arguments)
32     if (is(T == struct) && __traits(compiles, T(arguments))) {
33         return T(arguments);
34     }
35     
36     T make(Args...)(Args arguments)
37     if (is(T == class) && __traits(compiles, new T(arguments))) {
38         return new T(arguments);
39     }
40 }
41 
42 template isSerializable(T) {
43     alias U = Unqual!T;
44     static if (is(U == typeof(null)) ||
45         isBasicType!U ||
46         isSomeString!U ||
47         is(U == struct)) {
48         enum isSerializable = true;
49     }
50     else static if (is(U == class) && !isAbstractClass!U
51         && __traits(compiles, { new U; })) {
52         enum isSerializable = true;
53     }
54     else static if (isArray!U) {
55         enum isSerializable = isSerializable!(ForeachType!U);
56     }
57     else static if (isAssociativeArray!U) {
58         enum isSerializable = isSerializable!(KeyType!U) && isSerializable!(ValueType!U);
59     }
60     else {
61         enum isSerializable = false;
62     }
63 }
64 
65 template isSerializableField(T) if (is(T == struct) || is(T == class)) {
66     template isSerializableField(string M) {
67         static if (__traits(hasMember, T, M) && is(typeof(__traits(getMember, T, M)))) {
68             alias U = typeof(__traits(getMember, T, M));
69             enum isSerializableField = isAssignable!U && isSerializable!U &&
70                 !__traits(compiles, { mixin("(T)." ~ M ~ " = (U).init;"); }) &&
71                     __traits(compiles, { mixin("const T x = T.init; U y = x." ~ M ~ ";"); });
72         }
73         else {
74             enum isSerializableField = false;
75         }
76     }
77 }
78 
79 template getSerializableFields(T) if (is(T == struct) || is(T == class)) {
80     enum allMembers = __traits(allMembers, T);
81     static if (allMembers.length > 0) {
82         enum getSerializableFields = tuple(Filter!(isSerializableField!T, allMembers));
83     }
84     else {
85         static assert(0, T.stringof ~ " has no fields");
86     }
87 }
88 
89 private {
90 
91     struct MyStruct { int a; };
92 
93     class MyClass { int a; this(int a) {}; this() {}; };
94 
95 }
96 
97 unittest {
98     assert(getSerializableFields!(MyStruct) == tuple("a"));
99     assert(getSerializableFields!(MyClass) == tuple("a"));
100 }