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