GMP 0.4.0
Generative Metaprogramming library for C++
Loading...
Searching...
No Matches
deserializer.hpp
Go to the documentation of this file.
1// ___ __ __ ___
2// / __| \/ | _ \ GMP(Generative Metaprogramming)
3// | (_ | |\/| | _/ version 0.4.0
4// \___|_| |_|_| https://github.com/lkimuk/gmp
5//
6// SPDX-FileCopyrightText: 2023-2026 Miles Li <https://www.cppmore.com/>
7// SPDX-License-Identifier: MIT
8//
9// This file is part of the GMP (Generative Metaprogramming) library.
10// Full project source: https://github.com/lkimuk/gmp
11
12#ifndef GMP_SERIALIZATION_DESERIALIZER_HPP_
13#define GMP_SERIALIZATION_DESERIALIZER_HPP_
14
15#include <array>
16#include <cmath>
17#include <concepts>
18#include <limits>
19#include <optional>
20#include <string>
21#include <tuple>
22#include <type_traits>
23#include <utility>
24
25#include <gmp/meta/meta.hpp>
27#include <gmp/serialization/detail/schema.hpp>
28#include <gmp/serialization/detail/std_types.hpp>
30
31namespace gmp {
32
33template <typename Reader>
36public:
39
41 return options_;
42 }
43
44 template <typename T> serialization_result<T> decode() {
45 return decode_value<T>(reader_);
46 }
47
48private:
49 template <typename R> class decoder_archive {
50 public:
51 decoder_archive(basic_deserializer &owner, const R &reader) : owner_(owner), reader_(reader) {}
52
53 template <typename T> serialization_result<T> decode() {
54 return owner_.template decode_value<T>(reader_);
55 }
56
57 template <typename T> serialization_result<T> decode(const R &reader) {
58 return owner_.template decode_value<T>(reader);
59 }
60
61 const deserialization_options &options() const noexcept {
62 return owner_.options();
63 }
64
66 return reader_.kind();
67 }
68
69 std::size_t size() const noexcept {
70 return reader_.size();
71 }
72
73 bool read_bool() const {
74 return reader_.read_bool();
75 }
76
77 std::int64_t read_signed() const {
78 return reader_.read_signed();
79 }
80
81 std::uint64_t read_unsigned() const {
82 return reader_.read_unsigned();
83 }
84
85 double read_floating() const {
86 return reader_.read_floating();
87 }
88
89 std::string_view read_string() const {
90 return reader_.read_string();
91 }
92
93 auto element(std::size_t index) const {
94 return reader_.element(index);
95 }
96
97 auto member(std::size_t index) const {
98 return reader_.member(index);
99 }
100
101 private:
102 basic_deserializer &owner_;
103 const R &reader_;
104 };
105
106 class depth_guard {
107 public:
108 explicit depth_guard(basic_deserializer &s) : s_(s), ok_(s.depth_ < s.options_.max_depth) {
109 if (ok_) {
110 ++s_.depth_;
111 }
112 }
113
114 ~depth_guard() {
115 if (ok_) {
116 --s_.depth_;
117 }
118 }
119
120 explicit operator bool() const noexcept {
121 return ok_;
122 }
123
124 private:
125 basic_deserializer &s_;
126 bool ok_;
127 };
128
129 template <typename T> serialization_result<T> decode_value(const Reader &r) {
131 if (!result && result.error().offset == serialization_error::unknown_offset) {
132 if constexpr (requires { r.value().source_offset(); }) {
133 result.error().offset = r.value().source_offset();
134 }
135 }
136 return result;
137 }
138
139 template <typename T> serialization_result<T> decode_value_impl(const Reader &r) {
140 using U = detail::unqualified_t<T>;
141 if constexpr (requires(decoder_archive<Reader> & a) {
142 {
143 serialization_traits<U>::deserialize(a, type_tag<U>{})
144 } -> std::same_as<serialization_result<U>>;
145 }) {
147 return serialization_traits<U>::deserialize(archive, type_tag<U>{});
148 } else if constexpr (std::same_as<U, std::nullptr_t> || std::same_as<U, std::monostate>) {
149 if (r.kind() != serialization_kind::null) {
151 }
152 return U{};
153 } else if constexpr (std::same_as<U, bool>) {
154 if (r.kind() != serialization_kind::boolean) {
156 }
157 return r.read_bool();
158 } else if constexpr (std::is_integral_v<U> && std::is_signed_v<U>) {
160 const auto n = r.read_signed();
161 if (n < static_cast<std::int64_t>(std::numeric_limits<U>::min()) ||
162 n > static_cast<std::int64_t>(std::numeric_limits<U>::max())) {
164 "integer value is out of range");
165 }
166 return static_cast<U>(n);
167 }
169 const auto n = r.read_unsigned();
170 if (n > static_cast<std::uint64_t>(std::numeric_limits<U>::max())) {
172 "integer value is out of range");
173 }
174 return static_cast<U>(n);
175 }
176 return make_serialization_error(serialization_errc::type_mismatch, "expected signed integer");
177 } else if constexpr (std::is_integral_v<U> && std::is_unsigned_v<U>) {
179 const auto n = r.read_unsigned();
180 if (n > static_cast<std::uint64_t>(std::numeric_limits<U>::max())) {
182 "integer value is out of range");
183 }
184 return static_cast<U>(n);
185 }
187 const auto n = r.read_signed();
188 if (n < 0 || static_cast<std::uint64_t>(n) >
189 static_cast<std::uint64_t>(std::numeric_limits<U>::max())) {
191 "integer value is out of range");
192 }
193 return static_cast<U>(n);
194 }
196 "expected unsigned integer");
197 } else if constexpr (std::is_floating_point_v<U>) {
198 long double n = 0;
199 if (r.kind() == serialization_kind::floating) {
200 n = r.read_floating();
201 } else if (r.kind() == serialization_kind::signed_integer) {
202 n = r.read_signed();
203 } else if (r.kind() == serialization_kind::unsigned_integer) {
204 n = r.read_unsigned();
205 } else {
207 }
208 if (!std::isfinite(static_cast<long double>(n)) || n < std::numeric_limits<U>::lowest() ||
209 n > std::numeric_limits<U>::max()) {
211 "floating point value is out of range");
212 }
213 return static_cast<U>(n);
214 } else if constexpr (std::same_as<U, std::string>) {
215 if (r.kind() != serialization_kind::string) {
217 }
218 return std::string(r.read_string());
219 } else if constexpr (std::is_enum_v<U>) {
220 if (r.kind() == serialization_kind::string && options_.enums != enum_decoding::underlying) {
221 auto v = enum_cast<U>(r.read_string());
222 if (!v) {
224 }
225 return *v;
226 }
227 if ((options_.enums == enum_decoding::underlying ||
231 using B = std::underlying_type_t<U>;
232 auto n = decode_value<B>(r);
233 if (!n) {
234 return n.error();
235 }
236 U v = static_cast<U>(*n);
237 if (!enum_contains(v)) {
239 }
240 return v;
241 }
243 } else if constexpr (detail::is_optional_v<U>) {
244 if (r.kind() == serialization_kind::null) {
245 return U{};
246 }
248 if (!v) {
249 return v.error();
250 }
251 return U{std::move(*v)};
252 } else if constexpr (detail::is_sequence_v<U>) {
253 if (r.kind() != serialization_kind::array) {
255 }
256 if (r.size() > options_.max_container_size) {
258 "container size exceeds configured limit");
259 }
260 depth_guard guard(*this);
261 if (!guard) {
263 "maximum deserialization depth exceeded");
264 }
265 U out;
266 if constexpr (requires { out.reserve(r.size()); }) {
267 out.reserve(r.size());
268 }
269 for (std::size_t i = 0; i < r.size(); ++i) {
271 if (!v) {
272 return prepend_serialization_path(v.error(), std::to_string(i));
273 }
274 out.emplace_back(std::move(*v));
275 }
276 return out;
277 } else if constexpr (detail::is_set_v<U>) {
278 if (r.kind() != serialization_kind::array) {
280 }
281 if (r.size() > options_.max_container_size) {
283 "container size exceeds configured limit");
284 }
285 depth_guard guard(*this);
286 if (!guard) {
288 "maximum deserialization depth exceeded");
289 }
290 U out;
291 for (std::size_t i = 0; i < r.size(); ++i) {
293 if (!v) {
294 return prepend_serialization_path(v.error(), std::to_string(i));
295 }
296 auto [it, inserted] = out.emplace(std::move(*v));
299 "duplicate set element", std::to_string(i));
300 }
301 }
302 return out;
303 } else if constexpr (detail::is_array_v<U> || detail::is_pair_v<U> ||
304 detail::is_tuple_like_v<U>) {
305 constexpr auto N = std::tuple_size_v<U>;
306 if (r.kind() == serialization_kind::array && r.size() > options_.max_container_size) {
308 "container size exceeds configured limit");
309 }
310 if (r.kind() != serialization_kind::array) {
312 }
313 if (r.size() != N) {
315 "tuple length does not match input");
316 }
317 depth_guard guard(*this);
318 if (!guard) {
320 "maximum deserialization depth exceeded");
321 }
322 return decode_tuple<U>(r, std::make_index_sequence<N>{});
323 } else if constexpr (detail::is_map_v<U>) {
324 if (r.kind() != serialization_kind::array && r.kind() != serialization_kind::object) {
326 "expected map array/object");
327 }
328 if (r.size() > options_.max_container_size) {
330 "container size exceeds configured limit");
331 }
332 depth_guard guard(*this);
333 if (!guard) {
335 "maximum deserialization depth exceeded");
336 }
337 U out;
338 using K = typename detail::map_traits<U>::key_type;
339 using V = typename detail::map_traits<U>::mapped_type;
340 if constexpr (detail::is_string_key_v<K>) {
341 if (r.kind() != serialization_kind::object) {
342 return make_serialization_error(serialization_errc::type_mismatch, "expected object map");
343 }
344
345 auto decode_member = [&](const auto &m) -> serialization_result<void> {
346 auto v = decode_value<V>(m.value);
347 if (!v) {
348 return prepend_serialization_path(v.error(), m.name);
349 }
350 out.emplace(std::string(m.name), std::move(*v));
351 return {};
352 };
353
355 for (std::size_t i = r.size(); i != 0; --i) {
356 auto m = r.member(i - 1);
357 if (out.find(std::string(m.name)) != out.end()) {
358 continue;
359 }
360 auto status = decode_member(m);
361 if (!status) {
362 return status.error();
363 }
364 }
365 } else {
366 for (std::size_t i = 0; i < r.size(); ++i) {
367 auto m = r.member(i);
368 if (out.find(std::string(m.name)) != out.end()) {
371 "duplicate map key", std::string(m.name));
372 }
373 continue;
374 }
375 auto status = decode_member(m);
376 if (!status) {
377 return status.error();
378 }
379 }
380 }
381 } else {
382 if (r.kind() != serialization_kind::array) {
384 "expected map entry array");
385 }
386 for (std::size_t i = 0; i < r.size(); ++i) {
387 auto e = r.element(i);
388 if (e.kind() != serialization_kind::array || e.size() != 2) {
390 "map entry must contain key and value",
391 std::to_string(i));
392 }
393 depth_guard entry_depth(*this);
394 if (!entry_depth) {
396 "maximum deserialization depth exceeded",
397 std::to_string(i));
398 }
399 auto k = decode_value<K>(e.element(0));
400 if (!k) {
401 return prepend_serialization_path(k.error(), std::to_string(i) + ".0");
402 }
403 auto v = decode_value<V>(e.element(1));
404 if (!v) {
405 return prepend_serialization_path(v.error(), std::to_string(i) + ".1");
406 }
407 auto [it, inserted] = out.emplace(std::move(*k), std::move(*v));
410 "duplicate map key", std::to_string(i));
411 }
412 }
413 }
414 return out;
415 } else if constexpr (detail::is_variant_v<U>) {
416 if (r.kind() != serialization_kind::object) {
418 "expected variant object");
419 }
420 if (r.size() > options_.max_container_size) {
422 "container size exceeds configured limit");
423 }
424 depth_guard guard(*this);
425 if (!guard) {
427 "maximum deserialization depth exceeded");
428 }
429 std::optional<Reader> index;
430 std::optional<Reader> payload;
431 for (std::size_t i = 0; i < r.size(); ++i) {
432 auto m = r.member(i);
433 auto select = [&](std::optional<Reader> &field) -> serialization_result<void> {
434 if (field) {
437 "duplicate variant field", std::string(m.name));
438 }
440 return {};
441 }
442 field.reset();
443 }
444 field.emplace(std::move(m.value));
445 return {};
446 };
447 if (m.name == "index") {
448 auto status = select(index);
449 if (!status) {
450 return status.error();
451 }
452 } else if (m.name == "value") {
453 auto status = select(payload);
454 if (!status) {
455 return status.error();
456 }
457 } else if (options_.unknown_fields == unknown_field_policy::reject) {
459 "unknown variant field", std::string(m.name));
460 }
461 }
462 if (!index || !payload) {
464 "variant requires index and value");
465 }
466 if (index->kind() != serialization_kind::unsigned_integer) {
468 "variant index must be unsigned", "index");
469 }
470 const auto variant_index = index->read_unsigned();
471 if (variant_index >= std::variant_size_v<U>) {
473 "variant index is out of range", "index");
474 }
476 if (!result) {
477 return prepend_serialization_path(result.error(), "value");
478 }
479 return result;
480 } else if constexpr (reflectable<U>) {
481 return decode_aggregate<U>(r);
482 } else {
483 static_assert(detail::always_false_v<U>,
484 "type is not deserializable; specialize serialization_traits<T>");
485 }
486 }
487
488 template <typename T, std::size_t... I>
489 serialization_result<T> decode_tuple(const Reader &r, std::index_sequence<I...>) {
490 auto decode_element = [&]<std::size_t J>() -> serialization_result<std::tuple_element_t<J, T>> {
491 auto value = decode_value<std::tuple_element_t<J, T>>(r.element(J));
492 if (!value) {
493 return prepend_serialization_path(value.error(), std::to_string(J));
494 }
495 return value;
496 };
497 std::tuple<serialization_result<std::tuple_element_t<I, T>>...> vals{
498 decode_element.template operator()<I>()...};
499 bool ok = true;
500 serialization_error e;
501 std::apply(
502 [&](auto &...v) {
503 auto check = [&](auto &x) {
504 if (!x && ok) {
505 ok = false;
506 e = x.error();
507 }
508 };
509 (check(v), ...);
510 },
511 vals);
512 if (!ok) {
513 return e;
514 }
515 return T{std::move(*std::get<I>(vals))...};
516 }
517
518 template <typename V, std::size_t I = 0>
519 serialization_result<V> decode_variant(std::size_t index, const Reader &payload) {
520 if constexpr (I == std::variant_size_v<V>) {
522 "variant index is out of range");
523 } else if (index == I) {
525 if (!v) {
526 return v.error();
527 }
528 return V{std::in_place_index<I>, std::move(*v)};
529 } else {
530 return decode_variant<V, I + 1>(index, payload);
531 }
532 }
533
534 template <typename T> serialization_result<T> decode_aggregate(const Reader &r) {
535 static_assert(detail::valid_schema<T>(),
536 "serialization_schema contains an unknown/duplicate member "
537 "or an overlapping wire/alias name");
538 if (r.kind() != serialization_kind::object) {
540 }
541 if (r.size() > options_.max_container_size) {
543 "container size exceeds configured limit");
544 }
545 depth_guard guard(*this);
546 if (!guard) {
548 "maximum deserialization depth exceeded");
549 }
550 constexpr auto N = member_count_v<T>;
551 return decode_aggregate_impl<T>(r, std::make_index_sequence<N>{});
552 }
553
554 template <typename T, std::size_t... I>
555 serialization_result<T> decode_aggregate_impl(const Reader &r, std::index_sequence<I...>) {
556 struct selected_input {
557 Reader reader;
558 std::string name;
559 };
560
561 std::array<std::optional<selected_input>, sizeof...(I)> selected;
562 std::tuple<std::optional<member_type_t<I, T>>...> slots;
563 bool ok = true;
564 serialization_error error;
565 auto field = [&](std::size_t pos) {
566 auto m = r.member(pos);
567 bool matched = false;
568 auto one = [&]<std::size_t J>() {
569 using D = detail::field_descriptor_t<T, J>;
570 if (D::matches(m.name)) {
571 if (matched) {
572 ok = false;
574 "input field matches multiple schema members",
575 std::string(m.name));
576 } else {
577 matched = true;
578 if constexpr (!D::is_transient) {
579 auto &input = selected[J];
581 ok = false;
583 "duplicate object field", std::string(m.name));
584 return;
585 }
587 return;
588 }
589 input.reset();
590 input.emplace(selected_input{std::move(m.value), std::string(m.name)});
591 }
592 }
593 }
594 };
595 (one.template operator()<I>(), ...);
596 if (!matched && ok && options_.unknown_fields == unknown_field_policy::reject) {
597 ok = false;
598 error = make_serialization_error(serialization_errc::unknown_field, "unknown object field",
599 std::string(m.name));
600 }
601 };
602 if (r.kind() != serialization_kind::object) {
604 }
605 for (std::size_t p = 0; p < r.size() && ok; ++p) {
606 field(p);
607 }
608 if (!ok) {
609 return error;
610 }
611 auto decode_selected = [&]<std::size_t J>() {
612 if (!ok || !selected[J]) {
613 return;
614 }
615 using M = member_type_t<J, T>;
617 if (!v) {
618 ok = false;
619 error = prepend_serialization_path(v.error(), selected[J]->name);
620 return;
621 }
622 std::get<J>(slots).emplace(std::move(*v));
623 };
624 (decode_selected.template operator()<I>(), ...);
625 auto missing = [&]<std::size_t J>() {
626 auto &s = std::get<J>(slots);
627 using M = member_type_t<J, T>;
628 if (!s) {
629 using D = detail::field_descriptor_t<T, J>;
630 if constexpr (D::has_default) {
631 s.emplace(D::template make_default<M>());
632 } else if constexpr (D::is_transient && std::default_initializable<M>) {
633 s.emplace();
634 } else if constexpr (detail::is_optional_v<M>) {
635 s.emplace(std::nullopt);
636 } else if (ok) {
637 ok = false;
639 "missing required object field",
640 std::string(detail::descriptor_wire<D>()));
641 }
642 }
643 };
644 (missing.template operator()<I>(), ...);
645 if (!ok) {
646 return error;
647 }
648 return T{std::move(*std::get<I>(slots))...};
649 }
650
651 const Reader &reader_;
652 deserialization_options options_;
653 std::size_t depth_ = 0;
654};
655
656} // namespace gmp
657
658#endif // GMP_SERIALIZATION_DESERIALIZER_HPP_
basic_deserializer(const Reader &reader, deserialization_options options={})
serialization_result< T > decode()
const deserialization_options & options() const noexcept
constexpr bool enum_contains(E value)
Test whether an enumerator is present in the reflected set.
Definition meta.hpp:423
consteval auto enum_values()
Get all enumerator values of an enumeration type at compile-time.
Definition meta.hpp:193
Definition lock.hpp:21
constexpr serialization_field< Member > field
Definition traits.hpp:107
serialization_kind
Definition archive.hpp:26
serialization_error make_serialization_error(serialization_errc code, std::string message, std::string path={}, std::size_t offset=serialization_error::unknown_offset)
Definition error.hpp:160
serialization_error prepend_serialization_path(serialization_error error, std::string_view segment)
Definition error.hpp:165
duplicate_element_policy duplicate_elements
Definition options.hpp:38
unknown_field_policy unknown_fields
Definition options.hpp:36
duplicate_field_policy duplicate_fields
Definition options.hpp:37
static constexpr std::size_t unknown_offset
Definition error.hpp:49