@@ -21,8 +21,63 @@ abstract class SerializationFormat
2121 ;
2222
2323protected :
24- enum deserializationContext;
24+ static struct SerializedFieldSet (T)
25+ {
26+ import std.performance.bitmanip : BitArray ;
27+
28+ alias members = membersToSerialize! T;
29+ // BUG: Required due to a bug that causes compilation to fail
30+ enum membersLength = members.length;
31+
32+ mixin (genDeclarations());
33+ private static string genDeclarations ()
34+ {
35+ import std.conv : to;
36+ import std.performance.array : Appender;
37+
38+ auto ret = Appender! string ();
39+
40+ ret.put(` BitArray!` );
41+ ret.put(to! string (membersLength));
42+ ret.put(` fieldMarkers;` );
43+
44+ BitArray ! membersLength expectedArr;
45+ foreach (i, m; members)
46+ {
47+ if (! isMemberOptional! (T, m))
48+ expectedArr[i] = true ;
49+ }
50+ ret.put(` enum expectedFields = BitArray!` );
51+ ret.put(to! string (membersLength));
52+ ret.put(` ([` );
53+ foreach (i, d; expectedArr.data)
54+ {
55+ if (i != 0 )
56+ ret.put(' ,' );
57+ ret.put(` 0x` );
58+ ret.put(to! string (d, 16 ));
59+ }
60+ ret.put(` ]);` );
61+
62+ return ret.data;
63+ }
64+
65+ @property void markSerialized(string member)() @safe pure nothrow
66+ {
67+ import std.typecons : staticIndexOf;
68+
69+ fieldMarkers[staticIndexOf! (member, members)] = true ;
70+ }
2571
72+ void ensureFullySerialized () @safe pure
73+ {
74+ fieldMarkers &= expectedFields;
75+ if (fieldMarkers != expectedFields)
76+ throw new Exception (" A required field was not deserialized!" );
77+ }
78+ }
79+
80+ enum deserializationContext;
2681 enum isDeserializationContext (T) = hasAttribute! (T, deserializationContext);
2782
2883 template isSerializable (T)
@@ -46,12 +101,38 @@ protected:
46101 else
47102 static assert (0 , " Not yet implemented!" );
48103 }
104+
105+ template membersToSerialize (T)
106+ {
107+ alias CTValSet (E... ) = E;
108+ enum shouldSerializeMember (string member) = member != " this" && isMemberField! (T, member) && ! memberHasAttribute! (T, member, nonSerialized);
109+
110+ // TODO: This needs to deal with inherited members that have the same name.
111+ template membersToSerializeImpl (T, Members... )
112+ {
113+ static if (Members.length > 1 )
114+ {
115+ static if (shouldSerializeMember! (Members[0 ]))
116+ alias membersToSerializeImpl = CTValSet! (Members[0 ], membersToSerializeImpl! (T, Members[1 .. $]));
117+ else
118+ alias membersToSerializeImpl = membersToSerializeImpl! (T, Members[1 .. $]);
119+ }
120+ else
121+ {
122+ static if (shouldSerializeMember! (Members[0 ]))
123+ alias membersToSerializeImpl = CTValSet! (Members[0 ]);
124+ else
125+ alias membersToSerializeImpl = CTValSet! ();
126+ }
127+ }
128+ alias membersToSerialize = membersToSerializeImpl! (T, __traits(allMembers, T));
129+ }
49130
50- enum shouldSerializeMember (T, string member) = member != " this " && isMemberField ! (T, member) && ! memberHasAttribute! (T, member, nonSerialized );
131+ enum isMemberOptional (T, string member) = memberHasAttribute! (T, member, optional );
51132
52133 static bool shouldSerializeValue (T, string member)(T val) @safe pure nothrow
53134 {
54- static if (memberHasAttribute ! (T, member, optional ))
135+ static if (isMemberOptional ! (T, member))
55136 {
56137 if (getDefaultMemberValue! (T, member) == getMemberValue! member(val))
57138 return false ;
@@ -77,9 +158,7 @@ protected:
77158 static if (__traits(compiles, (cast (T)T.init).toString()) && __traits(compiles, T.parse(" " )))
78159 {
79160 // TODO: Support using an output range here as well.
80- output.put(' "' );
81- output.put(val.toString());
82- output.put(' "' );
161+ serialize(output, val.toString());
83162 }
84163 else
85164 static assert (0 , typeof (this ).stringof ~ " does not support serializing " ~ T.stringof ~ " s!" );
0 commit comments