MessageBus.hpp
1 #pragma once
3 
4 #include <boost/pfr.hpp>
5 
6 #include <avnd/common/tag.hpp>
7 #include <avnd/concepts/message_bus.hpp>
8 
9 namespace oscr
10 {
11 
12 struct Serializer
13 {
15 
16  template <typename F>
17  requires std::is_aggregate_v<F>
18  void operator()(const F& f) { boost::pfr::for_each_field(f, *this); }
19 
20  template <typename F>
21  requires(std::is_arithmetic_v<F>) void operator()(const F& f)
22  {
23  r.stream().stream << f;
24  }
25 
26  template <typename... Args>
27  void operator()(const std::variant<Args...>& f)
28  {
29  r.stream() << (int)f.index();
30  std::visit([&](const auto& arg) { r.stream() << arg; }, f);
31  }
32 
33  void operator()(const auto& f) { r.stream() << f; }
34 };
35 
37 {
38  std::function<void(QByteArray)>& bus;
39 
40  template <typename T>
41  requires std::is_trivial_v<T>
42  void operator()(const T& msg)
43  {
44  // Here we can just do a memcpy
45  this->bus(QByteArray((const char*)&msg, sizeof(msg)));
46  }
47 
48  template <typename T>
49  requires(!std::is_trivial_v<T> && avnd::relocatable<T>)
50  void operator()(const T& msg)
51  {
52  QByteArray b(msg.size(), Qt::Uninitialized);
53  auto dst = reinterpret_cast<T*>(b.data());
54  new(dst) T(msg);
55 
56  this->bus(std::move(b));
57  }
58 
59  template <typename T>
60  requires(!std::is_trivial_v<T> && avnd::relocatable<T>)
61  void operator()(T&& msg)
62  {
63  QByteArray b(sizeof(msg), Qt::Uninitialized);
64  auto dst = reinterpret_cast<T*>(b.data());
65  std::construct_at(dst, std::move(msg));
66 
67  this->bus(std::move(b));
68  }
69 
70  template <typename T>
71  requires(!std::is_trivial_v<T> && !avnd::relocatable<T>)
72  void operator()(const T& msg)
73  {
74  // Here we gotta serialize... :D
75  QByteArray buf;
76 
77  DataStreamReader str{&buf};
78  Serializer{str}(msg);
79 
80  this->bus(std::move(buf));
81  }
82 
83  template <typename T>
84  void operator()(const std::shared_ptr<T>& msg)
85  {
86  SCORE_ASSERT(msg);
87  return (*this)(std::move(*msg));
88  }
89  template <typename T>
90  void operator()(std::unique_ptr<T> msg)
91  {
92  SCORE_ASSERT(msg);
93  return (*this)(std::move(*msg));
94  }
95 };
96 
98 {
100 
101  template <typename F>
102  requires std::is_aggregate_v<F>
103  void operator()(F& f) { boost::pfr::for_each_field(f, *this); }
104 
105  template <typename F>
106  requires(std::is_arithmetic_v<F>) void operator()(F& f) { r.stream().stream >> f; }
107 
108  template <std::size_t I, typename... Args>
109  bool write_variant(std::variant<Args...>& f)
110  {
111  auto& elt = f.template emplace<I>();
112  r.stream() >> elt;
113  return true;
114  }
115 
116  template <typename... Args>
117  void operator()(std::variant<Args...>& f)
118  {
119  int index{};
120  r.stream() >> index;
121 
122  [&]<std::size_t... I>(std::index_sequence<I...>)
123  {
124  (((index == I) && write_variant<I>(f)) || ...);
125  }
126  (std::make_index_sequence<sizeof...(Args)>{});
127  }
128 
129  void operator()(auto& f) { r.stream() >> f; }
130 };
131 
133 {
134  QByteArray& mess;
135 
136  template <typename T>
137  requires std::is_trivial_v<T>
138  void operator()(T& msg)
139  {
140  // Here we can just do a memcpy
141  memcpy(&msg, mess.data(), mess.size());
142  }
143  template <typename T>
144  requires(!std::is_trivial_v<T> && avnd::relocatable<T>)
145  void operator()(T& msg)
146  {
147  auto src = reinterpret_cast<T*>(mess.data());
148  msg = std::move(*src);
149  std::destroy_at(src);
150  }
151 
152  template <typename T>
153  requires(!std::is_trivial_v<T> && !avnd::relocatable<T>)
154  void operator()(T& msg)
155  {
156  // Deserialize... :D
157 
158  DataStreamWriter str{mess};
159  Deserializer{str}(msg);
160  }
161 };
162 
163 }
Definition: DataStreamVisitor.hpp:27
Definition: DataStreamVisitor.hpp:202
Definition: Factories.hpp:19
Definition: MessageBus.hpp:98
Definition: MessageBus.hpp:133
Definition: MessageBus.hpp:37
Definition: MessageBus.hpp:13