Loading...
Searching...
No Matches
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
9namespace oscr
10{
11
13{
15
16 template <typename F>
17 void operator()(const F& f)
18 {
19 if constexpr(std::is_arithmetic_v<F>)
20 r.stream().stream << f;
21 else if constexpr(std::is_aggregate_v<F>)
22 avnd::pfr::for_each_field(f, *this);
23 else if constexpr(avnd::list_ish<F>)
24 {
25 r.stream().stream << (int64_t)std::ssize(f);
26 for(const auto& val : f)
27 {
28 (*this)(val);
29 }
30 }
31 else
32 r.stream() << f;
33 }
34
35 template <typename... Args>
36 void operator()(const std::variant<Args...>& f)
37 {
38 r.stream().stream << (int)f.index();
39 std::visit(*this, f);
40 }
41};
42
44{
45 std::function<void(QByteArray)>& bus;
46
47 // Case for zero-argument message bus (e.g. just a ping)
48 void operator()() { this->bus(QByteArray{}); }
49
50 template <typename T>
51 requires std::is_trivial_v<T>
52 void operator()(const T& msg)
53 {
54 // Here we can just do a memcpy
55 this->bus(QByteArray((const char*)&msg, sizeof(msg)));
56 }
57
58 template <typename T>
59 requires(
60 !std::is_trivial_v<T> && avnd::relocatable<T>
61 && alignof(T) <= alignof(max_align_t))
62 void operator()(const T& msg)
63 {
64 QByteArray b(msg.size(), Qt::Uninitialized);
65 auto dst = reinterpret_cast<T*>(b.data());
66 new(dst) T(msg);
67
68 this->bus(std::move(b));
69 }
70
71 template <typename T>
72 requires(
73 !std::is_trivial_v<T> && avnd::relocatable<T>
74 && alignof(T) <= alignof(max_align_t))
75 void operator()(T&& msg)
76 {
77 QByteArray b(sizeof(msg), Qt::Uninitialized);
78 auto dst = reinterpret_cast<T*>(b.data());
79 std::construct_at(dst, std::move(msg));
80
81 this->bus(std::move(b));
82 }
83
84 template <typename T>
85 requires(
86 !std::is_trivial_v<T>
87 && (!avnd::relocatable<T> || (alignof(T) > alignof(max_align_t))))
88 void operator()(const T& msg)
89 {
90 // Here we gotta serialize... :D
91 QByteArray buf;
92
93 DataStreamReader str{&buf};
94 Serializer{str}(msg);
95
96 this->bus(std::move(buf));
97 }
98
99 template <typename T>
100 void operator()(const std::shared_ptr<T>& msg)
101 {
102 SCORE_ASSERT(msg);
103 return (*this)(std::move(*msg));
104 }
105 template <typename T>
106 void operator()(std::unique_ptr<T> msg)
107 {
108 SCORE_ASSERT(msg);
109 return (*this)(std::move(*msg));
110 }
111};
112
114{
116
117 template <typename F>
118 requires std::is_aggregate_v<F>
119 void operator()(F& f)
120 {
121 avnd::pfr::for_each_field(f, *this);
122 }
123
124 template <typename F>
125 requires(std::is_arithmetic_v<F>)
126 void operator()(F& f)
127 {
128 r.stream().stream >> f;
129 }
130
131 template <typename F>
132 requires avnd::list_ish<F>
133 void operator()(F& f)
134 {
135 int64_t sz;
136 r.stream().stream >> sz;
137 SCORE_ASSERT(sz >= 0);
138 for(int64_t i = 0; i < sz; i++)
139 {
140 using type = typename F::value_type;
141 type val;
142 (*this)(val);
143 f.push_back(std::move(val));
144 }
145 }
146
147 template <std::size_t I, typename... Args>
148 bool write_variant(std::variant<Args...>& f)
149 {
150 auto& elt = f.template emplace<I>();
151 (*this)(elt);
152 return true;
153 }
154
155 template <typename... Args>
156 void operator()(std::variant<Args...>& f)
157 {
158 int index{};
159 r.stream().stream >> index;
160
161 SCORE_ASSERT(index >= 0);
162 SCORE_ASSERT(index < sizeof...(Args));
163 [&]<std::size_t... I>(std::index_sequence<I...>)
164 {
165 (((index == I) && write_variant<I>(f)) || ...);
166 }
167 (std::make_index_sequence<sizeof...(Args)>{});
168 }
169
170 void operator()(auto& f) { r.stream() >> f; }
171};
172
174{
175 QByteArray& mess;
176
177 // Case for zero-argument message bus (e.g. just a ping)
178 void operator()() { }
179
180 template <typename T>
181 requires std::is_trivial_v<T>
182 void operator()(T& msg)
183 {
184 // Here we can just do a memcpy
185 memcpy(&msg, mess.data(), mess.size());
186 }
187 template <typename T>
188 requires(
189 !std::is_trivial_v<T> && avnd::relocatable<T>
190 && alignof(T) <= alignof(max_align_t))
191 void operator()(T& msg)
192 {
193 auto src = reinterpret_cast<T*>(mess.data());
194 msg = std::move(*src);
195 std::destroy_at(src);
196 }
197
198 template <typename T>
199 requires(
200 !std::is_trivial_v<T>
201 && (!avnd::relocatable<T> || (alignof(T) > alignof(max_align_t))))
202 void operator()(T& msg)
203 {
204 // Deserialize... :D
205
206 DataStreamWriter str{mess};
207 Deserializer{str}(msg);
208 }
209};
210
211}
Definition DataStreamVisitor.hpp:27
Definition DataStreamVisitor.hpp:202
Definition Factories.hpp:19
Definition MessageBus.hpp:114
Definition MessageBus.hpp:174
Definition MessageBus.hpp:44
Definition MessageBus.hpp:13