1 module libs.marshal.marshaller;
2 
3 import std.traits;
4 import std.stdio;
5 import std.conv;
6 
7 package interface IMarshalStrategy
8 {
9 	void BeginDocumentMarshal(string name);
10 	void EndDocumentMarshal(string name);
11 
12 	void BeginObjectMarshal(T)(T val, string name);
13 	void EndObjectMarshal(T)(T val, string name);
14 	
15 	void BeginArrayMarshal(T)(T val, string name);
16 	void EndArrayMarshal(T)(T val, string name);
17 
18 	void MarshalClassOrStruct(T)(T val, string name);
19 	void MarshalArray(T)(StorageStrategy storer, T val, string name);
20 	void MarshalSingleVar(T)(T val, string name);
21 	void MarshalEnum(T)(T val, string name);
22 	void MarshalUnion(T)(T val, string name);
23 }
24 
25 package class Marshaller(alias InMarshalStrategy, StorageStrategy)
26 {
27 public:
28 	alias InMarshalStrategy!(StorageStrategy) MarshalStrategy;
29 
30 	final string ToString()
31 	{
32 		return to!string(m_storer.GetBuffer().idup);
33 	}
34 	
35 	final auto GetBuffer()
36 	{
37 		return m_storer.GetBuffer().idup;
38 	}
39 	
40 	void Marshal(T)(T val, string name)
41 	{
42 		m_marshaller.Marshal(val, name);
43 	}
44 	
45 	this()
46 	{
47 		m_storer = new StorageStrategy;
48 		m_marshaller = new MarshalStrategy(m_storer);
49 		m_marshaller.BeginDocumentMarshal("");
50 	}
51 	
52 	private:
53 	StorageStrategy m_storer;
54 	MarshalStrategy m_marshaller;
55 }
56 
57 mixin template MarshalMixinTemplate(StorageStrategy)
58 {
59 	void MarshalClassOrStruct(T)(T val, string name)
60 	{
61 		static if (__traits(hasMember, T, "BeginObjectMarshal") && __traits(hasMember, T, "EndObjectMarshal")
62 				&& (isSomeFunction!(T.BeginObjectMarshal!(typeof(this), StorageStrategy)) 
63 				&& (is(TemplateArgsOf!(T.BeginObjectMarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
64 				&&  is(TemplateArgsOf!(T.BeginObjectMarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
65 				&& (isSomeFunction!(T.EndObjectMarshal!(typeof(this), StorageStrategy)) 
66 				&& (is(TemplateArgsOf!(T.EndObjectMarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
67 				&&  is(TemplateArgsOf!(T.EndObjectMarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy))))
68 		{
69 			val.BeginObjectMarshal!(typeof(this), StorageStrategy)(m_storer, name);
70 			foreach (item; __traits(allMembers, T))
71 			{
72 				static if (__traits(compiles, Marshal(__traits(getMember, val, item), item))
73 					&& !isSomeFunction!(typeof(__traits(getMember, val, item))))
74 				{
75 					Marshal(__traits(getMember, val, item), item);
76 				}
77 			}
78 			val.EndObjectMarshal!(typeof(this), StorageStrategy)(m_storer, name);
79 		}
80 		else 
81 		{
82 			BeginObjectMarshal(val, name);
83 			foreach (item; __traits(allMembers, T))
84 			{
85 				static if (__traits(compiles, Marshal(__traits(getMember, val, item), item))
86 					&& !isSomeFunction!(typeof(__traits(getMember, val, item))))
87 				{
88 					Marshal(__traits(getMember, val, item), item);
89 				}
90 			}
91 			EndObjectMarshal(val, name);
92 		}
93 	}
94 	
95 	void MarshalArray(T)(T val, string name)
96 	{
97 		static if (__traits(hasMember, T, "BeginArrayMarshal") && __traits(hasMember, T, "EndArrayMarshal")
98 				&& (isSomeFunction!(T.BeginArrayMarshal!(typeof(this), StorageStrategy)) 
99 				&& (is(TemplateArgsOf!(T.BeginArrayMarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
100 				&&  is(TemplateArgsOf!(T.BeginArrayMarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
101 				&& (isSomeFunction!(T.EndArrayMarshal!(typeof(this), StorageStrategy)) 
102 				&& (is(TemplateArgsOf!(T.EndArrayMarshal!(typeof(this), StorageStrategy))[0] == typeof(this))
103 				&&  is(TemplateArgsOf!(T.EndArrayMarshal!(typeof(this), StorageStrategy))[1] == StorageStrategy))))
104 		{
105 			val.BeginArrayMarshal!(typeof(this), StorageStrategy)(storer, name);
106 			foreach (i, item; val)
107 			{
108 				Marshal(item, to!string(i));
109 			}
110 			val.EndArrayMarshal!(typeof(this), StorageStrategy)(storer, name);
111 		}
112 		else 
113 		{
114 			BeginArrayMarshal(val, name);
115 			foreach (i, item; val)
116 			{
117 				Marshal(item, to!string(i));
118 			}
119 			EndArrayMarshal(val, name);
120 		}
121 	}
122 	
123 	void Marshal(T)(T val, string name)
124 	{
125 		static if (__traits(hasMember, T, "Marshal") 
126 					&& isSomeFunction!(T.Marshal!(typeof(this), StorageStrategy))
127 					&& (is(TemplateArgsOf!(T.Marshal!(typeof(this), StorageStrategy))[0] == typeof(this))
128 					&&  is(TemplateArgsOf!(T.Marshal!(typeof(this), StorageStrategy))[1] == StorageStrategy)))
129 		{
130 			val.Marshal!(typeof(this), StorageStrategy)(m_storer, name);
131 		}
132 		else static if (is(T == struct) || is(T == class))
133 		{
134 			MarshalClassOrStruct(val, name);
135 		}
136 		else static if (isArray!(T) && !isSomeString!(T))
137 		{
138 			MarshalArray(val, name);
139 		}
140 		else static if (is(T == enum))
141 		{
142 			MarshalEnum(val, name);
143 		}
144 		else static if (is(T == union))
145 		{
146 			MarshalUnion(val, name);
147 		}
148 		else static if (__traits(isPOD, T))
149 		{
150 			//Any other POD, we've already covered structs
151 			MarshalSingleVar(val, name);
152 		}
153 		else 
154 		{
155 			//do nothing...
156 		}
157 	}
158 	
159 	private StorageStrategy m_storer;
160 	
161 	package this(StorageStrategy storer)
162 	{
163 		this.m_storer = storer; 
164 	}
165 
166 }