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 boost::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) { boost::pfr::for_each_field(f, *this); }
120
121 template <typename F>
122 requires(std::is_arithmetic_v<F>)
123 void operator()(F& f)
124 {
125 r.stream().stream >> f;
126 }
127
128 template <typename F>
129 requires avnd::list_ish<F>
130 void operator()(F& f)
131 {
132 int64_t sz;
133 r.stream().stream >> sz;
134 SCORE_ASSERT(sz >= 0);
135 for(int64_t i = 0; i < sz; i++)
136 {
137 using type = typename F::value_type;
138 type val;
139 (*this)(val);
140 f.push_back(std::move(val));
141 }
142 }
143
144 template <std::size_t I, typename... Args>
145 bool write_variant(std::variant<Args...>& f)
146 {
147 auto& elt = f.template emplace<I>();
148 (*this)(elt);
149 return true;
150 }
151
152 template <typename... Args>
153 void operator()(std::variant<Args...>& f)
154 {
155 int index{};
156 r.stream().stream >> index;
157
158 SCORE_ASSERT(index >= 0);
159 SCORE_ASSERT(index < sizeof...(Args));
160 [&]<std::size_t... I>(std::index_sequence<I...>)
161 {
162 (((index == I) && write_variant<I>(f)) || ...);
163 }
164 (std::make_index_sequence<sizeof...(Args)>{});
165 }
166
167 void operator()(auto& f) { r.stream() >> f; }
168};
169
171{
172 QByteArray& mess;
173
174 // Case for zero-argument message bus (e.g. just a ping)
175 void operator()() { }
176
177 template <typename T>
178 requires std::is_trivial_v<T>
179 void operator()(T& msg)
180 {
181 // Here we can just do a memcpy
182 memcpy(&msg, mess.data(), mess.size());
183 }
184 template <typename T>
185 requires(
186 !std::is_trivial_v<T> && avnd::relocatable<T>
187 && alignof(T) <= alignof(max_align_t))
188 void operator()(T& msg)
189 {
190 auto src = reinterpret_cast<T*>(mess.data());
191 msg = std::move(*src);
192 std::destroy_at(src);
193 }
194
195 template <typename T>
196 requires(
197 !std::is_trivial_v<T>
198 && (!avnd::relocatable<T> || (alignof(T) > alignof(max_align_t))))
199 void operator()(T& msg)
200 {
201 // Deserialize... :D
202
203 DataStreamWriter str{mess};
204 Deserializer{str}(msg);
205 }
206};
207
208}
Definition DataStreamVisitor.hpp:27
Definition DataStreamVisitor.hpp:202
Definition Factories.hpp:19
Definition MessageBus.hpp:114
Definition MessageBus.hpp:171
Definition MessageBus.hpp:44
Definition MessageBus.hpp:13