LeviLamina
Loading...
Searching...
No Matches
Serialization.h
1#pragma once
2#include "ll/api/base/FixedString.h"
3#include "ll/api/base/TypeTraits.h"
4#include <ll/api/reflection/Reflection.h>
5#include <ll/api/reflection/ReflectionError.h>
6#include <ll/api/reflection/Serializer.h>
7
8// Priority:
9// 11. Arithmetic
10// 10. Custom Specialization
11// 9. Optional
12// 9. Dispatcher
13// 8. IsVectorBase
14// 7. Enum
15// 6. Variant
16// 5. String Convertible
17// 4. TupleLike
18// 3. ArrayLike
19// 2. Associative
20// 1. Aggregate
21// 0. Not Reflectable
22
23namespace ll::reflection {
24
25namespace {
26
27template <typename J, typename T, IsKeyFormatter F>
28inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<11>)
29 requires(std::is_arithmetic_v<std::remove_cvref_t<T>>);
30template <typename J, typename T, IsKeyFormatter F>
31inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<10>)
32 requires(detail::has_custom_serializer_v<std::remove_cvref_t<T>, J, F>);
33template <typename J, typename T, IsKeyFormatter F>
34inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<9>)
35 requires(concepts::IsOptional<std::remove_cvref_t<T>>);
36template <typename J, typename T, IsKeyFormatter F>
37inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<9>)
38 requires(concepts::IsDispatcher<std::remove_cvref_t<T>>);
39template <typename J, typename T, IsKeyFormatter F>
40inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<8>)
41 requires(concepts::IsVectorBase<std::remove_cvref_t<T>>);
42template <class J, typename T, IsKeyFormatter F>
43inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<7>)
44 requires(std::is_enum_v<std::remove_cvref_t<T>>);
45template <class J, typename T, IsKeyFormatter F>
46inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<6>)
47 requires(concepts::IsVariant<std::remove_cvref_t<T>>);
48template <class J, typename T, IsKeyFormatter F>
49inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<5>)
50 requires(concepts::IsStringConvertible<std::remove_cvref_t<T>>);
51template <class J, typename T, IsKeyFormatter F>
52inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<4>)
53 requires(concepts::TupleLike<std::remove_cvref_t<T>>);
54template <typename J, typename T, IsKeyFormatter F>
55inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<3>)
56 requires(concepts::ArrayLike<std::remove_cvref_t<T>>);
57template <typename J, typename T, IsKeyFormatter F>
58inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<2>)
59 requires(concepts::Associative<std::remove_cvref_t<T>>);
60template <typename J, typename T, IsKeyFormatter F>
61inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<1>)
63template <typename J, typename T, IsKeyFormatter F>
64inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<0>);
65
66} // namespace
67
68template <typename J, typename T, IsKeyFormatter F>
69inline Expected<J> serialize(T&& t, F const& keyFormatter) noexcept
70#if !defined(__INTELLISENSE__)
71 requires(requires(T&& t, F const& keyFormatter) {
72 serialize_impl<J>(std::forward<T>(t), keyFormatter, meta::PriorityTag<11>{});
73 })
74#endif
75try {
76 return serialize_impl<J>(std::forward<T>(t), keyFormatter, meta::PriorityTag<11>{});
77} catch (...) {
78 return makeExceptionError();
79}
80
81template <typename J, typename T>
82inline Expected<J> serialize(T&& t) noexcept {
83 return serialize<J>(std::forward<T>(t), detail::default_key_formatter);
84}
85
86template <class J, class T, IsKeyFormatter F>
87inline Expected<> serialize_to(J& j, T&& t, F const& keyFormatter) noexcept {
88 if (auto res = serialize<J>(std::forward<T>(t), keyFormatter); res) {
89 j = std::move(*res);
90 } else {
91 return forwardError(res.error());
92 }
93 return {};
94}
95
96template <class J, class T>
97inline Expected<> serialize_to(J& j, T&& t) noexcept {
98 return serialize_to<J>(j, std::forward<T>(t), detail::default_key_formatter);
99}
100
101template <auto MemberPtr, class J, class T, IsKeyFormatter F>
102inline Expected<> member_serialize(J& j, T&& t, F const& keyFormatter) noexcept
103 requires(!std::is_const_v<std::remove_reference_t<J>>)
104{
105 static_assert(!typeNameStem(getRawName<MemberPtr>()).empty(), "member name is empty");
106 if (!j.is_object()) return makeSerObjectTypeError();
107 auto result = serialize<J>(t.*MemberPtr, keyFormatter);
108 if (!result) return ll::forwardError(result.error());
109 j[keyFormatter(typeNameStem(getRawName<MemberPtr>()))] = *std::move(result);
110 return {};
111}
112
113template <ll::FixedString Key, class J, class T, IsKeyFormatter F>
114inline Expected<> field_serialize(J& j, T&& t, F const& keyFormatter) noexcept
115 requires(!std::is_const_v<std::remove_reference_t<J>>)
116{
117 static_assert(Key.size() != 0, "field name is empty");
118 if (!j.is_object()) return makeSerObjectTypeError();
119
120 auto key = keyFormatter(Key.sv());
121
122 if constexpr (concepts::IsOptional<std::remove_cvref_t<T>>) {
123 if (!t.has_value()) {
124 return {};
125 }
126 auto result = serialize<J>(*t, keyFormatter);
127 if (!result) return ll::forwardError(result.error());
128 j[key] = *std::move(result);
129 } else {
130 auto result = serialize<J>(std::forward<T>(t), keyFormatter);
131 if (!result) return ll::forwardError(result.error());
132 j[key] = *std::move(result);
133 }
134
135 return {};
136}
137
138template <auto MemberPtr, class J, class T>
139inline Expected<> member_serialize(J& j, T&& t) noexcept
140 requires(!std::is_const_v<std::remove_reference_t<J>>)
141{
142 return member_serialize<MemberPtr>(j, std::forward<T>(t), detail::default_key_formatter);
143}
144
145template <ll::FixedString Key, class J, class T>
146inline Expected<> field_serialize(J& j, T&& t) noexcept
147 requires(!std::is_const_v<std::remove_reference_t<J>>)
148{
149 return field_serialize<Key>(j, std::forward<T>(t), detail::default_key_formatter);
150}
151
152template <auto MemberPtr, class T, class J, IsKeyFormatter F>
153inline Expected<> member(T&& t, J& j, F const& keyFormatter) noexcept
154 requires(!std::is_const_v<std::remove_reference_t<J>>)
155{
156 return member_serialize<MemberPtr>(j, std::forward<T>(t), keyFormatter);
157}
158
159template <ll::FixedString Key, class T, class J, IsKeyFormatter F>
160inline Expected<> field(T&& t, J& j, F const& keyFormatter) noexcept
161 requires(!std::is_const_v<std::remove_reference_t<J>>)
162{
163 return field_serialize<Key>(j, std::forward<T>(t), keyFormatter);
164}
165
166template <auto MemberPtr, class T, class J>
167inline Expected<> member(T&& t, J& j) noexcept
168 requires(!std::is_const_v<std::remove_reference_t<J>>)
169{
170 return member<MemberPtr>(std::forward<T>(t), j, detail::default_key_formatter);
171}
172
173template <ll::FixedString Key, class T, class J>
174inline Expected<> field(T&& t, J& j) noexcept
175 requires(!std::is_const_v<std::remove_reference_t<J>>)
176{
177 return field<Key>(std::forward<T>(t), j, detail::default_key_formatter);
178}
179
180namespace {
181
182template <typename J, typename T, IsKeyFormatter F>
183inline Expected<J> serialize_impl(T&& t, F const&, meta::PriorityTag<11>)
184 requires(std::is_arithmetic_v<std::remove_cvref_t<T>>)
185{
186 return t;
187}
188
189template <typename J, typename T, IsKeyFormatter F>
190inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<10>)
191 requires(detail::has_custom_serializer_v<std::remove_cvref_t<T>, J, F>)
192{
193 using RT = std::remove_cvref_t<T>;
194 if constexpr (detail::has_value_serializer_v<RT, J, F>) {
195 using JT = std::remove_cvref_t<J>;
196 auto result = [&]() -> decltype(auto) {
197 if constexpr (requires { Serializer<RT, JT>::serialize(std::forward<T>(t), keyFormatter); }) {
198 return Serializer<RT, JT>::serialize(std::forward<T>(t), keyFormatter);
199 } else if constexpr (requires { Serializer<RT, JT>::serialize(std::forward<T>(t)); }) {
200 return Serializer<RT, JT>::serialize(std::forward<T>(t));
201 } else if constexpr (requires {
202 Serializer<RT>::template serialize<JT>(std::forward<T>(t), keyFormatter);
203 }) {
204 return Serializer<RT>::template serialize<JT>(std::forward<T>(t), keyFormatter);
205 } else {
206 return Serializer<RT>::template serialize<JT>(std::forward<T>(t));
207 }
208 }();
209 using Result = std::remove_cvref_t<decltype(result)>;
210 if constexpr (concepts::IsLeviExpected<Result>) {
211 if (!result) {
212 return forwardError(result.error());
213 }
214 if constexpr (std::same_as<std::remove_cvref_t<decltype(*result)>, J>) {
215 return *std::move(result);
216 } else {
217 return J(*std::move(result));
218 }
219 } else {
220 if constexpr (std::same_as<Result, J>) {
221 return std::move(result);
222 } else {
223 return J(std::move(result));
224 }
225 }
226 } else {
227 J result{};
228 if constexpr (requires { Serializer<RT>::serialize(std::forward<T>(t), result, keyFormatter); }) {
229 if (auto res = Serializer<RT>::serialize(std::forward<T>(t), result, keyFormatter); !res) {
230 return forwardError(res.error());
231 }
232 } else {
233 if (auto res = Serializer<RT>::serialize(std::forward<T>(t), result); !res) {
234 return forwardError(res.error());
235 }
236 }
237 return result;
238 }
239}
240
241template <typename J, typename T, IsKeyFormatter F>
242inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<9>)
243 requires(concepts::IsOptional<std::remove_cvref_t<T>>)
244{
245 return t ? serialize_impl<J>(*std::forward<T>(t), keyFormatter, meta::PriorityTag<11>{}) : nullptr;
246}
247
248template <typename J, typename T, IsKeyFormatter F>
249inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<9>)
250 requires(concepts::IsDispatcher<std::remove_cvref_t<T>>)
251{
252 return serialize_impl<J>(std::forward<T>(t).storage, keyFormatter, meta::PriorityTag<11>{});
253}
254
255template <typename J, typename T, IsKeyFormatter F>
256inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<8>)
257 requires(concepts::IsVectorBase<std::remove_cvref_t<T>>)
258{
259 Expected<J> res{J::array()};
260 std::remove_cvref_t<T>::forEachComponent([&]<typename axis_type, size_t iter> {
261 if (res) {
262 if (auto v = serialize<J>(std::forward<T>(t).template get<axis_type, iter>(), keyFormatter); v) {
263 res->push_back(*std::move(v));
264 } else {
265 res = makeSerIndexError(iter, v.error());
266 }
267 }
268 });
269 return res;
270}
271
272template <class J, typename T, IsKeyFormatter F>
273inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<7>)
274 requires(std::is_enum_v<std::remove_cvref_t<T>>)
275{
276 using enum_type = std::remove_cvref_t<T>;
277 if (auto name = detail::enum_name_to_string<enum_type>(t, keyFormatter)) {
278 return *std::move(name);
279 }
280 return fmt::underlying(t);
281}
282
283template <class J, typename T, IsKeyFormatter F>
284inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<6>)
285 requires(concepts::IsVariant<std::remove_cvref_t<T>>)
286{
287 return std::visit(
288 [&](auto const& value) { return serialize_impl<J>(value, keyFormatter, meta::PriorityTag<11>{}); },
289 t
290 );
291}
292
293template <class J, typename T, IsKeyFormatter F>
294inline Expected<J> serialize_impl(T&& t, F const&, meta::PriorityTag<5>)
295 requires(concepts::IsStringConvertible<std::remove_cvref_t<T>>)
296{
297 return J(std::string{std::forward<T>(t)});
298}
299
300template <class J, typename T, IsKeyFormatter F>
301inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<4>)
302 requires(concepts::TupleLike<std::remove_cvref_t<T>>)
303{
304 Expected<J> res{J::array()};
305 std::apply(
306 [&](auto&&... args) {
307 size_t iter{0};
308 (([&](auto&& arg) {
309 if (res) {
310 if (auto v =
311 serialize_impl<J>(std::forward<decltype(arg)>(arg), keyFormatter, meta::PriorityTag<11>{});
312 v) {
313 res->push_back(*std::move(v));
314 iter++;
315 } else {
316 res = makeSerIndexError(iter, v.error());
317 }
318 }
319 }(std::forward<decltype(args)>(args))),
320 ...);
321 },
322 std::forward<decltype(t)>(t)
323 );
324 return res;
325}
326
327template <typename J, typename T, IsKeyFormatter F>
328inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<3>)
329 requires(concepts::ArrayLike<std::remove_cvref_t<T>>)
330{
331 Expected<J> res{J::array()};
332 size_t iter{0};
333 for (auto&& val : std::forward<T>(t)) {
334 if (auto v = serialize_impl<J>(std::forward<decltype(val)>(val), keyFormatter, meta::PriorityTag<11>{}); v) {
335 res->push_back(*std::move(v));
336 iter++;
337 } else {
338 res = makeSerIndexError(iter, v.error());
339 break;
340 }
341 }
342 return res;
343}
344
345template <typename J, typename T, IsKeyFormatter F>
346inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<2>)
347 requires(concepts::Associative<std::remove_cvref_t<T>>)
348{
349 static_assert(
350 detail::is_key_stringifiable_v<typename std::remove_cvref_t<T>::key_type>,
351 "an associative container key has to be a string, an enum, or a type with a "
352 "ll::reflection::Serializer<T>::to_string / from_string specialization"
353 );
354 Expected<J> res{J::object()};
355 for (auto&& [k, v] : t) {
356 auto key = type_to_string(k, keyFormatter);
357 if (auto sv = serialize_impl<J>(std::forward<decltype(v)>(v), keyFormatter, meta::PriorityTag<11>{}); sv) {
358 (*res)[key] = *std::move(sv);
359 } else {
360 res = makeSerKeyError(key, sv.error());
361 break;
362 }
363 }
364 return res;
365}
366
367template <typename J, typename T, IsKeyFormatter F>
368inline Expected<J> serialize_impl(T&& t, F const& keyFormatter, meta::PriorityTag<1>)
370{
371 Expected<J> res{J::object()};
372 forEachMember(t, [&](std::string_view name, auto&& member) {
373 if (!res) return;
374 auto key = keyFormatter(name);
375 auto v = serialize_impl<J>(std::forward<decltype((member))>(member), keyFormatter, meta::PriorityTag<11>{});
376 if (v) {
377 if (!v->is_null()) (*res)[key] = *std::move(v);
378 } else {
379 res = makeSerMemberError(key, v.error());
380 }
381 });
382 return res;
383}
384
385template <typename J, typename T, IsKeyFormatter F>
386inline Expected<J> serialize_impl(T&&, F const&, meta::PriorityTag<0>) {
387 static_assert(
388 traits::always_false<std::remove_cvref_t<T>>,
389 "cannot serialize this type: provide a ll::reflection::Serializer<T> specialization, or use an "
390 "arithmetic type, a string, an optional, a dispatcher, an enum, a variant, a tuple-like, an array-like "
391 "or associative container, or a reflectable aggregate"
392 );
393}
394
395} // namespace
396
397} // namespace ll::reflection
Definition Reflection.h:33
Definition Serializer.h:9