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/classmanager.d                               *
13  *                                                        *
14  * hprose classmanager library for D.                     *
15  *                                                        *
16  * LastModified: Jan 3, 2016                              *
17  * Author: Ma Bingyao <andot@hprose.com>                  *
18  *                                                        *
19 \**********************************************************/
20 
21 module hprose.io.classmanager;
22 
23 import hprose.io.common;
24 import hprose.io.reader;
25 import std.stdio;
26 import std.traits;
27 import std.variant;
28 import std.typecons;
29 
30 package interface Unserializer {
31     Variant get();
32     void setRef();
33     void setField(string name);
34 }
35 
36 private synchronized class classmanager {
37     private {
38         TypeInfo[string] nameCache;
39         string[TypeInfo] typeCache;
40         Unserializer delegate(Reader reader)[TypeInfo] unserializerCache;
41     }
42     string register(T)(string name) {
43         if (name !in nameCache) {
44             nameCache[name] = cast(shared)typeid(Unqual!T);
45             typeCache[typeid(Unqual!T)] = name;
46             unserializerCache[typeid(Unqual!T)] = delegate(Reader reader) {
47                 class UnserializerImpl: Unserializer {
48                     private {
49                         Unqual!T value = make!(Unqual!T)();
50                         @safe void delegate()[string] setters;
51                     }
52                     private void genSetters(alias fieldList)() {
53                         static if (fieldList.length > 0) {
54                             enum f = fieldList[0];
55                             setters[f] = delegate() {
56                                 __traits(getMember, value, f) = reader.unserialize!(typeof(__traits(getMember, value, f)))();
57                             };
58                             static if (fieldList.length > 1) {
59                                 genSetters!(tuple(fieldList[1..$]))();
60                             }
61                         }
62                     }
63                     this() {
64                         genSetters!(getSerializableFields!(Unqual!T))();
65                     }
66                     Variant get() {
67                         return Variant(value);
68                     }
69                     void setRef() {
70                         static if (is(T == struct)) {
71                             reader.setRef(null);
72                         }
73                         else {
74                             reader.setRef(value);
75                         }
76                     }
77                     void setField(string name) {
78                         if (name in setters) {
79                             setters[name]();
80                         }
81                         else {
82                             reader.unserialize!Variant();
83                         }
84                     }
85                 }
86                 return new UnserializerImpl();
87             };
88         }
89         return name;
90     }
91     TypeInfo getClass(string name) {
92         return (cast(TypeInfo[string])nameCache).get(name, null);
93     }
94     string getAlias(T)() {
95         return (cast(string[TypeInfo])typeCache).get(typeid(Unqual!T), register!T(Unqual!T.stringof));
96     }
97     package Unserializer getUnserializer(TypeInfo t, Reader reader) {
98         if (t in unserializerCache) {
99             return unserializerCache[t](reader);
100         }
101         return null;
102     }
103 }
104 
105 static shared classmanager ClassManager = new shared classmanager();
106 
107 private {
108     class MyClass { int a; }
109     class MyClass2 { int a; }
110 }
111 
112 unittest {
113     ClassManager.register!(MyClass)("Apple");
114     assert(ClassManager.getAlias!(MyClass) == "Apple");
115     assert(ClassManager.getAlias!(MyClass2) == "MyClass2");
116     assert(ClassManager.getClass("Apple") is typeid(MyClass));
117     assert(ClassManager.getClass("MyClass2") is typeid(MyClass2));
118 }