LeviLamina
Loading...
Searching...
No Matches
Serialization.h
1#pragma once
2
3#include "ll/api/reflection/Reflection.h"
4#include "ll/api/reflection/SerializationError.h"
5
6// Priority:
7// 5. IsVectorBase IsDispatcher IsOptional
8// 4. string
9// 3. TupleLike
10// 2. ArrayLike Associative
11// 1. Reflectable enum
12// 0. convertible
13
14namespace ll::reflection {
15
16template <class J, class T>
17inline Expected<J> serialize_impl(T&& vec, meta::PriorityTag<5>)
18 requires(concepts::IsVectorBase<std::remove_cvref_t<T>>);
19template <class J, class T>
20inline Expected<J> serialize_impl(T&& d, meta::PriorityTag<5>)
21 requires(concepts::IsDispatcher<std::remove_cvref_t<T>>);
22template <class J, class T>
23inline Expected<J> serialize_impl(T&& opt, meta::PriorityTag<5>)
24 requires(concepts::IsOptional<std::remove_cvref_t<T>>);
25template <class J, class T>
26inline Expected<J> serialize_impl(T&& str, meta::PriorityTag<4>)
27 requires(concepts::IsString<std::remove_cvref_t<T>>);
28template <class J, class T>
29inline Expected<J> serialize_impl(T&& tuple, meta::PriorityTag<3>)
30 requires(concepts::TupleLike<std::remove_cvref_t<T>>);
31template <class J, class T>
32inline Expected<J> serialize_impl(T&& arr, meta::PriorityTag<2>)
33 requires(concepts::ArrayLike<std::remove_cvref_t<T>>);
34template <class J, class T>
35inline Expected<J> serialize_impl(T&& map, meta::PriorityTag<2>)
36 requires(concepts::Associative<std::remove_cvref_t<T>>);
37template <class J, class T>
38inline Expected<J> serialize_impl(T&& obj, meta::PriorityTag<1>)
39 requires(Reflectable<std::remove_cvref_t<T>>);
40template <class J, class T>
41inline Expected<J> serialize_impl(T&& e, meta::PriorityTag<1>)
42 requires(std::is_enum_v<std::remove_cvref_t<T>>);
43template <class J, class T>
44inline Expected<J> serialize_impl(T&& obj, meta::PriorityTag<0>)
45 requires(std::convertible_to<std::remove_cvref_t<T>, J>);
46
47template <class J, class T>
48[[nodiscard]] inline Expected<J> serialize(T&& t) noexcept
49#if !defined(__INTELLISENSE__)
50 requires(requires(T&& t) { serialize_impl<J>(std::forward<T>(t), meta::PriorityTag<5>{}); })
51#endif
52try {
53 return serialize_impl<J>(std::forward<T>(t), meta::PriorityTag<5>{});
54} catch (...) {
55 return makeExceptionError();
56}
57
58template <class J, class T>
59[[nodiscard]] inline Expected<> serialize_to(J& j, T&& t) noexcept {
60 if (auto res = serialize<J>(std::forward<T>(t)); res) {
61 j = std::move(*res);
62 } else {
63 return forwardError(res.error());
64 }
65 return {};
66}
67
68template <class J, class T>
69inline Expected<J> serialize_impl(T&& vec, meta::PriorityTag<5>)
70 requires(concepts::IsVectorBase<std::remove_cvref_t<T>>)
71{
72 Expected<J> res{J::array()};
73 std::remove_cvref_t<T>::forEachComponent([&]<typename axis_type, size_t iter> {
74 if (res) {
75 if (auto v = serialize<J>(std::forward<T>(vec).template get<axis_type, iter>()); v) {
76 res->push_back(*std::move(v));
77 } else {
78 res = makeSerIndexError(iter, v.error());
79 }
80 }
81 });
82 return res;
83}
84template <class J, class T>
85inline Expected<J> serialize_impl(T&& d, meta::PriorityTag<5>)
86 requires(concepts::IsDispatcher<std::remove_cvref_t<T>>)
87{
88 return serialize<J>(std::forward<T>(d).storage);
89}
90template <class J, class T>
91inline Expected<J> serialize_impl(T&& opt, meta::PriorityTag<5>)
92 requires(concepts::IsOptional<std::remove_cvref_t<T>>)
93{
94 if (!opt) {
95 return nullptr;
96 }
97 return serialize<J>(*std::forward<T>(opt));
98}
99template <class J, class T>
100inline Expected<J> serialize_impl(T&& str, meta::PriorityTag<4>)
101 requires(concepts::IsString<std::remove_cvref_t<T>>)
102{
103 return std::string{std::forward<T>(str)};
104}
105template <class J, class T>
106inline Expected<J> serialize_impl(T&& tuple, meta::PriorityTag<3>)
107 requires(concepts::TupleLike<std::remove_cvref_t<T>>)
108{
109 Expected<J> res{J::array()};
110 std::apply(
111 [&](auto&&... args) {
112 size_t iter{0};
113 (([&](auto&& arg) {
114 if (res) {
115 if (auto v = serialize<J>(std::forward<decltype((arg))>(arg)); v) {
116 res->push_back(*std::move(v));
117 iter++;
118 } else {
119 res = makeSerIndexError(iter, v.error());
120 }
121 }
122 }(std::forward<decltype((args))>(args))),
123 ...);
124 },
125 std::forward<decltype((tuple))>(tuple)
126 );
127 return res;
128}
129template <class J, class T>
130inline Expected<J> serialize_impl(T&& arr, meta::PriorityTag<2>)
131 requires(concepts::ArrayLike<std::remove_cvref_t<T>>)
132{
133 Expected<J> res{J::array()};
134 size_t iter{0};
135 for (auto&& val : std::forward<T>(arr)) {
136 if (auto v = serialize<J>(std::forward<decltype((val))>(val)); v) {
137 res->push_back(*std::move(v));
138 iter++;
139 } else {
140 res = makeSerIndexError(iter, v.error());
141 break;
142 }
143 }
144 return res;
145}
146template <class J, class T>
147inline Expected<J> serialize_impl(T&& map, meta::PriorityTag<2>)
148 requires(concepts::Associative<std::remove_cvref_t<T>>)
149{
150 using RT = std::remove_cvref_t<T>;
151 static_assert(
152 (concepts::IsString<typename RT::key_type> || std::is_enum_v<typename RT::key_type>),
153 "the key type of the associative container must be convertible to a string"
154 );
155 Expected<J> res{J::object()};
156 for (auto&& [k, v] : map) {
157 std::string key;
158 if constexpr (std::is_enum_v<typename RT::key_type>) {
159 key = magic_enum::enum_name(std::forward<decltype((k))>(k));
160 } else {
161 key = std::string{std::forward<decltype((k))>(k)};
162 }
163 if (auto sv = serialize<J>(std::forward<decltype((v))>(v)); sv) {
164 (*res)[key] = *std::move(sv);
165 } else {
166 res = makeSerKeyError(key, sv.error());
167 break;
168 }
169 }
170 return res;
171}
172template <class J, class T>
173inline Expected<J> serialize_impl(T&& obj, meta::PriorityTag<1>)
174 requires(Reflectable<std::remove_cvref_t<T>>)
175{
176 Expected<J> res{J::object()};
177 forEachMember(obj, [&](std::string_view name, auto&& member) {
178 if (name.starts_with('$') || !res) {
179 return;
180 }
181 using member_type = decltype((member));
182 if constexpr (requires(member_type m) { serialize<J>(m); }) {
183 auto v = serialize<J>(std::forward<member_type>(member));
184 if (v) {
185 if (!v->is_null()) (*res)[std::string{name}] = *std::move(v);
186 } else {
187 res = makeSerMemberError(std::string{name}, v.error());
188 }
189 } else {
190 static_assert(traits::always_false<member_type>, "this type can't serialize");
191 }
192 });
193 return res;
194}
195template <class J, class T>
196inline Expected<J> serialize_impl(T&& e, meta::PriorityTag<1>)
197 requires(std::is_enum_v<std::remove_cvref_t<T>>)
198{
199 return magic_enum::enum_name(std::forward<T>(e));
200}
201template <class J, class T>
202inline Expected<J> serialize_impl(T&& obj, meta::PriorityTag<0>)
203 requires(std::convertible_to<std::remove_cvref_t<T>, J>)
204{
205 return std::forward<T>(obj);
206}
207} // namespace ll::reflection
Definition serialize.h:11