Loading...
Searching...
No Matches
VariantSerialization.hpp
1#pragma once
3#include <score/serialization/JSONVisitor.hpp>
4#include <score/tools/Metadata.hpp>
5
6#include <ossia/detail/for_each.hpp>
7#include <ossia/detail/nullable_variant.hpp>
8
39template <typename T>
41{
43 : s{s_p}
44 , var{var_p}
45 {
46 }
47
49 const T& var;
50
51 bool done = false;
52
53 template <typename TheClass>
54 void operator()();
55};
56
57template <typename T>
58template <typename TheClass>
60{
61 // This trickery iterates over all the types in Args...
62 // A single type should be serialized, even if we cannot break.
63 if(done)
64 return;
65 if(auto res = var.template target<TheClass>())
66 {
67 s.stream() << *res;
68 done = true;
69 }
70}
71
72template <typename T>
74{
75 VariantDataStreamDeserializer(DataStream::Deserializer& s_p, quint64 which_p, T& var_p)
76 : s{s_p}
77 , which{which_p}
78 , var{var_p}
79 {
80 }
81
83 quint64 which;
84 T& var;
85
86 quint64 i = 1; // 0 is the monostate / npos
87 template <typename TheClass>
88 void operator()();
89};
90
91template <typename T>
92template <typename TheClass>
94{
95 // Here we iterate until we are on the correct type, and we deserialize it.
96 if(i++ != which)
97 return;
98
99 TheClass data;
100 s.stream() >> data;
101 var = std::move(data);
102}
103
104template <typename... Args>
105struct TSerializer<DataStream, ossia::nullable_variant<Args...>>
106{
107 using var_t = ossia::nullable_variant<Args...>;
108 static void readFrom(DataStream::Serializer& s, const var_t& var)
109 {
110 s.stream() << (quint64)var.which().index();
111
112 // TODO this should be an assert.
113 if(var)
114 {
115 ossia::for_each_type<Args...>(VariantDataStreamSerializer<var_t>{s, var});
116 }
117
118 s.insertDelimiter();
119 }
120
121 static void writeTo(DataStream::Deserializer& s, var_t& var)
122 {
123 quint64 which;
124 s.stream() >> which;
125
126 if(which != (quint64)var.npos.index())
127 {
128 ossia::for_each_type<Args...>(VariantDataStreamDeserializer<var_t>{s, which, var});
129 }
130 s.checkDelimiter();
131 }
132};
133
134// This part is required because it isn't as straightforward to save variant
135// data
136// in JSON as it is to save it in a DataStream.
137// Basically, each variant member has an associated name that will be the
138// key in the JSON parent object. This name is defined by specializing
139// template<> class Metadata<Json_k, T>.
140// For instance:
141// template<> class Metadata<Json_k, score::Address>
142// { public: static constexpr const char * get() { return "Address"; } };
143// A JSON_METADATA macro is provided for this.
144
145// This allows easy store and retrieval under a familiar name
146
147// TODO add some ASSERT for the variant being set on debug mode. npos case
148// should not happen since we have the std::optionalVariant.
149
150template <typename T>
152{
154 : s{s_p}
155 , var{var_p}
156 {
157 }
159 const T& var;
160
161 bool done = false;
162
163 template <typename TheClass>
164 void operator()();
165};
166
167template <typename T>
168template <typename TheClass>
170{
171 if(done)
172 return;
173
174 if(auto res = var.template target<TheClass>())
175 {
176 s.obj[Metadata<Json_k, TheClass>::get()] = *res;
177 done = true;
178 }
179}
180
181template <typename T>
183{
185 : s{s_p}
186 , var{var_p}
187 {
188 }
190 T& var;
191
192 bool done = false;
193 template <typename TheClass>
194 void operator()();
195};
196
197template <typename T>
198template <typename TheClass>
200{
201 if(done)
202 return;
203
204 if(auto it = s.obj.tryGet(Metadata<Json_k, TheClass>::get()))
205 {
206 JSONWriter w{*it};
207 TheClass obj;
208 obj <<= JsonValue{w.base};
209 var = std::move(obj);
210 done = true;
211 }
212}
213
214template <typename... Args>
215struct TSerializer<JSONObject, ossia::nullable_variant<Args...>>
216{
217 using var_t = ossia::nullable_variant<Args...>;
218 static void readFrom(JSONObject::Serializer& s, const var_t& var)
219 {
220 s.stream.StartObject();
221 if(var)
222 {
223 ossia::for_each_type<Args...>(VariantJSONSerializer<var_t>{s, var});
224 }
225 s.stream.EndObject();
226 }
227
228 static void writeTo(JSONObject::Deserializer& s, var_t& var)
229 {
230 if(s.base.MemberCount() == 0)
231 return;
232 ossia::for_each_type<Args...>(VariantJSONDeserializer<var_t>{s, var});
233 }
234};
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
void insertDelimiter()
insertDelimiter
Definition DataStreamVisitor.hpp:156
Definition DataStreamVisitor.hpp:202
Definition VisitorInterface.hpp:61
Definition JSONVisitor.hpp:52
Definition JSONVisitor.hpp:423
Definition JSONVisitor.hpp:372
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Definition VisitorInterface.hpp:13
Definition VariantSerialization.hpp:74
Definition VariantSerialization.hpp:41
Definition VariantSerialization.hpp:183
Definition VariantSerialization.hpp:152