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 
17 template <typename model>
18 class IdentifiedObject;
19 namespace score
20 {
21 template <typename model>
22 class Entity;
23 class ApplicationComponents;
24 }
25 
26 class SCORE_LIB_BASE_EXPORT DataStreamReader : public AbstractVisitor
27 {
28 public:
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  {
61  TSerializer<DataStream, IdentifiedObject<T>>::readFrom(*this, obj);
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(
84  identified_object<T> && !identified_entity<T> && !abstract_base<T>
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(
113  identified_object<T> && !identified_entity<T> && abstract_base<T>
114  && !is_custom_serialized<T>::value)
115  {
116  readFromAbstract(obj, [](DataStreamReader& sub, const T& obj) {
117  TSerializer<DataStream, IdentifiedObject<T>>::readFrom(sub, 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 
165 private:
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;
173  DataStream::Serializer sub{&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 
196 public:
197  const score::ApplicationComponents& components;
198  DataStreamInput m_stream{m_stream_impl};
199 };
200 
201 class SCORE_LIB_BASE_EXPORT DataStreamWriter : public AbstractVisitor
202 {
203 public:
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 
268 private:
269  QDataStream m_stream_impl;
270 };
271 
272 template <typename T>
273  requires(!std::is_enum_v<T>)
274 DataStreamInput& operator<<(DataStreamInput& s, const T& obj)
275 {
276  DataStreamReader reader{s.stream.device()};
277  reader.readFrom(obj);
278  return s;
279 }
280 
281 template <typename T>
282  requires(!std::is_enum_v<T>)
283 DataStreamOutput& operator>>(DataStreamOutput& s, T& obj)
284 {
285  DataStreamWriter writer{s.stream.device()};
286  writer.writeTo(obj);
287  return s;
288 }
289 
290 template <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 
308 template <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 
336 template <typename T>
337 struct 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 
369 template <typename T>
370 struct 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 
376 template <typename T, std::size_t N>
377 struct 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)
397 template <typename T, std::size_t N>
398 struct 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 
422 template <typename T, std::size_t N>
423 struct 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 
447 template <typename T, std::size_t N>
448 OSSIA_INLINE QDataStream&
449 operator<<(QDataStream& stream, const ossia::small_vector<T, N>& obj)
450 {
451  DataStreamReader reader{stream.device()};
452  reader.readFrom(obj);
453  return stream;
454 }
455 
456 template <typename T, std::size_t N>
457 OSSIA_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 
466 template <typename T, typename Alloc>
467  requires(
468  !is_QDataStreamSerializable<typename std::vector<T, Alloc>::value_type>
469  && !std::is_pointer_v<T> && !is_shared_ptr_v<T>)
470 struct 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 
497 template <typename T, typename Alloc>
498  requires(
499  !is_QDataStreamSerializable<typename std::vector<T, Alloc>::value_type>
500  && !std::is_pointer_v<T> && !is_shared_ptr_v<T>)
501 struct 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 
530 template <>
531 struct 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 
560 template <typename T, typename Alloc>
561  requires(is_QDataStreamSerializable<typename std::vector<T, Alloc>::value_type>)
562 struct 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 
589 template <typename T, typename Alloc>
590  requires(is_QDataStreamSerializable<typename std::vector<T, Alloc>::value_type>)
591 struct 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 
620 template <typename T>
621 struct 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 
644 template <typename T, typename U>
645 struct 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 
659 template <typename T>
660 struct 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 
668 Q_DECLARE_METATYPE(DataStreamReader*)
669 Q_DECLARE_METATYPE(DataStreamWriter*)
670 W_REGISTER_ARGTYPE(DataStreamReader*)
671 W_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
Base toolkit upon which the software is built.
Definition: Application.cpp:90
auto marshall(const Object &obj)
marshall Serializes a single object
Definition: VisitorCommon.hpp:129
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