3#include "ll/api/reflection/Reflection.h"
4#include "ll/api/reflection/ReflectionError.h"
14namespace ll::reflection {
15template <concepts::IsVectorBase T,
class J>
16inline Expected<> deserialize_impl(T& vec, J&& j, meta::PriorityTag<5>);
17template <concepts::IsDispatcher T,
class J>
18inline Expected<> deserialize_impl(T& d, J&& j, meta::PriorityTag<5>);
19template <concepts::IsOptional T,
class J>
20inline Expected<> deserialize_impl(T& opt, J&& j, meta::PriorityTag<5>);
21template <
class T,
class J>
22inline Expected<> deserialize_impl(T& str, J&& j, meta::PriorityTag<4>)
23 requires(concepts::IsString<T> && std::is_assignable_v<T, std::string>);
24template <concepts::TupleLike T,
class J>
25inline Expected<> deserialize_impl(T& tuple, J&& j, meta::PriorityTag<3>);
26template <concepts::ArrayLike T,
class J>
27inline Expected<> deserialize_impl(T& arr, J&& j, meta::PriorityTag<2>);
28template <concepts::Associative T,
class J>
29inline Expected<> deserialize_impl(T& map, J
const& j, meta::PriorityTag<2>);
30template <Reflectable T,
class J>
31inline Expected<> deserialize_impl(T& obj, J
const& j, meta::PriorityTag<1>);
32template <concepts::Require<std::is_enum> T,
class J>
33inline Expected<> deserialize_impl(T& e, J
const& j, meta::PriorityTag<1>);
34template <
class T,
class J>
35inline Expected<> deserialize_impl(T& obj, J
const& j, meta::PriorityTag<0>)
36 requires(std::convertible_to<J, T>);
38template <
class T,
class J>
39[[nodiscard]]
inline Expected<> deserialize(T& t, J&& j)
noexcept
40#if !defined(__INTELLISENSE__)
41 requires(
requires(T& t, J&& j) { deserialize_impl<T>(t, std::forward<J>(j), meta::PriorityTag<5>{}); })
44 return deserialize_impl<T>(t, std::forward<J>(j), meta::PriorityTag<5>{});
46 return makeExceptionError();
49template <
class T,
class J>
50[[nodiscard]]
inline Expected<T> deserialize_to(J&& j)
noexcept {
52 if (
auto d = deserialize<T>(*res, std::forward<J>(j)); !d) {
53 res = forwardError(d.error());
58template <concepts::IsVectorBase T,
class J>
59inline Expected<> deserialize_impl(T& vec, J&& j, meta::PriorityTag<5>) {
61 T::forEachComponent([&]<
typename axis_type,
size_t iter> {
63 res = deserialize<axis_type>(vec.template get<axis_type, iter>(),
static_cast<J&&
>(j[iter]));
64 if (!res) res = makeSerIndexError(iter, res.error());
69template <concepts::IsDispatcher T,
class J>
70inline Expected<> deserialize_impl(T& d, J&& j, meta::PriorityTag<5>) {
71 auto res{deserialize<typename T::storage_type>(d.storage, std::forward<J>(j))};
75template <concepts::IsOptional T,
class J>
76inline Expected<> deserialize_impl(T& opt, J&& j, meta::PriorityTag<5>) {
81 if (!opt) opt.emplace();
82 res = deserialize<typename T::value_type>(*opt, std::forward<J>(j));
86template <
class T,
class J>
87inline Expected<> deserialize_impl(T& str, J&& j, meta::PriorityTag<4>)
88 requires(concepts::IsString<T> && std::is_assignable_v<T, std::string>)
90 if (!j.is_string())
return makeDeserStringTypeError();
91 str = std::string{std::forward<J>(j)};
94template <concepts::TupleLike T,
class J>
95inline Expected<> deserialize_impl(T& tuple, J&& j, meta::PriorityTag<3>) {
96 if (!j.is_array())
return makeDeserArrayTypeError();
97 if (j.size() != std::tuple_size_v<T>)
return makeDeserArraySizeError(std::tuple_size_v<T>);
104 res = deserialize<std::remove_cvref_t<
decltype(arg)>>(arg,
static_cast<J&&
>(j[iter]));
105 if (!res) res = makeSerIndexError(iter, res.error());
115template <concepts::ArrayLike T,
class J>
116inline Expected<> deserialize_impl(T& arr, J&& j, meta::PriorityTag<2>) {
117 if (!j.is_array())
return makeDeserArrayTypeError();
118 using value_type =
typename T::value_type;
119 if constexpr (
requires(T a) { a.clear(); }) {
122 if constexpr (
requires(T a, value_type v) { a.push_back(v); }) {
123 for (
size_t i = 0; i < j.size(); i++) {
124 if (
auto res = deserialize<value_type>(arr.emplace_back(),
static_cast<J&&
>(j[i])); !res) {
125 res = makeSerIndexError(i, res.error());
129 }
else if constexpr (
requires(T a, value_type v) { a.insert(v); }) {
130 for (
size_t i = 0; i < j.size(); i++) {
132 if (
auto res = deserialize<value_type>(tmp,
static_cast<J&&
>(j[i])); !res) {
133 res = makeSerIndexError(i, res.error());
136 arr.insert(std::move(tmp));
141template <concepts::Associative T,
class J>
142inline Expected<> deserialize_impl(T& map, J
const& j, meta::PriorityTag<2>) {
144 (concepts::IsString<typename T::key_type> || std::is_enum_v<typename T::key_type>),
145 "the key type of the associative container must be convertible to a string"
147 if (!j.is_object())
return makeDeserObjectTypeError();
149 for (
auto&& [k, v] : j.items()) {
150 if constexpr (concepts::IsString<typename T::key_type>) {
151 if (
auto res = deserialize<typename T::mapped_type>(
152 map[
static_cast<T::key_type
>(k)],
153 std::forward<
decltype(v)>(v)
156 res = makeSerKeyError(k, res.error());
160 if (
auto res = deserialize<typename T::mapped_type>(
161 map[magic_enum::enum_cast<typename T::key_type>(k).value()],
162 std::forward<
decltype(v)>(v)
165 res = makeSerKeyError(k, res.error());
172template <Reflectable T,
class J>
173inline Expected<> deserialize_impl(T& obj, J
const& j, meta::PriorityTag<1>) {
175 if (!j.is_object()) {
176 res = makeDeserObjectTypeError();
179 forEachMember(obj, [&](std::string_view name,
auto& member) {
180 if (name.starts_with(
'$') || !res) {
183 using member_type = std::remove_cvref_t<
decltype((member))>;
184 auto sname = std::string{name};
185 if (j.contains(sname)) {
186 if constexpr (
requires(member_type& o, J
const& s) { deserialize<member_type>(o, s); }) {
187 res = deserialize<member_type>(member, j[sname]);
188 if (!res) res = makeSerMemberError(sname, res.error());
190 static_assert(traits::always_false<member_type>,
"this type can't deserialize");
193 if constexpr (!concepts::IsOptional<member_type>) {
194 res = makeDeserMissingRequiredFieldError(sname);
196 member = std::nullopt;
202template <concepts::Require<std::is_enum> T,
class J>
203inline Expected<> deserialize_impl(T& e, J
const& j, meta::PriorityTag<1>) {
204 using enum_type = std::remove_cvref_t<T>;
206 if constexpr (magic_enum::detail::subtype_v<enum_type> == magic_enum::detail::enum_subtype::flags) {
207 e = magic_enum::enum_flags_cast<enum_type>(std::string{j}).value();
209 e = magic_enum::enum_cast<enum_type>(std::string{j}).value();
212 e = (enum_type)(std::underlying_type_t<enum_type>{j});
216template <
class T,
class J>
217inline Expected<> deserialize_impl(T& obj, J
const& j, meta::PriorityTag<0>)
218 requires(std::convertible_to<J, T>)