1 module libs.marshal.demarshaller;
2 
3 import std.traits;
4 import std.stdio;
5 
6 package interface IDemarshalStrategy
7 {
8 	void BeginDocumentDemarshal(string name);
9 	void EndDocumentDemarshal(string name);
10 	
11 	void BeginArrayDemarshal(T)(T val, string name);
12 	void EndArrayDemarshal(T)(T val, string name);
13 
14 	void BeginObjectDemarshal(T)(T val, string name);
15 	void EndObjectDemarshal(T)(T val, string name);
16 
17 	void DemarshalStructOrClass(T)(string name, ref T val);
18 	void DemarshalArray(T)(string name, ref T val);
19 	void DemarshalSingleVar(T)(string name, ref T val);
20 	void DemarshalEnum(T)(string name, ref T val);
21 	void DemarshalUnion(T)(string name, ref T val);
22 }
23 
24 package class Demarshaller(alias InDemarshalStrategy, StorageStrategy)
25 {
26 public:
27 	alias InDemarshalStrategy!(StorageStrategy) DemarshalStrategy;
28 
29 	//alias m_storer.SetBuffer SetBuffer;
30 
31 	static if (__traits(hasMember, StorageStrategy, "SetText"))
32 	{
33 		final void SetText(const(char)[] data)
34 		{
35 			m_storer.SetText(data);
36 		}
37 	}
38 	else static if (__traits(hasMember, StorageStrategy, "SetBuffer"))
39 	{
40 		final void SetBuffer(const(ubyte)[] data)
41 		{
42 			m_storer.SetBuffer(data);
43 		}
44 	}
45 	
46 	void Demarshal(T)(string name, out T val)
47 	{
48 		m_demarshaller.Demarshal(name, val);
49 	}
50 	
51 	void Demarshal(T)(out T val)
52 	{
53 		m_demarshaller.Demarshal(val);
54 	}
55 	
56 	this()
57 	{
58 		m_storer = new StorageStrategy;
59 		m_demarshaller = new DemarshalStrategy(m_storer);
60 		m_demarshaller.BeginDocumentDemarshal("");
61 	}
62 	
63 	private:
64 	StorageStrategy m_storer;
65 	DemarshalStrategy m_demarshaller;
66 }
67 
68 mixin template DemarshalMixinTemplate(StorageStrategy)
69 {
70 	void DemarshalStructOrClass(T)(string name, ref T val)
71 	{
72 		static if (__traits(hasMember, T, "BeginObjectDemarshal") && __traits(hasMember, T, "EndObjectDemarshal")
73 				&& (isSomeFunction!(T.BeginObjectDemarshal!(typeof(this), StorageStrategy)) 
74 				&& (is(TemplateArgsOf!(T.BeginObjectDemarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
75 				&&  is(TemplateArgsOf!(T.BeginObjectDemarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
76 				&& (isSomeFunction!(T.EndObjectDemarshal!(typeof(this), StorageStrategy)) 
77 				&& (is(TemplateArgsOf!(T.EndObjectDemarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
78 				&&  is(TemplateArgsOf!(T.EndObjectDemarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy))))
79 		{
80 			val.BeginObjectDemarshal!(typeof(this), StorageStrategy)(storer, name);
81 			foreach (item; __traits(allMembers, T))
82 			{
83 				static if (__traits(compiles, Demarshal(item, __traits(getMember, val, item)))
84 						&& !isSomeFunction!(typeof(__traits(getMember, val, item))))
85 				{
86 					Demarshal(item, __traits(getMember, val, item));
87 				}
88 			}
89 			val.EndObjectDemarshal!(typeof(this), StorageStrategy)(storer, name);
90 		}
91 		else 
92 		{
93 			BeginObjectDemarshal(name, val);
94 			foreach (item; __traits(allMembers, T))
95 			{
96 				static if (__traits(compiles, Demarshal(item, __traits(getMember, val, item)))
97 						&& !isSomeFunction!(typeof(__traits(getMember, val, item))))
98 				{
99 					Demarshal(item, __traits(getMember, val, item));
100 //					writefln("Demarshal: %s, %s", item, to!string(__traits(getMember, val, item)));
101 				}
102 			}
103 			EndObjectDemarshal(name, val);
104 		}
105 	}
106 	
107 	void DemarshalArray(T)(string name, ref T val)
108 	{
109 		static if (__traits(hasMember, T, "BeginArrayDemarshal") && __traits(hasMember, T, "EndArrayDemarshal")
110 				&& (isSomeFunction!(T.BeginArrayDemarshal!(typeof(this), StorageStrategy)) 
111 				&& (is(TemplateArgsOf!(T.BeginArrayDemarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
112 				&&  is(TemplateArgsOf!(T.BeginArrayDemarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
113 				&& (isSomeFunction!(T.EndArrayDemarshal!(typeof(this), StorageStrategy)) 
114 				&& (is(TemplateArgsOf!(T.EndArrayDemarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
115 				&&  is(TemplateArgsOf!(T.EndArrayDemarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy))))
116 		{
117 			//Begin
118 			val.BeginArrayDemarshal!(typeof(this), StorageStrategy)(storer, name);
119 			
120 			int i = 0;
121 			val = [];
122 			ForeachType!(T) item;
123 			try
124 			{
125 				while (true)
126 				{
127 					Demarshal(to!string(i), item);
128 					val ~= item;
129 					++i;
130 				}
131 			}
132 			catch (InvalidFormattingException ex)
133 			{
134 			}
135 			
136 			//End
137 			val.EndArrayDemarshal!(typeof(this), StorageStrategy)(storer, name);
138 		}
139 		else 
140 		{
141 			//Begin
142 			BeginArrayDemarshal(name, val);
143 			
144 			static if (__traits(hasMember, typeof(this), "LoopArrayDemarshal") && 
145 				isSomeFunction!(typeof(this).LoopArrayDemarshal!(T)))
146 			{
147 				LoopArrayDemarshal(name, val);
148 			}
149 			else
150 			{
151 				int i = 0;
152 				val = [];
153 				ForeachType!(T) item;
154 				try
155 				{
156 					while (true)
157 					{
158 						Demarshal(to!string(i), item);
159 						val ~= item;
160 						++i;
161 					}
162 				}
163 				catch (InvalidFormattingException ex)
164 				{
165 				}
166 			}
167 			
168 			//End
169 			EndArrayDemarshal(name, val);
170 		}
171 	}
172 	
173 	void Demarshal(T)(string name, ref T val) 
174 	{
175 		static if (__traits(hasMember, T, "Demarshal") 
176 					&& isSomeFunction!(T.Demarshal!(typeof(this), StorageStrategy))
177 					&& (is(TemplateArgsOf!(T.Demarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
178 					&&  is(TemplateArgsOf!(T.Demarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
179 		{
180 			val.Demarshal!(typeof(this), StorageStrategy)(m_storer, name);
181 		}
182 		else static if (is(T == struct) || is(T == class))
183 		{
184 			DemarshalStructOrClass(name, val);
185 		}
186 		else static if (isArray!(T) && !isSomeString!(T))
187 		{
188 			DemarshalArray(name, val);
189 		}
190 		else static if (__traits(isPOD, T))
191 		{
192 			DemarshalSingleVar(name, val);
193 		}
194 	}
195 	
196 	private StorageStrategy m_storer;
197 	
198 	package this(StorageStrategy storer)
199 	{
200 		this.m_storer = storer;
201 	}
202 
203 }