Loading...
Searching...
No Matches
DataStreamVisitor.hpp
Go to the documentation of this file.
1#pragma once
2#include <score/model/Identifier.hpp>
3#include <score/plugins/UuidKey.hpp>
4#include <score/serialization/CommonTypes.hpp>
5#include <score/serialization/DataStreamFwd.hpp>
6#include <score/serialization/DataStreamHelpers.hpp>
7#include <score/serialization/VisitorInterface.hpp>
8#include <score/serialization/VisitorTags.hpp>
9#include <score/tools/std/HashMap.hpp>
10#include <score/tools/std/Optional.hpp>
11
12#include <ossia/detail/flat_set.hpp>
13#include <ossia/detail/small_vector.hpp>
14
15#include <verdigris>
16
17template <typename model>
19namespace score
20{
21template <typename model>
22class Entity;
23class ApplicationComponents;
24}
25
26class SCORE_LIB_BASE_EXPORT DataStreamReader : public AbstractVisitor
27{
28public:
29 using type = DataStream;
30 using is_visitor_tag = std::integral_constant<bool, true>;
31
32 VisitorVariant toVariant() { return {*this, DataStream::type()}; }
33
35 DataStreamReader(QByteArray* array);
36 DataStreamReader(QIODevice* dev);
37
38 DataStreamReader(const DataStreamReader&) = delete;
39 DataStreamReader& operator=(const DataStreamReader&) = delete;
40
41 template <typename T>
42 static auto marshall(const T& t)
43 {
44 QByteArray arr;
45 DataStreamReader reader{&arr};
46 reader.readFrom(t);
47 return arr;
48 }
49
51
52 template <typename T>
53 void readFrom(const score::Entity<T>& obj)
54 {
55 TSerializer<DataStream, score::Entity<T>>::readFrom(*this, obj);
56 }
57
58 template <typename T>
59 void readFrom(const IdentifiedObject<T>& obj)
60 {
62 }
63
64 void readFrom(const QByteArray& obj) { m_stream_impl << obj; }
65
66 template <typename T>
67 void readFrom(const T& obj)
68 {
69 static constexpr bool has_base = base_kind<T>::value;
70
71 if constexpr(has_base)
72 {
73 readFrom((const typename T::score_base_type&)obj);
74 }
75 else
76 {
77 if constexpr(
78 (is_template<T>::value && !abstract_base<T> && !identified_object<T>)
79 || is_custom_serialized<T>::value)
80 {
82 }
83 else if constexpr(
85 && !is_custom_serialized<T>::value)
86 {
88
89 if constexpr(is_custom_serialized<T>::value || is_template<T>::value)
91 else
92 read(obj);
93 }
94 else if constexpr(
95 identified_entity<T> && !abstract_base<T> && !is_custom_serialized<T>::value)
96 {
98
99 if constexpr(is_custom_serialized<T>::value || is_template<T>::value)
101 else
102 read(obj);
103 }
104 else if constexpr(
105 !identified_object<T> && abstract_base<T> && !is_custom_serialized<T>::value)
106 {
107 readFromAbstract(obj, [](DataStreamReader& sub, const T& obj) {
108 // Read the implementation of the base object
109 sub.read(obj);
110 });
111 }
112 else if constexpr(
114 && !is_custom_serialized<T>::value)
115 {
116 readFromAbstract(obj, [](DataStreamReader& sub, const T& obj) {
118
119 if constexpr(is_custom_serialized<T>::value || is_template<T>::value)
121 else
122 sub.read(obj);
123 });
124 }
125 else if constexpr(
126 identified_entity<T> && abstract_base<T> && !is_custom_serialized<T>::value)
127 {
128 readFromAbstract(obj, [](DataStreamReader& sub, const T& obj) {
129 TSerializer<DataStream, score::Entity<T>>::readFrom(sub, obj);
130
131 if constexpr(is_custom_serialized<T>::value || is_template<T>::value)
133 else
134 sub.read(obj);
135 });
136 }
137 else if constexpr(std::is_enum<T>::value)
138 {
139 static_assert(check_enum_size<T>::value);
140 m_stream << (int32_t)obj;
141 }
142 else
143 {
146 read(obj);
147 }
148 }
149 }
150
156 void insertDelimiter() { m_stream << int32_t(0xDEADBEEF); }
157
158 auto& stream() { return m_stream; }
159
162 template <typename T>
163 void read(const T&);
164
165private:
166 template <typename T, typename Fun>
167 void readFromAbstract(const T& obj, Fun f)
168 {
169 // We save in a byte array so that
170 // we have a chance to save it as-is and reload it later
171 // if the plug-in is not found on the system.
172 QByteArray b;
174
175 // First read the key
176 SCORE_DEBUG_INSERT_DELIMITER2(sub);
177 sub.readFrom(obj.concreteKey().impl());
178 SCORE_DEBUG_INSERT_DELIMITER2(sub);
179
180 // Read our object
181 f(sub, obj);
182
183 // Read the implementation of the derived class, through a virtual
184 // function.
185 obj.serialize_impl(sub.toVariant());
186
187 // Finish our object
188 SCORE_DEBUG_INSERT_DELIMITER2(sub);
189
190 // Save the bundle
191 m_stream << std::move(b);
192 }
193
194 QDataStream m_stream_impl;
195
196public:
197 const score::ApplicationComponents& components;
198 DataStreamInput m_stream{m_stream_impl};
199};
200
201class SCORE_LIB_BASE_EXPORT DataStreamWriter : public AbstractVisitor
202{
203public:
204 using type = DataStream;
205 using is_visitor_tag = std::integral_constant<bool, true>;
206 using is_deserializer_tag = std::integral_constant<bool, true>;
207
208 VisitorVariant toVariant() { return {*this, DataStream::type()}; }
209
211 DataStreamWriter(const DataStreamWriter&) = delete;
212 DataStreamWriter& operator=(const DataStreamWriter&) = delete;
213
214 DataStreamWriter(const QByteArray& array);
215 DataStreamWriter(QIODevice* dev);
216
217 template <typename T>
218 static auto unmarshall(const QByteArray& arr)
219 {
220 T data;
221 DataStreamWriter wrt{arr};
222 wrt.writeTo(data);
223 return data;
224 }
225
228 template <typename T>
229 void write(T&);
230
231 void writeTo(QByteArray& obj) { m_stream_impl >> obj; }
232
233 template <typename T>
234 void writeTo(T& obj)
235 {
236 if constexpr(
237 (is_template<T>::value && !abstract_base<T> && !identified_object<T>)
238 || is_custom_serialized<T>::value)
239 {
241 }
242 else if constexpr(std::is_enum<T>::value)
243 {
244 static_assert(check_enum_size<T>::value);
245 int32_t e;
246 m_stream >> e;
247 obj = static_cast<T>(e);
248 }
249 else
250 {
251 write(obj);
252 }
253 }
254
261 void checkDelimiter();
262
263 auto& stream() { return m_stream; }
264
265 const score::ApplicationComponents& components;
266 DataStreamOutput m_stream{m_stream_impl};
267
268private:
269 QDataStream m_stream_impl;
270};
271
272template <typename T>
273 requires(!std::is_enum_v<T>)
274DataStreamInput& operator<<(DataStreamInput& s, const T& obj)
275{
276 DataStreamReader reader{s.stream.device()};
277 reader.readFrom(obj);
278 return s;
279}
280
281template <typename T>
282 requires(!std::is_enum_v<T>)
283DataStreamOutput& operator>>(DataStreamOutput& s, T& obj)
284{
285 DataStreamWriter writer{s.stream.device()};
286 writer.writeTo(obj);
287 return s;
288}
289
290template <typename U>
292{
293 static void readFrom(DataStream::Serializer& s, const Id<U>& obj)
294 {
295 s.stream() << obj.val();
296 SCORE_DEBUG_INSERT_DELIMITER2(s);
297 }
298
299 static void writeTo(DataStream::Deserializer& s, Id<U>& obj)
300 {
301 int32_t val{};
302 s.stream() >> val;
303 obj.setVal(val);
304 SCORE_DEBUG_CHECK_DELIMITER2(s);
305 }
306};
307
308template <typename T>
310{
311 template <typename U>
312 static void readFrom(DataStream::Serializer& s, const IdentifiedObject<U>& obj)
313 {
314 SCORE_DEBUG_INSERT_DELIMITER2(s);
315 s.stream() << obj.objectName();
316 SCORE_DEBUG_INSERT_DELIMITER2(s);
317 s.readFrom(obj.id());
318 SCORE_DEBUG_INSERT_DELIMITER2(s);
319 }
320
321 template <typename U>
322 static void writeTo(DataStream::Deserializer& s, IdentifiedObject<U>& obj)
323 {
324 QString name;
325 Id<T> id;
326 SCORE_DEBUG_CHECK_DELIMITER2(s);
327 s.stream() >> name;
328 SCORE_DEBUG_CHECK_DELIMITER2(s);
329 obj.setObjectName(name);
330 s.writeTo(id);
331 obj.setId(std::move(id));
332 SCORE_DEBUG_CHECK_DELIMITER2(s);
333 }
334};
335
336template <typename T>
337struct TSerializer<DataStream, std::optional<T>>
338{
339 static void readFrom(DataStream::Serializer& s, const std::optional<T>& obj)
340 {
341 s.stream() << static_cast<bool>(obj);
342
343 if(obj)
344 {
345 s.stream() << *obj;
346 }
347 SCORE_DEBUG_INSERT_DELIMITER2(s);
348 }
349
350 static void writeTo(DataStream::Deserializer& s, std::optional<T>& obj)
351 {
352 bool b{};
353 s.stream() >> b;
354
355 if(b)
356 {
357 T val;
358 s.stream() >> val;
359 obj = val;
360 }
361 else
362 {
363 obj = std::nullopt;
364 }
365 SCORE_DEBUG_CHECK_DELIMITER2(s);
366 }
367};
368
369template <typename T>
370struct TSerializer<DataStream, QList<T>>
371{
372 static void readFrom(DataStream::Serializer& s, const QList<T>& obj) = delete;
373 static void writeTo(DataStream::Deserializer& s, QList<T>& obj) = delete;
374};
375
376template <typename T, std::size_t N>
377struct TSerializer<DataStream, std::array<T, N>>
378{
379 static void readFrom(DataStream::Serializer& s, const std::array<T, N>& arr)
380 {
381 for(std::size_t i = 0U; i < N; i++)
382 s.stream() << arr[i];
383
384 SCORE_DEBUG_INSERT_DELIMITER2(s);
385 }
386
387 static void writeTo(DataStream::Deserializer& s, std::array<T, N>& arr)
388 {
389 for(std::size_t i = 0U; i < N; i++)
390 s.stream() >> arr[i];
391
392 SCORE_DEBUG_CHECK_DELIMITER2(s);
393 }
394};
395
396#if defined(OSSIA_SMALL_VECTOR)
397template <typename T, std::size_t N>
398struct TSerializer<DataStream, ossia::small_vector<T, N>>
399{
400 static void readFrom(DataStream::Serializer& s, const ossia::small_vector<T, N>& arr)
401 {
402 s.stream() << (int32_t)arr.size();
403 for(std::size_t i = 0U; i < arr.size(); i++)
404 s.stream() << arr[i];
405
406 SCORE_DEBUG_INSERT_DELIMITER2(s);
407 }
408
409 static void writeTo(DataStream::Deserializer& s, ossia::small_vector<T, N>& arr)
410 {
411 int32_t sz;
412
413 s.stream() >> sz;
414 arr.resize(sz);
415 for(int32_t i = 0; i < sz; i++)
416 s.stream() >> arr[i];
417
418 SCORE_DEBUG_CHECK_DELIMITER2(s);
419 }
420};
421
422template <typename T, std::size_t N>
423struct TSerializer<DataStream, ossia::static_vector<T, N>>
424{
425 static void readFrom(DataStream::Serializer& s, const ossia::static_vector<T, N>& arr)
426 {
427 s.stream() << (int32_t)arr.size();
428 for(int32_t i = 0U; i < arr.size(); i++)
429 s.stream() << arr[i];
430
431 SCORE_DEBUG_INSERT_DELIMITER2(s);
432 }
433
434 static void writeTo(DataStream::Deserializer& s, ossia::static_vector<T, N>& arr)
435 {
436 int32_t sz;
437
438 s.stream() >> sz;
439 arr.resize(sz);
440 for(int32_t i = 0U; i < sz; i++)
441 s.stream() >> arr[i];
442
443 SCORE_DEBUG_CHECK_DELIMITER2(s);
444 }
445};
446
447template <typename T, std::size_t N>
448OSSIA_INLINE QDataStream&
449operator<<(QDataStream& stream, const ossia::small_vector<T, N>& obj)
450{
451 DataStreamReader reader{stream.device()};
452 reader.readFrom(obj);
453 return stream;
454}
455
456template <typename T, std::size_t N>
457OSSIA_INLINE QDataStream& operator>>(QDataStream& stream, ossia::small_vector<T, N>& obj)
458{
459 DataStreamWriter writer{stream.device()};
460 writer.writeTo(obj);
461 return stream;
462}
463
464#endif
465
466template <typename T, typename Alloc>
467 requires(
469 && !std::is_pointer_v<T> && !is_shared_ptr_v<T>)
470struct TSerializer<DataStream, std::vector<T, Alloc>>
471{
472 static void readFrom(DataStream::Serializer& s, const std::vector<T, Alloc>& vec)
473 {
474 s.stream() << (int32_t)vec.size();
475 for(const auto& elt : vec)
476 s.readFrom(elt);
477
478 SCORE_DEBUG_INSERT_DELIMITER2(s);
479 }
480
481 static void writeTo(DataStream::Deserializer& s, std::vector<T, Alloc>& vec)
482 {
483 int32_t n;
484 s.stream() >> n;
485
486 vec.clear();
487 vec.resize(n);
488 for(int32_t i = 0; i < n; i++)
489 {
490 s.writeTo(vec[i]);
491 }
492
493 SCORE_DEBUG_CHECK_DELIMITER2(s);
494 }
495};
496
497template <typename T, typename Alloc>
498 requires(
500 && !std::is_pointer_v<T> && !is_shared_ptr_v<T>)
501struct TSerializer<DataStream, boost::container::vector<T, Alloc>>
502{
503 static void
504 readFrom(DataStream::Serializer& s, const boost::container::vector<T, Alloc>& vec)
505 {
506 s.stream() << (int32_t)vec.size();
507 for(const auto& elt : vec)
508 s.readFrom(elt);
509
510 SCORE_DEBUG_INSERT_DELIMITER2(s);
511 }
512
513 static void
514 writeTo(DataStream::Deserializer& s, boost::container::vector<T, Alloc>& vec)
515 {
516 int32_t n;
517 s.stream() >> n;
518
519 vec.clear();
520 vec.resize(n);
521 for(int32_t i = 0; i < n; i++)
522 {
523 s.writeTo(vec[i]);
524 }
525
526 SCORE_DEBUG_CHECK_DELIMITER2(s);
527 }
528};
529
530template <>
531struct TSerializer<DataStream, std::vector<bool>>
532{
533 static void readFrom(DataStream::Serializer& s, const std::vector<bool>& vec)
534 {
535 s.stream() << (int32_t)vec.size();
536 for(bool elt : vec)
537 s.stream() << elt;
538
539 SCORE_DEBUG_INSERT_DELIMITER2(s);
540 }
541
542 static void writeTo(DataStream::Deserializer& s, std::vector<bool>& vec)
543 {
544 int32_t n;
545 s.stream() >> n;
546
547 vec.clear();
548 vec.resize(n);
549 for(int i = 0; i < n; i++)
550 {
551 bool b;
552 s.stream() >> b;
553 vec[i] = b;
554 }
555
556 SCORE_DEBUG_CHECK_DELIMITER2(s);
557 }
558};
559
560template <typename T, typename Alloc>
562struct TSerializer<DataStream, std::vector<T, Alloc>>
563{
564 static void readFrom(DataStream::Serializer& s, const std::vector<T, Alloc>& vec)
565 {
566 s.stream() << (int32_t)vec.size();
567 for(const auto& elt : vec)
568 s.stream() << elt;
569
570 SCORE_DEBUG_INSERT_DELIMITER2(s);
571 }
572
573 static void writeTo(DataStream::Deserializer& s, std::vector<T, Alloc>& vec)
574 {
575 int32_t n = 0;
576 s.stream() >> n;
577
578 vec.clear();
579 vec.resize(n);
580 for(int32_t i = 0; i < n; i++)
581 {
582 s.stream() >> vec[i];
583 }
584
585 SCORE_DEBUG_CHECK_DELIMITER2(s);
586 }
587};
588
589template <typename T, typename Alloc>
591struct TSerializer<DataStream, boost::container::vector<T, Alloc>>
592{
593 static void
594 readFrom(DataStream::Serializer& s, const boost::container::vector<T, Alloc>& vec)
595 {
596 s.stream() << (int32_t)vec.size();
597 for(const auto& elt : vec)
598 s.stream() << elt;
599
600 SCORE_DEBUG_INSERT_DELIMITER2(s);
601 }
602
603 static void
604 writeTo(DataStream::Deserializer& s, boost::container::vector<T, Alloc>& vec)
605 {
606 int32_t n = 0;
607 s.stream() >> n;
608
609 vec.clear();
610 vec.resize(n);
611 for(int32_t i = 0; i < n; i++)
612 {
613 s.stream() >> vec[i];
614 }
615
616 SCORE_DEBUG_CHECK_DELIMITER2(s);
617 }
618};
619
620template <typename T>
621struct TSerializer<DataStream, ossia::flat_set<T>>
622{
623 using type = ossia::flat_set<T>;
624 static void readFrom(DataStream::Serializer& s, const type& obj)
625 {
626 s.stream() << (int32_t)obj.size();
627 for(const auto& e : obj)
628 s.stream() << e;
629 }
630
631 static void writeTo(DataStream::Deserializer& s, type& obj)
632 {
633 int32_t n;
634 s.stream() >> n;
635 for(; n-- > 0;)
636 {
637 T val;
638 s.stream() >> val;
639 obj.insert(std::move(val));
640 }
641 }
642};
643
644template <typename T, typename U>
645struct TSerializer<DataStream, std::pair<T, U>>
646{
647 using type = std::pair<T, U>;
648 static void readFrom(DataStream::Serializer& s, const type& obj)
649 {
650 s.stream() << obj.first << obj.second;
651 }
652
653 static void writeTo(DataStream::Deserializer& s, type& obj)
654 {
655 s.stream() >> obj.first >> obj.second;
656 }
657};
658
659template <typename T>
660struct TSerializer<DataStream, std::shared_ptr<T>>
661{
662 using type = std::shared_ptr<T>;
663 static void readFrom(DataStream::Serializer& s, const type& obj) { SCORE_ABORT; }
664
665 static void writeTo(DataStream::Deserializer& s, type& obj) { SCORE_ABORT; }
666};
667
668Q_DECLARE_METATYPE(DataStreamReader*)
669Q_DECLARE_METATYPE(DataStreamWriter*)
670W_REGISTER_ARGTYPE(DataStreamReader*)
671W_REGISTER_ARGTYPE(DataStreamWriter*)
Definition VisitorInterface.hpp:10
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
void readFrom(const score::Entity< T > &obj)
Called by code that wants to serialize.
Definition DataStreamVisitor.hpp:53
void readFrom(const T &obj)
Definition DataStreamVisitor.hpp:67
void insertDelimiter()
insertDelimiter
Definition DataStreamVisitor.hpp:156
void read(const T &)
Definition DataStreamVisitor.hpp:202
The IdentifiedObject class.
Definition IdentifiedObject.hpp:19
The id_base_t class.
Definition Identifier.hpp:57
Definition ApplicationComponents.hpp:68
Base for complex model objects.
Definition EntityBase.hpp:24
Definition VisitorTags.hpp:10
Definition VisitorTags.hpp:18
Definition VisitorTags.hpp:14
Definition DataStreamHelpers.hpp:87
Base toolkit upon which the software is built.
Definition Application.cpp:90
STL namespace.
Definition DataStreamHelpers.hpp:99
Definition DataStreamHelpers.hpp:103
Definition VisitorInterface.hpp:13
The VisitorVariant struct.
Definition VisitorInterface.hpp:26
Definition VisitorTags.hpp:29
Definition VisitorTags.hpp:152
Definition VisitorTags.hpp:24