Loading...
Searching...
No Matches
BoostVariant2Serialization.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/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 = ossia::get_if<TheClass>(&var))
66 {
67 s.stream() << *res;
68 done = true;
69 }
70}
71
72template <typename T>
74{
76 DataStream::Deserializer& s_p, quint64 which_p, T& var_p)
77 : s{s_p}
78 , which{which_p}
79 , var{var_p}
80 {
81 }
82
84 quint64 which;
85 T& var;
86
87 quint64 i = 0;
88 template <typename TheClass>
89 void operator()();
90};
91
92template <typename T>
93template <typename TheClass>
95{
96 // Here we iterate until we are on the correct type, and we deserialize it.
97 if(i++ != which)
98 return;
99
100 TheClass data;
101 s.stream() >> data;
102 var = std::move(data);
103}
104
105template <typename... Args>
106struct TSerializer<DataStream, ossia::variant<Args...>>
107{
108 using var_t = ossia::variant<Args...>;
109 static void readFrom(DataStream::Serializer& s, const var_t& var)
110 {
111 s.stream() << (quint64)var.index();
112
113 ossia::for_each_type<Args...>(OssiaVariantDataStreamSerializer<var_t>{s, var});
114
115 s.insertDelimiter();
116 }
117
118 static void writeTo(DataStream::Deserializer& s, var_t& var)
119 {
120 quint64 which;
121 s.stream() >> which;
122
123 ossia::for_each_type<Args...>(
125 s.checkDelimiter();
126 }
127};
128
129template <>
130struct TSerializer<DataStream, ossia::monostate>
131{
132 static void readFrom(DataStream::Serializer& s, const ossia::monostate& var) { }
133
134 static void writeTo(DataStream::Deserializer& s, ossia::monostate& var) { }
135};
136
137// This part is required because it isn't as straightforward to save variant
138// data
139// in JSON as it is to save it in a DataStream.
140// Basically, each variant member has an associated name that will be the
141// key in the JSON parent object. This name is defined by specializing
142// template<> class Metadata<Json_k, T>.
143// For instance:
144// template<> class Metadata<Json_k, score::Address>
145// { public: static constexpr const char * get() { return "Address"; } };
146// A JSON_METADATA macro is provided for this.
147
148// This allows easy store and retrieval under a familiar name
149
150// TODO add some ASSERT for the variant being set on debug mode. npos case
151// should not happen since we have the std::optionalVariant.
152
153template <typename T>
155{
157 : s{s_p}
158 , var{var_p}
159 {
160 }
162 const T& var;
163
164 bool done = false;
165
166 template <typename TheClass>
167 void operator()();
168};
169
170template <typename T>
171template <typename TheClass>
173{
174 if(done)
175 return;
176
177 if(auto res = ossia::get_if<TheClass>(&var))
178 {
179 s.obj[Metadata<Json_k, TheClass>::get()] = *res;
180 done = true;
181 }
182}
183
184template <typename T>
186{
188 : s{s_p}
189 , var{var_p}
190 {
191 }
193 T& var;
194
195 bool done = false;
196 template <typename TheClass>
197 void operator()();
198};
199
200template <typename T>
201template <typename TheClass>
203{
204 if(done)
205 return;
206
207 if(auto it = s.obj.tryGet(Metadata<Json_k, TheClass>::get()))
208 {
209 JSONWriter w{*it};
210 TheClass obj;
211 obj <<= JsonValue{w.base};
212 var = std::move(obj);
213 done = true;
214 }
215}
216
217template <typename... Args>
218struct TSerializer<JSONObject, ossia::variant<Args...>>
219{
220 using var_t = ossia::variant<Args...>;
221 static void readFrom(JSONObject::Serializer& s, const var_t& var)
222 {
223 s.stream.StartObject();
224 ossia::for_each_type<Args...>(OssiaVariantJSONSerializer<var_t>{s, var});
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...>(OssiaVariantJSONDeserializer<var_t>{s, var});
233 }
234};
235
236template <>
237struct TSerializer<JSONObject, ossia::monostate>
238{
239 static void readFrom(JSONObject::Serializer& s, const ossia::monostate& var)
240 {
241 s.stream.Null();
242 }
243
244 static void writeTo(JSONObject::Deserializer& s, ossia::monostate& var) { }
245};
246
247JSON_METADATA(std::string, "string")
248
249JSON_METADATA(std::uint8_t, "u8")
250JSON_METADATA(std::uint16_t, "u16")
251JSON_METADATA(std::uint32_t, "u32")
252JSON_METADATA(std::uint64_t, "u64")
253
254JSON_METADATA(std::int8_t, "i8")
255JSON_METADATA(std::int16_t, "i16")
256JSON_METADATA(std::int32_t, "i32")
257JSON_METADATA(std::int64_t, "i64")
258
259JSON_METADATA(std::monostate, "monostate")
260JSON_METADATA(boost::variant2::monostate, "monostate")
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
STL namespace.
Definition JSONVisitor.hpp:372
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Definition BoostVariant2Serialization.hpp:74
Definition BoostVariant2Serialization.hpp:41
Definition BoostVariant2Serialization.hpp:186
Definition BoostVariant2Serialization.hpp:155
Definition VisitorInterface.hpp:13