Add basic model validation after deserialization

This commit is contained in:
G.H.O.S.T 2024-12-28 21:13:24 +01:00
parent cf503e6bfa
commit 5ab48d8c36
Signed by: G.H.O.S.T
GPG Key ID: 3BD93EABD1407B82

View File

@ -68,11 +68,27 @@ namespace code::json
};
template<member_name_t Name, auto Member>
template<typename, typename = std::void_t<>>
struct has_validator
: std::false_type
{};
template<typename T>
struct has_validator<
T,
std::void_t<
decltype(std::declval<T const&>().validate(std::declval<marshaling_context_t*>()))
>
>
: std::true_type
{};
template<member_name_t Name, auto Member, typename Validator = void>
struct member_t
{
using T = member_traits<decltype(Member)>::class_type;
using M = member_traits<decltype(Member)>::member_type;
using V = Validator;
static constexpr bool is_optional{
is_optional_v<M>
@ -97,7 +113,13 @@ namespace code::json
throw std::runtime_error{"missing field '" + Name.str() + "'"};
}
instance.*Member = marshaling_traits<M>::unmarshal(v.get(Name), context);
M value = marshaling_traits<M>::unmarshal(v.get(Name), context);
if constexpr (!std::is_same_v<V, void>) {
V::validate(value, context);
}
instance.*Member = std::move(value);
}
struct pointer_t
@ -133,7 +155,13 @@ namespace code::json
throw std::runtime_error{ "missing field '" + to_string(ptr()) + "'" };
}
instance.*Member = marshaling_traits<M>::unmarshal(*ptr_v, context);
M value = marshaling_traits<M>::unmarshal(*ptr_v, context);
if constexpr (!std::is_same_v<V, void>) {
V::validate(value, context);
}
instance.*Member = std::move(value);
}
};
@ -168,6 +196,10 @@ namespace code::json
{
First::unmarshal(instance, v, context);
((Members::unmarshal(instance, v, context)), ...);
if constexpr (has_validator<T>::value) {
instance.validate(context);
}
}
static
@ -209,6 +241,10 @@ namespace code::json
((Bases::json::do_unmarshal(instance, v, context)), ...);
First::unmarshal(instance, v, context);
((Members::unmarshal(instance, v, context)), ...);
if constexpr (has_validator<T>::value) {
instance.validate(context);
}
}
static