1+ #pragma once
2+ #include < meta>
3+ #include < ranges>
4+ #include " util.hpp"
5+
6+ namespace rsl ::serializer {
7+
8+ template <typename T>
9+ concept is_meta = requires {
10+ { T::info } -> std::convertible_to<std::meta::info>;
11+ };
12+
13+ template <typename T>
14+ concept has_members = is_meta<T> && requires {
15+ { T::members } -> std::convertible_to<std::span<std::meta::info const >>;
16+ };
17+
18+ template <typename T>
19+ concept is_iterable = is_meta<T> && T::iterable;
20+
21+ template <typename T>
22+ concept is_optional = is_meta<T> && T::is_optional;
23+
24+ template <typename T>
25+ struct Meta ;
26+
27+ template <typename T>
28+ requires (std::is_scalar_v<T>)
29+ struct Meta <T> {
30+ static constexpr std::meta::info info = ^^T;
31+
32+ template <typename S, typename F, typename U>
33+ requires (std::same_as<std::remove_cvref_t <U>, T>)
34+ void visit (this S&& self, F&& visitor, U&& value) {
35+ std::invoke (std::forward<F>(visitor), std::forward<S>(self), std::forward<U>(value));
36+ }
37+
38+ template <typename U, typename F>
39+ requires (std::same_as<std::remove_cvref_t <U>, T>)
40+ void descend (F&& visitor, U&& value) {}
41+ };
42+
43+ template <std::size_t Idx, std::meta::info R, typename T>
44+ struct Member : Meta<T> {
45+ static constexpr std::meta::info info = R;
46+ static constexpr std::size_t index = Idx;
47+ };
48+
49+ template <typename T>
50+ requires (std::is_aggregate_v<T> && !std::is_array_v<T>)
51+ struct Meta <T> {
52+ static constexpr std::meta::info info = ^^T;
53+ static constexpr auto members =
54+ define_static_array (nonstatic_data_members_of(info, std::meta::access_context::current()));
55+
56+ template <typename S, typename F, typename U>
57+ requires (std::same_as<std::remove_cvref_t <U>, T>)
58+ void visit (this S&& self, F&& visitor, U&& value) {
59+ std::invoke (std::forward<F>(visitor), std::forward<S>(self), std::forward<U>(value));
60+ }
61+
62+ template <typename F, typename U>
63+ requires (std::same_as<std::remove_cvref_t <U>, T>)
64+ void descend (F&& visitor, U&& value) {
65+ template for (constexpr auto Idx : std::views::iota (0ZU, members.size ())) {
66+ constexpr auto M = members[Idx];
67+ Member<Idx, M, typename [:type_of (M):]>{}.visit (visitor, value.[:M:]);
68+ }
69+ }
70+ };
71+
72+ template <std::ranges::range T>
73+ requires std::constructible_from<std::initializer_list<typename T::value_type>>
74+ struct Meta <T> {
75+ using type = T;
76+ using element_type = typename T::value_type;
77+ constexpr static std::meta::info info = ^^T;
78+ constexpr static bool can_descend = true ;
79+ constexpr static bool iterable = true ;
80+ constexpr static bool associative = requires {
81+ typename type::key_type;
82+ typename type::mapped_type;
83+ };
84+
85+ template <typename S, typename F, typename U>
86+ requires (std::same_as<std::remove_cvref_t <U>, T>)
87+ void visit (this S&& self, F&& visitor, U&& value) {
88+ std::invoke (std::forward<F>(visitor), std::forward<S>(self), std::forward<U>(value));
89+ }
90+
91+ template <typename F, typename U>
92+ requires (std::same_as<std::remove_cvref_t <U>, T>)
93+ void descend (F&& visitor, U&& value) {
94+ for (auto && item : value) {
95+ Meta<std::remove_cvref_t <decltype (item)>>{}.visit (visitor, item);
96+ }
97+ }
98+ };
99+
100+ template <typename T>
101+ struct Meta <std::optional<T>> {
102+ using type = std::optional<T>;
103+ using element_type = T;
104+ constexpr static std::meta::info info = dealias(^^type);
105+ constexpr static bool is_optional = true ;
106+
107+ template <typename S, typename F, typename U>
108+ requires (std::same_as<std::remove_cvref_t <U>, type>)
109+ void visit (this S&& self, F&& visitor, U&& value) {
110+ std::invoke (std::forward<F>(visitor), std::forward<S>(self), std::forward<U>(value));
111+ }
112+ };
113+
114+ } // namespace rsl::serializer
0 commit comments