FastEngine 0.9.4
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
network_manager.inl
1/*
2 * Copyright 2025 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17namespace fge::net
18{
19
20namespace rules
21{
22template<class TValue>
23constexpr ChainedArguments<TValue>::ChainedArguments(Packet const& pck, TValue* existingValue) :
24 g_pck(&pck),
25 g_value(existingValue == nullptr ? Value{std::in_place_type<TValue>} : Value{existingValue}),
26 g_error(pck.isValid() ? Error{}
27 : Error{Error::Types::ERR_ALREADY_INVALID, pck.getReadPos(), "already invalid packet",
28 __func__})
29{}
30template<class TValue>
31constexpr ChainedArguments<TValue>::ChainedArguments(Packet const& pck, Error&& err, TValue* existingValue) :
32 g_pck(&pck),
33 g_value(existingValue == nullptr ? Value{std::in_place_type<TValue>} : Value{existingValue}),
34 g_error(std::move(err))
35{}
36
37template<class TValue>
39{
40 auto* value = std::holds_alternative<TValue>(this->g_value) ? &std::get<TValue>(this->g_value)
41 : std::get<TValue*>(this->g_value);
42 *this->g_pck >> *value;
43 if (this->g_pck->isValid())
44 {
45 return value;
46 }
47 this->g_error =
48 net::Error{net::Error::Types::ERR_EXTRACT, this->g_pck->getReadPos(), "extraction failed", __func__};
49 return nullptr;
50}
51template<class TValue>
52template<class TPeek>
53constexpr std::optional<TPeek> ChainedArguments<TValue>::peek()
54{
55 auto startReadPos = this->g_pck->getReadPos();
56
57 TPeek value{};
58 *this->g_pck >> value;
59
60 if (this->g_pck->isValid())
61 {
62 this->g_pck->setReadPos(startReadPos);
63 return value;
64 }
65
66 this->g_error = net::Error{net::Error::Types::ERR_EXTRACT, this->g_pck->getReadPos(), "peek failed", __func__};
67 return std::nullopt;
68}
69
70template<class TValue>
71constexpr ChainedArguments<TValue>::operator Packet const&() const
72{
73 return *this->g_pck;
74}
75template<class TValue>
76constexpr Packet const& ChainedArguments<TValue>::packet() const
77{
78 return *this->g_pck;
79}
80template<class TValue>
81constexpr TValue const& ChainedArguments<TValue>::value() const
82{
83 return std::holds_alternative<TValue>(this->g_value) ? std::get<TValue>(this->g_value)
84 : *std::get<TValue*>(this->g_value);
85}
86template<class TValue>
87constexpr TValue& ChainedArguments<TValue>::value()
88{
89 return std::holds_alternative<TValue>(this->g_value) ? std::get<TValue>(this->g_value)
90 : *std::get<TValue*>(this->g_value);
91}
92
93template<class TValue>
94template<class TInvokable>
95constexpr typename std::invoke_result_t<TInvokable, ChainedArguments<TValue>&>
97{
98 if (this->g_pck->isValid())
99 {
100 return std::invoke(std::forward<TInvokable>(f), *this);
101 }
102 return {*this->g_pck, std::move(this->g_error), nullptr};
103}
104template<class TValue>
105template<class TInvokable, class TIndex>
107ChainedArguments<TValue>::and_for_each(TIndex iStart, TIndex iEnd, TIndex iIncrement, TInvokable&& f)
108{
109 if (!this->g_pck->isValid())
110 {
111 return *this;
112 }
113
114 for (; iStart != iEnd; iStart += iIncrement)
115 {
116 std::optional<Error> err =
117 std::invoke(std::forward<TInvokable>(f), const_cast<ChainedArguments<TValue> const&>(*this), iStart);
118
119 if (err)
120 {
121 this->invalidate(std::move(err.value()));
122 return *this;
123 }
124 }
125 return *this;
126}
127template<class TValue>
128template<class TInvokable, class TIndex>
130ChainedArguments<TValue>::and_for_each(TIndex iStart, TIndex iIncrement, TInvokable&& f)
131{
132 if (!this->g_pck->isValid())
133 {
134 return *this;
135 }
136
137 auto& value = this->value();
138
139 for (; iStart != value; iStart += iIncrement)
140 {
141 std::optional<Error> err =
142 std::invoke(std::forward<TInvokable>(f), const_cast<ChainedArguments<TValue> const&>(*this), iStart);
143
144 if (err)
145 {
146 this->invalidate(std::move(err.value()));
147 return *this;
148 }
149 }
150 return *this;
151}
152template<class TValue>
153template<class TInvokable>
154constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::and_for_each(TInvokable&& f)
155{
156 if (!this->g_pck->isValid())
157 {
158 return *this;
159 }
160
161 auto& value = this->value();
162
163 for (TValue iIndex = 0; iIndex != value; ++iIndex)
164 {
165 std::optional<Error> err =
166 std::invoke(std::forward<TInvokable>(f), const_cast<ChainedArguments<TValue> const&>(*this), iIndex);
167
168 if (err)
169 {
170 this->invalidate(std::move(err.value()));
171 return *this;
172 }
173 }
174 return *this;
175}
176template<class TValue>
177template<class TInvokable>
178constexpr std::optional<Error> ChainedArguments<TValue>::on_error(TInvokable&& f)
179{
180 if (!this->g_pck->isValid())
181 {
182 std::invoke(std::forward<TInvokable>(f), *this);
183 return this->g_error;
184 }
185 return std::nullopt;
186}
187template<class TValue>
188constexpr std::optional<Error> ChainedArguments<TValue>::end()
189{
190 return this->g_pck->isValid() ? std::nullopt : std::optional<Error>{std::move(this->g_error)};
191}
192template<class TValue>
193constexpr std::optional<Error> ChainedArguments<TValue>::final()
194{
195 return this->g_pck->isValid() && this->g_pck->endReached() ? std::nullopt
196 : std::optional<Error>{std::move(this->g_error)};
197}
198template<class TValue>
199constexpr std::optional<Error> ChainedArguments<TValue>::skip() const
200{
201 return std::nullopt;
202}
203template<class TValue>
204constexpr std::optional<Error> ChainedArguments<TValue>::stop(char const* error, char const* function) const
205{
206 return Error{Error::Types::ERR_EXTRACT, this->g_pck->getReadPos(), error, function};
207}
208
209template<class TValue>
210constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::apply(TValue& value)
211{
212 if (this->g_pck->isValid())
213 {
214 auto* extractedValue = std::holds_alternative<TValue>(this->g_value) ? &std::get<TValue>(this->g_value)
215 : std::get<TValue*>(this->g_value);
216 if constexpr (std::is_move_assignable_v<TValue>)
217 {
218 value = std::move(*extractedValue);
219 }
220 else
221 {
222 value = *extractedValue;
223 }
224 }
225 return *this;
226}
227template<class TValue>
228template<class TInvokable>
229constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::apply(TInvokable&& f)
230{
231 if (this->g_pck->isValid())
232 {
233 auto* extractedValue = std::holds_alternative<TValue>(this->g_value) ? &std::get<TValue>(this->g_value)
234 : std::get<TValue*>(this->g_value);
235 std::invoke(std::forward<TInvokable>(f), const_cast<TValue&>(*extractedValue));
236 }
237 return *this;
238}
239
240template<class TValue>
241constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::setError(Error&& err)
242{
243 this->g_error = std::move(err);
244 return *this;
245}
246template<class TValue>
247constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::invalidate(Error&& err)
248{
249 this->g_pck->invalidate();
250 this->g_error = std::move(err);
251 return *this;
252}
253template<class TValue>
254constexpr ChainedArguments<TValue>& ChainedArguments<TValue>::invalidate(char const* error, char const* function)
255{
256 this->g_pck->invalidate();
257 this->g_error = Error{Error::Types::ERR_EXTRACT, this->g_pck->getReadPos(), error, function};
258 return *this;
259}
260
261template<class TValue, ROutputs TOutput>
262constexpr ChainedArguments<TValue> RRange(TValue const& min, TValue const& max, ChainedArguments<TValue>&& args)
263{
264 if (args.packet().isValid())
265 {
266 auto* val = args.extract();
267 if (val != nullptr)
268 {
269 if (!((*val >= min && *val <= max) ^ static_cast<bool>(TOutput)))
270 {
271 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
272 }
273 }
274 }
275 return args;
276}
277
278template<class TValue>
280{
281 if (args.packet().isValid())
282 {
283 auto* val = args.extract();
284 if (val == nullptr)
285 {
286 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
287 }
288 }
289 return args;
290}
291
292template<class TValue, ROutputs TOutput>
294{
295 if (args.packet().isValid())
296 {
297 auto* val = args.extract();
298 if (val != nullptr)
299 {
300 if (!((*val == a) ^ static_cast<bool>(TOutput)))
301 {
302 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
303 }
304 }
305 }
306 return args;
307}
308
309template<class TValue, ROutputs TOutput>
311{
312 if (args.packet().isValid())
313 {
314 auto* val = args.extract();
315 if (val != nullptr)
316 {
317 if (!((*val < less) ^ static_cast<bool>(TOutput)))
318 {
319 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
320 }
321 }
322 }
323 return args;
324}
325
326template<class TValue, ROutputs TOutput>
328{
329 if (args.packet().isValid())
330 {
331 auto* val = args.extract();
332 if (val != nullptr)
333 {
334 if (!((*val <= less) ^ static_cast<bool>(TOutput)))
335 {
336 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
337 }
338 }
339 }
340 return args;
341}
342
343template<class TValue, ROutputs TOutput>
344constexpr ChainedArguments<TValue> RSizeRange(SizeType min, SizeType max, ChainedArguments<TValue>&& args)
345{
346 if (args.packet().isValid())
347 {
348 auto size = args.template peek<SizeType>();
349 if (size)
350 {
351 if (!((size >= min && size <= max) ^ static_cast<bool>(TOutput)))
352 {
353 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
354 }
355 }
356 }
357 return args;
358}
359
360template<class TValue, ROutputs TOutput>
362{
363 if (args.packet().isValid())
364 {
365 auto size = args.template peek<SizeType>();
366 if (size)
367 {
368 if (!((size == a) ^ static_cast<bool>(TOutput)))
369 {
370 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
371 }
372 }
373 }
374 return args;
375}
376
377template<class TValue, ROutputs TOutput>
379{
380 if (args.packet().isValid())
381 {
382 auto* val = args.extract();
383 if (val != nullptr)
384 {
385 if (!(fge::string::IsValidUtf8String(val) ^ static_cast<bool>(TOutput)))
386 {
387 args.invalidate(Error{Error::Types::ERR_RULE, args.packet().getReadPos(), "rule failed", __func__});
388 }
389 }
390 }
391 return args;
392}
393
394} // namespace rules
395
396} // namespace fge::net
Definition C_packet.hpp:52
This is a wrapper around a Packet and a value for safe extraction.
Definition network_manager.hpp:74
constexpr ChainedArguments< TValue > & setError(Error &&err)
Set the error.
Definition network_manager.inl:241
constexpr std::optional< TPeek > peek()
Peek without changing the read position a copy of value.
Definition network_manager.inl:53
constexpr std::optional< Error > skip() const
Helper to "continue" in a and_for_each() loop without returning an error.
Definition network_manager.inl:199
constexpr std::optional< Error > final()
End the chain by doing a last validity check on the packet.
Definition network_manager.inl:193
constexpr ChainedArguments< TValue > & apply(TValue &value)
Apply the extracted value to the provided reference.
Definition network_manager.inl:210
constexpr TValue * extract()
Extract and verify the value from the packet.
Definition network_manager.inl:38
constexpr std::invoke_result_t< TInvokable, ChainedArguments< TValue > & > and_then(TInvokable &&f)
Chain up some code after a successful extraction.
Definition network_manager.inl:96
constexpr ChainedArguments< TValue > & and_for_each(TIndex iStart, TIndex iEnd, TIndex iIncrement, TInvokable &&f)
Chain up some code in a for loop after a successful extraction.
Definition network_manager.inl:107
constexpr std::optional< Error > stop(char const *error, char const *function) const
Helper to "break" in a and_for_each() loop with a custom error.
Definition network_manager.inl:204
constexpr std::optional< Error > on_error(TInvokable &&f)
Chain up some code after an unsuccessful extraction.
Definition network_manager.inl:178
constexpr std::optional< Error > end()
End the chain by doing a last validity check on the packet.
Definition network_manager.inl:188
constexpr ChainedArguments< TValue > & invalidate(Error &&err)
Invalidate the packet and set the error.
Definition network_manager.inl:247
FGE_API bool IsValidUtf8String(std::string const &str)
Check if the provided string has valid utf8 encoded chars.
constexpr ChainedArguments< TValue > RRange(TValue const &min, TValue const &max, ChainedArguments< TValue > &&args)
Range rule, check if the value is in the min/max range.
Definition network_manager.inl:262
constexpr ChainedArguments< TValue > RMustValidUtf8(ChainedArguments< TValue > &&args)
Check if the extracted string is a valid UTF8 string.
Definition network_manager.inl:378
constexpr ChainedArguments< TValue > RStrictLess(TValue less, ChainedArguments< TValue > &&args)
Strict less rule, check if the value is strictly lesser than the provided one.
Definition network_manager.inl:310
constexpr ChainedArguments< TValue > RMustEqual(TValue const &a, ChainedArguments< TValue > &&args)
Must equal rule, check if the value is equal to the provided one.
Definition network_manager.inl:293
constexpr ChainedArguments< TValue > RSizeMustEqual(SizeType a, ChainedArguments< TValue > &&args)
Size must equal rule, check if the size is equal to the provided one.
Definition network_manager.inl:361
constexpr ChainedArguments< TValue > RSizeRange(SizeType min, SizeType max, ChainedArguments< TValue > &&args)
Size range rule, check if the size is in the min/max range.
Definition network_manager.inl:344
constexpr ChainedArguments< TValue > RValid(ChainedArguments< TValue > &&args)
Valid rule, check if the value is correctly extracted.
Definition network_manager.inl:279
constexpr ChainedArguments< TValue > RLess(TValue less, ChainedArguments< TValue > &&args)
Less rule, check if the value is lesser than the provided one.
Definition network_manager.inl:327
Definition C_error.hpp:28