weh
This commit is contained in:
parent
bd402f57f5
commit
3ea546fe08
|
@ -1,5 +1,8 @@
|
||||||
---
|
---
|
||||||
|
AlignAfterOpenBracket: BlockIndent
|
||||||
|
AlignArrayOfStructures: Right
|
||||||
AlignConsecutiveAssignments: true
|
AlignConsecutiveAssignments: true
|
||||||
|
AlignConsecutiveDeclarations: true
|
||||||
AllowShortBlocksOnASingleLine: Always
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortCompoundRequirementOnASingleLine: true
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
AllowShortEnumsOnASingleLine: true
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
|
8464
include/ctre.hpp
8464
include/ctre.hpp
File diff suppressed because it is too large
Load diff
|
@ -21,8 +21,9 @@ namespace rfl {
|
||||||
internal::remove_namespaces<internal::get_type_name<StructType>()>()>;
|
internal::remove_namespaces<internal::get_type_name<StructType>()>()>;
|
||||||
using FieldType = Field<field_name_, LiteralType>;
|
using FieldType = Field<field_name_, LiteralType>;
|
||||||
const auto add_new_field = [](auto&&... _fields) {
|
const auto add_new_field = [](auto&&... _fields) {
|
||||||
return make_named_tuple(FieldType(LiteralType()),
|
return make_named_tuple(
|
||||||
std::move(_fields)...);
|
FieldType(LiteralType()), std::move(_fields)...
|
||||||
|
);
|
||||||
};
|
};
|
||||||
return std::apply(add_new_field, std::move(_view.fields()));
|
return std::apply(add_new_field, std::move(_view.fields()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ namespace rfl {
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto types = std::vector<ValidationType>(
|
const auto types = std::vector<ValidationType>(
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...});
|
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
||||||
|
);
|
||||||
return ValidationType {ValidationType::AllOf {.types_ = types}};
|
return ValidationType {ValidationType::AllOf {.types_ = types}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace rfl {
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto types = std::vector<ValidationType>(
|
const auto types = std::vector<ValidationType>(
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...});
|
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
||||||
|
);
|
||||||
return ValidationType {ValidationType::AnyOf {.types_ = types}};
|
return ValidationType {ValidationType::AnyOf {.types_ = types}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,15 +40,16 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class Head, class... Tail>
|
template <class T, class Head, class... Tail>
|
||||||
static rfl::Result<T> validate_impl(const T& _value,
|
static rfl::Result<T>
|
||||||
std::vector<Error> _errors) {
|
validate_impl(const T& _value, std::vector<Error> _errors) {
|
||||||
const auto handle_err = [&](Error&& _err) {
|
const auto handle_err = [&](Error&& _err) {
|
||||||
_errors.push_back(std::forward<Error>(_err));
|
_errors.push_back(std::forward<Error>(_err));
|
||||||
if constexpr (sizeof...(Tail) == 0) {
|
if constexpr (sizeof...(Tail) == 0) {
|
||||||
return make_error_message(_errors);
|
return make_error_message(_errors);
|
||||||
} else {
|
} else {
|
||||||
return validate_impl<T, Tail...>(
|
return validate_impl<T, Tail...>(
|
||||||
_value, std::forward<std::vector<Error>>(_errors));
|
_value, std::forward<std::vector<Error>>(_errors)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Head::validate(_value).or_else(handle_err);
|
return Head::validate(_value).or_else(handle_err);
|
||||||
|
|
|
@ -33,25 +33,29 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {}
|
Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Attribute(const U& _value) : value_(_value) {}
|
Attribute(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Attribute(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
Attribute(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Attribute(const Attribute<U>& _attr) : value_(_attr.value()) {}
|
Attribute(const Attribute<U>& _attr) : value_(_attr.value()) {}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
Attribute(const Default& _default) : value_(Type()) {}
|
Attribute(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Attribute() = default;
|
~Attribute() = default;
|
||||||
|
@ -78,18 +82,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -96,9 +96,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class CharT, class Traits, class T>
|
template <class CharT, class Traits, class T>
|
||||||
inline std::basic_ostream<CharT, Traits>& operator<<(
|
inline std::basic_ostream<CharT, Traits>&
|
||||||
std::basic_ostream<CharT, Traits>& _os,
|
operator<<(std::basic_ostream<CharT, Traits>& _os, const Box<T>& _b) {
|
||||||
const Box<T>& _b) {
|
|
||||||
_os << _b.get();
|
_os << _b.get();
|
||||||
return _os;
|
return _os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,26 +42,30 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Description(Description<_description, U>&& _field) : value_(_field.get()) {}
|
Description(Description<_description, U>&& _field) : value_(_field.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Description(const U& _value) : value_(_value) {}
|
Description(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Description(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
Description(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Description(const Description<_description, U>& _field)
|
Description(const Description<_description, U>& _field)
|
||||||
: value_(_field.value()) {}
|
: value_(_field.value()) {}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
Description(const Default& _default) : value_(Type()) {}
|
Description(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Description() = default;
|
~Description() = default;
|
||||||
|
@ -91,18 +95,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -110,11 +116,13 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Description<_description, T>& operator=(
|
Description<_description, T>& operator=(
|
||||||
const Description<_description, T>& _field) = default;
|
const Description<_description, T>& _field
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Description<_description, T>& operator=(
|
Description<_description, T>& operator=(
|
||||||
Description<_description, T>&& _field) = default;
|
Description<_description, T>&& _field
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U>
|
template <class U>
|
||||||
|
|
|
@ -39,25 +39,29 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Field(Field<_name, U>&& _field) : value_(_field.get()) {}
|
Field(Field<_name, U>&& _field) : value_(_field.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Field(const U& _value) : value_(_value) {}
|
Field(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Field(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
Field(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Field(const Field<_name, U>& _field) : value_(_field.value()) {}
|
Field(const Field<_name, U>& _field) : value_(_field.value()) {}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
Field(const Default& _default) : value_(Type()) {}
|
Field(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Field() = default;
|
~Field() = default;
|
||||||
|
@ -90,18 +94,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -29,14 +29,16 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Flatten(Flatten<U>&& _f) : value_(_f.get()) {}
|
Flatten(Flatten<U>&& _f) : value_(_f.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Flatten(const U& _value) : value_(_value) {}
|
Flatten(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Flatten(U&& _value) : value_(_value) {}
|
Flatten(U&& _value) : value_(_value) {}
|
||||||
|
|
||||||
~Flatten() = default;
|
~Flatten() = default;
|
||||||
|
@ -66,9 +68,10 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Flatten<T>& operator=(const U& _value) {
|
Flatten<T>& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -25,11 +25,10 @@ namespace rfl {
|
||||||
using FieldsType = std::tuple<LiteralHelper<fields_>...>;
|
using FieldsType = std::tuple<LiteralHelper<fields_>...>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ValueType =
|
using ValueType = std::conditional_t<
|
||||||
std::conditional_t<sizeof...(fields_) <=
|
sizeof...(fields_) <= std::numeric_limits<std::uint8_t>::max(),
|
||||||
std::numeric_limits<std::uint8_t>::max(),
|
std::uint8_t,
|
||||||
std::uint8_t,
|
std::uint16_t>;
|
||||||
std::uint16_t>;
|
|
||||||
|
|
||||||
/// The number of different fields or different options that the literal
|
/// The number of different fields or different options that the literal
|
||||||
/// can assume.
|
/// can assume.
|
||||||
|
@ -47,8 +46,9 @@ namespace rfl {
|
||||||
|
|
||||||
/// A single-field literal is special because it
|
/// A single-field literal is special because it
|
||||||
/// can also have a default constructor.
|
/// can also have a default constructor.
|
||||||
template <ValueType num_fields = num_fields_,
|
template <
|
||||||
typename = std::enable_if_t<num_fields <= 1>>
|
ValueType num_fields = num_fields_,
|
||||||
|
typename = std::enable_if_t<num_fields <= 1>>
|
||||||
Literal() : value_(0) {}
|
Literal() : value_(0) {}
|
||||||
|
|
||||||
~Literal() = default;
|
~Literal() = default;
|
||||||
|
@ -69,8 +69,9 @@ namespace rfl {
|
||||||
/// Constructs a new Literal.
|
/// Constructs a new Literal.
|
||||||
template <ValueType _value>
|
template <ValueType _value>
|
||||||
static Literal<fields_...> from_value() {
|
static Literal<fields_...> from_value() {
|
||||||
static_assert(_value < num_fields_,
|
static_assert(
|
||||||
"Value cannot exceed number of fields.");
|
_value < num_fields_, "Value cannot exceed number of fields."
|
||||||
|
);
|
||||||
return Literal<fields_...>(_value);
|
return Literal<fields_...>(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +156,8 @@ namespace rfl {
|
||||||
Literal<fields_...>& operator=(const Literal<fields_...>& _other) = default;
|
Literal<fields_...>& operator=(const Literal<fields_...>& _other) = default;
|
||||||
|
|
||||||
/// Assigns from another literal.
|
/// Assigns from another literal.
|
||||||
Literal<fields_...>& operator=(Literal<fields_...>&& _other) noexcept =
|
Literal<fields_...>& operator=(Literal<fields_...>&& _other
|
||||||
default;
|
) noexcept = default;
|
||||||
|
|
||||||
/// Assigns the literal from a string
|
/// Assigns the literal from a string
|
||||||
Literal<fields_...>& operator=(const std::string& _str) {
|
Literal<fields_...>& operator=(const std::string& _str) {
|
||||||
|
@ -221,7 +222,7 @@ namespace rfl {
|
||||||
|
|
||||||
/// Returns all of the allowed fields.
|
/// Returns all of the allowed fields.
|
||||||
static std::string allowed_strings() {
|
static std::string allowed_strings() {
|
||||||
const auto vec = allowed_strings_vec();
|
const auto vec = allowed_strings_vec();
|
||||||
std::string str;
|
std::string str;
|
||||||
for (size_t i = 0; i < vec.size(); ++i) {
|
for (size_t i = 0; i < vec.size(); ++i) {
|
||||||
const auto head = "'" + vec[i] + "'";
|
const auto head = "'" + vec[i] + "'";
|
||||||
|
@ -233,7 +234,8 @@ namespace rfl {
|
||||||
/// Returns all of the allowed fields.
|
/// Returns all of the allowed fields.
|
||||||
template <int _i = 0>
|
template <int _i = 0>
|
||||||
static std::vector<std::string> allowed_strings_vec(
|
static std::vector<std::string> allowed_strings_vec(
|
||||||
std::vector<std::string> _values = {}) {
|
std::vector<std::string> _values = {}
|
||||||
|
) {
|
||||||
using FieldType = typename std::tuple_element<_i, FieldsType>::type;
|
using FieldType = typename std::tuple_element<_i, FieldsType>::type;
|
||||||
const auto head = FieldType::field_.str();
|
const auto head = FieldType::field_.str();
|
||||||
_values.push_back(head);
|
_values.push_back(head);
|
||||||
|
@ -297,9 +299,10 @@ namespace rfl {
|
||||||
using FieldType = typename std::tuple_element<_i, FieldsType>::type;
|
using FieldType = typename std::tuple_element<_i, FieldsType>::type;
|
||||||
if (FieldType::field_.str() == _str) { return _i; }
|
if (FieldType::field_.str() == _str) { return _i; }
|
||||||
if constexpr (_i + 1 == num_fields_) {
|
if constexpr (_i + 1 == num_fields_) {
|
||||||
return Error("Literal does not support string '" + _str +
|
return Error(
|
||||||
"'. The following strings are supported: " +
|
"Literal does not support string '" + _str +
|
||||||
allowed_strings() + ".");
|
"'. The following strings are supported: " + allowed_strings() + "."
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return find_value<_i + 1>(_str);
|
return find_value<_i + 1>(_str);
|
||||||
}
|
}
|
||||||
|
@ -336,11 +339,15 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sizeof...(fields_) <= std::numeric_limits<ValueType>::max(),
|
static_assert(
|
||||||
"Too many fields.");
|
sizeof...(fields_) <= std::numeric_limits<ValueType>::max(),
|
||||||
|
"Too many fields."
|
||||||
|
);
|
||||||
|
|
||||||
static_assert(sizeof...(fields_) <= 1 || !has_duplicates(),
|
static_assert(
|
||||||
"Duplicate strings are not allowed in a Literal.");
|
sizeof...(fields_) <= 1 || !has_duplicates(),
|
||||||
|
"Duplicate strings are not allowed in a Literal."
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The underlying value.
|
/// The underlying value.
|
||||||
|
|
|
@ -39,46 +39,56 @@ namespace rfl {
|
||||||
NamedTuple(typename std::remove_cvref<FieldTypes>::type::Type&&... _values)
|
NamedTuple(typename std::remove_cvref<FieldTypes>::type::Type&&... _values)
|
||||||
: values_(
|
: values_(
|
||||||
std::forward<typename std::remove_cvref<FieldTypes>::type::Type>(
|
std::forward<typename std::remove_cvref<FieldTypes>::type::Type>(
|
||||||
_values)...) {
|
_values
|
||||||
static_assert(no_duplicate_field_names(),
|
)...
|
||||||
"Duplicate field names are not allowed");
|
) {
|
||||||
|
static_assert(
|
||||||
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from the values.
|
/// Construct from the values.
|
||||||
NamedTuple(
|
NamedTuple(
|
||||||
const typename std::remove_cvref<FieldTypes>::type::Type&... _values)
|
const typename std::remove_cvref<FieldTypes>::type::Type&... _values
|
||||||
|
)
|
||||||
: values_(std::make_tuple(_values...)) {
|
: values_(std::make_tuple(_values...)) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from the fields.
|
/// Construct from the fields.
|
||||||
NamedTuple(FieldTypes&&... _fields)
|
NamedTuple(FieldTypes&&... _fields)
|
||||||
: values_(std::make_tuple(std::move(_fields.value_)...)) {
|
: values_(std::make_tuple(std::move(_fields.value_)...)) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from the fields.
|
/// Construct from the fields.
|
||||||
NamedTuple(const FieldTypes&... _fields)
|
NamedTuple(const FieldTypes&... _fields)
|
||||||
: values_(std::make_tuple(_fields.value_...)) {
|
: values_(std::make_tuple(_fields.value_...)) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from a tuple containing fields.
|
/// Construct from a tuple containing fields.
|
||||||
NamedTuple(std::tuple<FieldTypes...>&& _tup)
|
NamedTuple(std::tuple<FieldTypes...>&& _tup)
|
||||||
: NamedTuple(std::make_from_tuple<NamedTuple<FieldTypes...>>(
|
: NamedTuple(std::make_from_tuple<NamedTuple<FieldTypes...>>(
|
||||||
std::forward<std::tuple<FieldTypes...>>(_tup))) {
|
std::forward<std::tuple<FieldTypes...>>(_tup)
|
||||||
static_assert(no_duplicate_field_names(),
|
)) {
|
||||||
"Duplicate field names are not allowed");
|
static_assert(
|
||||||
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from a tuple containing fields.
|
/// Construct from a tuple containing fields.
|
||||||
NamedTuple(const std::tuple<FieldTypes...>& _tup)
|
NamedTuple(const std::tuple<FieldTypes...>& _tup)
|
||||||
: NamedTuple(std::make_from_tuple<NamedTuple<FieldTypes...>>(_tup)) {
|
: NamedTuple(std::make_from_tuple<NamedTuple<FieldTypes...>>(_tup)) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
|
@ -91,16 +101,18 @@ namespace rfl {
|
||||||
template <class... OtherFieldTypes>
|
template <class... OtherFieldTypes>
|
||||||
NamedTuple(const NamedTuple<OtherFieldTypes...>& _other)
|
NamedTuple(const NamedTuple<OtherFieldTypes...>& _other)
|
||||||
: NamedTuple(retrieve_fields(_other.fields())) {
|
: NamedTuple(retrieve_fields(_other.fields())) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move constructor.
|
/// Move constructor.
|
||||||
template <class... OtherFieldTypes>
|
template <class... OtherFieldTypes>
|
||||||
NamedTuple(NamedTuple<OtherFieldTypes...>&& _other)
|
NamedTuple(NamedTuple<OtherFieldTypes...>&& _other)
|
||||||
: NamedTuple(retrieve_fields(_other.fields())) {
|
: NamedTuple(retrieve_fields(_other.fields())) {
|
||||||
static_assert(no_duplicate_field_names(),
|
static_assert(
|
||||||
"Duplicate field names are not allowed");
|
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
~NamedTuple() = default;
|
~NamedTuple() = default;
|
||||||
|
@ -111,11 +123,13 @@ namespace rfl {
|
||||||
using Head = Field<_name, FType>;
|
using Head = Field<_name, FType>;
|
||||||
if constexpr (sizeof...(Tail) > 0) {
|
if constexpr (sizeof...(Tail) > 0) {
|
||||||
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
||||||
make_fields<1, Head>(std::forward<Head>(_head)))
|
make_fields<1, Head>(std::forward<Head>(_head))
|
||||||
|
)
|
||||||
.add(std::forward<Tail>(_tail)...);
|
.add(std::forward<Tail>(_tail)...);
|
||||||
} else {
|
} else {
|
||||||
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
||||||
make_fields<1, Head>(std::forward<Head>(_head)));
|
make_fields<1, Head>(std::forward<Head>(_head))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +139,13 @@ namespace rfl {
|
||||||
using Head = Field<_name, FType>;
|
using Head = Field<_name, FType>;
|
||||||
if constexpr (sizeof...(Tail) > 0) {
|
if constexpr (sizeof...(Tail) > 0) {
|
||||||
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
||||||
make_fields<1, Head>(_head))
|
make_fields<1, Head>(_head)
|
||||||
|
)
|
||||||
.add(_tail...);
|
.add(_tail...);
|
||||||
} else {
|
} else {
|
||||||
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
|
||||||
make_fields<1, Head>(_head));
|
make_fields<1, Head>(_head)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,15 +176,17 @@ namespace rfl {
|
||||||
/// named tuples.
|
/// named tuples.
|
||||||
template <class... TupContent, class... Tail>
|
template <class... TupContent, class... Tail>
|
||||||
auto add(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
|
auto add(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
|
||||||
return add(std::forward<std::tuple<TupContent...>>(_named_tuple.fields()),
|
return add(
|
||||||
std::forward<Tail>(_tail)...);
|
std::forward<std::tuple<TupContent...>>(_named_tuple.fields()),
|
||||||
|
std::forward<Tail>(_tail)...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Template specialization for NamedTuple, so we can pass fields from other
|
/// Template specialization for NamedTuple, so we can pass fields from other
|
||||||
/// named tuples.
|
/// named tuples.
|
||||||
template <class... TupContent, class... Tail>
|
template <class... TupContent, class... Tail>
|
||||||
auto add(NamedTuple<TupContent...> _named_tuple,
|
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail)
|
||||||
const Tail&... _tail) const {
|
const {
|
||||||
return add(_named_tuple.fields(), _tail...);
|
return add(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,11 +197,9 @@ namespace rfl {
|
||||||
const auto transform_field = [&_f](auto... _fields) {
|
const auto transform_field = [&_f](auto... _fields) {
|
||||||
return std::tuple_cat(_f(std::move(_fields)).fields()...);
|
return std::tuple_cat(_f(std::move(_fields)).fields()...);
|
||||||
};
|
};
|
||||||
const auto to_nt =
|
const auto to_nt = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
||||||
[]<class... NewFields>(std::tuple<NewFields...>&& _tup) {
|
) { return NamedTuple<NewFields...>(_tup); };
|
||||||
return NamedTuple<NewFields...>(_tup);
|
auto new_fields = std::apply(transform_field, std::move(fields()));
|
||||||
};
|
|
||||||
auto new_fields = std::apply(transform_field, std::move(fields()));
|
|
||||||
return to_nt(std::move(new_fields));
|
return to_nt(std::move(new_fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,21 +210,19 @@ namespace rfl {
|
||||||
const auto transform_field = [&_f](auto... _fields) {
|
const auto transform_field = [&_f](auto... _fields) {
|
||||||
return std::tuple_cat(_f(std::move(_fields)).fields()...);
|
return std::tuple_cat(_f(std::move(_fields)).fields()...);
|
||||||
};
|
};
|
||||||
const auto to_nt =
|
const auto to_nt = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
||||||
[]<class... NewFields>(std::tuple<NewFields...>&& _tup) {
|
) { return NamedTuple<NewFields...>(_tup); };
|
||||||
return NamedTuple<NewFields...>(_tup);
|
auto new_fields = std::apply(transform_field, std::move(fields()));
|
||||||
};
|
|
||||||
auto new_fields = std::apply(transform_field, std::move(fields()));
|
|
||||||
return to_nt(std::move(new_fields));
|
return to_nt(std::move(new_fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes a callable object once for each field in order.
|
/// Invokes a callable object once for each field in order.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void apply(F&& _f) {
|
void apply(F&& _f) {
|
||||||
const auto apply_to_field =
|
const auto apply_to_field = [&_f]<typename... AFields>(AFields&&... fields
|
||||||
[&_f]<typename... AFields>(AFields&&... fields) {
|
) {
|
||||||
((_f(std::forward<AFields>(fields))), ...);
|
((_f(std::forward<AFields>(fields))), ...);
|
||||||
};
|
};
|
||||||
std::apply(apply_to_field, fields());
|
std::apply(apply_to_field, fields());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,12 +284,12 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy assignment operator.
|
/// Copy assignment operator.
|
||||||
NamedTuple<FieldTypes...>& operator=(
|
NamedTuple<FieldTypes...>& operator=(const NamedTuple<FieldTypes...>& _other
|
||||||
const NamedTuple<FieldTypes...>& _other) = default;
|
) = default;
|
||||||
|
|
||||||
/// Move assignment operator.
|
/// Move assignment operator.
|
||||||
NamedTuple<FieldTypes...>& operator=(
|
NamedTuple<FieldTypes...>& operator=(NamedTuple<FieldTypes...>&& _other
|
||||||
NamedTuple<FieldTypes...>&& _other) noexcept = default;
|
) noexcept = default;
|
||||||
|
|
||||||
/// Equality operator
|
/// Equality operator
|
||||||
inline auto operator==(const rfl::NamedTuple<FieldTypes...>& _other) const {
|
inline auto operator==(const rfl::NamedTuple<FieldTypes...>& _other) const {
|
||||||
|
@ -289,8 +303,8 @@ namespace rfl {
|
||||||
/// Replaces one or several fields, returning a new version
|
/// Replaces one or several fields, returning a new version
|
||||||
/// with the non-replaced fields left unchanged.
|
/// with the non-replaced fields left unchanged.
|
||||||
template <internal::StringLiteral _name, class FType, class... OtherRFields>
|
template <internal::StringLiteral _name, class FType, class... OtherRFields>
|
||||||
auto replace(Field<_name, FType>&& _field,
|
auto
|
||||||
OtherRFields&&... _other_fields) {
|
replace(Field<_name, FType>&& _field, OtherRFields&&... _other_fields) {
|
||||||
using RField = Field<_name, FType>;
|
using RField = Field<_name, FType>;
|
||||||
constexpr auto num_other_fields = sizeof...(OtherRFields);
|
constexpr auto num_other_fields = sizeof...(OtherRFields);
|
||||||
if constexpr (num_other_fields == 0) {
|
if constexpr (num_other_fields == 0) {
|
||||||
|
@ -304,8 +318,10 @@ namespace rfl {
|
||||||
/// Replaces one or several fields, returning a new version
|
/// Replaces one or several fields, returning a new version
|
||||||
/// with the non-replaced fields left unchanged.
|
/// with the non-replaced fields left unchanged.
|
||||||
template <internal::StringLiteral _name, class FType, class... OtherRFields>
|
template <internal::StringLiteral _name, class FType, class... OtherRFields>
|
||||||
auto replace(Field<_name, FType> _field,
|
auto replace(
|
||||||
const OtherRFields&... _other_fields) const {
|
Field<_name, FType> _field,
|
||||||
|
const OtherRFields&... _other_fields
|
||||||
|
) const {
|
||||||
using RField = Field<_name, FType>;
|
using RField = Field<_name, FType>;
|
||||||
constexpr auto num_other_fields = sizeof...(OtherRFields);
|
constexpr auto num_other_fields = sizeof...(OtherRFields);
|
||||||
if constexpr (num_other_fields == 0) {
|
if constexpr (num_other_fields == 0) {
|
||||||
|
@ -345,14 +361,15 @@ namespace rfl {
|
||||||
auto replace(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
|
auto replace(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
|
||||||
return replace(
|
return replace(
|
||||||
std::forward<NamedTuple<TupContent...>>(_named_tuple).fields(),
|
std::forward<NamedTuple<TupContent...>>(_named_tuple).fields(),
|
||||||
std::forward<Tail>(_tail)...);
|
std::forward<Tail>(_tail)...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Template specialization for NamedTuple, so we can pass fields from other
|
/// Template specialization for NamedTuple, so we can pass fields from other
|
||||||
/// named tuples.
|
/// named tuples.
|
||||||
template <class... TupContent, class... Tail>
|
template <class... TupContent, class... Tail>
|
||||||
auto replace(NamedTuple<TupContent...> _named_tuple,
|
auto replace(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail)
|
||||||
const Tail&... _tail) const {
|
const {
|
||||||
return replace(_named_tuple.fields(), _tail...);
|
return replace(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,11 +383,9 @@ namespace rfl {
|
||||||
const auto transform_field = [&_f](auto... fields) {
|
const auto transform_field = [&_f](auto... fields) {
|
||||||
return std::make_tuple(_f(std::move(fields))...);
|
return std::make_tuple(_f(std::move(fields))...);
|
||||||
};
|
};
|
||||||
const auto to_nt =
|
const auto to_nt = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
||||||
[]<class... NewFields>(std::tuple<NewFields...>&& _tup) {
|
) { return NamedTuple<NewFields...>(_tup); };
|
||||||
return NamedTuple<NewFields...>(_tup);
|
auto new_fields = std::apply(transform_field, std::move(fields()));
|
||||||
};
|
|
||||||
auto new_fields = std::apply(transform_field, std::move(fields()));
|
|
||||||
return to_nt(std::move(new_fields));
|
return to_nt(std::move(new_fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,11 +396,9 @@ namespace rfl {
|
||||||
const auto transform_field = [&_f](auto... fields) {
|
const auto transform_field = [&_f](auto... fields) {
|
||||||
return std::make_tuple(_f(std::move(fields))...);
|
return std::make_tuple(_f(std::move(fields))...);
|
||||||
};
|
};
|
||||||
const auto to_nt =
|
const auto to_nt = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
||||||
[]<class... NewFields>(std::tuple<NewFields...>&& _tup) {
|
) { return NamedTuple<NewFields...>(_tup); };
|
||||||
return NamedTuple<NewFields...>(_tup);
|
auto new_fields = std::apply(transform_field, std::move(fields()));
|
||||||
};
|
|
||||||
auto new_fields = std::apply(transform_field, std::move(fields()));
|
|
||||||
return to_nt(std::move(new_fields));
|
return to_nt(std::move(new_fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +447,8 @@ namespace rfl {
|
||||||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||||
return make_fields<num_additional_fields>(
|
return make_fields<num_additional_fields>(
|
||||||
FieldType(std::forward<T>(std::get<i>(values_))),
|
FieldType(std::forward<T>(std::get<i>(values_))),
|
||||||
std::forward<Args>(_args)...);
|
std::forward<Args>(_args)...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +468,8 @@ namespace rfl {
|
||||||
// them to the end, that is why we do it like this.
|
// them to the end, that is why we do it like this.
|
||||||
using FieldType = typename std::tuple_element<i, Fields>::type;
|
using FieldType = typename std::tuple_element<i, Fields>::type;
|
||||||
return make_fields<num_additional_fields>(
|
return make_fields<num_additional_fields>(
|
||||||
FieldType(std::get<i>(values_)), std::move(_args)...);
|
FieldType(std::get<i>(values_)), std::move(_args)...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,13 +488,15 @@ namespace rfl {
|
||||||
if constexpr (size == _index) {
|
if constexpr (size == _index) {
|
||||||
return make_replaced<_index, V, T>(
|
return make_replaced<_index, V, T>(
|
||||||
std::forward<V>(_values), std::forward<T>(_val),
|
std::forward<V>(_values), std::forward<T>(_val),
|
||||||
std::forward<Args>(_args)..., FieldType(std::forward<T>(_val)));
|
std::forward<Args>(_args)..., FieldType(std::forward<T>(_val))
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
using U = typename FieldType::Type;
|
using U = typename FieldType::Type;
|
||||||
return make_replaced<_index, V, T>(
|
return make_replaced<_index, V, T>(
|
||||||
std::forward<V>(_values), std::forward<T>(_val),
|
std::forward<V>(_values), std::forward<T>(_val),
|
||||||
std::forward<Args>(_args)...,
|
std::forward<Args>(_args)...,
|
||||||
FieldType(std::forward<U>(std::get<size>(_values))));
|
FieldType(std::forward<U>(std::get<size>(_values)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,18 +511,20 @@ namespace rfl {
|
||||||
NamedTuple<FieldTypes...> replace_value(T&& _val) {
|
NamedTuple<FieldTypes...> replace_value(T&& _val) {
|
||||||
using FieldType = std::remove_cvref_t<Field>;
|
using FieldType = std::remove_cvref_t<Field>;
|
||||||
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
|
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
|
||||||
return make_replaced<index, Values, T>(std::forward<Values>(values_),
|
return make_replaced<index, Values, T>(
|
||||||
std::forward<T>(_val));
|
std::forward<Values>(values_), std::forward<T>(_val)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaced the field signified by the field type.
|
/// Replaced the field signified by the field type.
|
||||||
template <class Field, class T>
|
template <class Field, class T>
|
||||||
NamedTuple<FieldTypes...> replace_value(T&& _val) const {
|
NamedTuple<FieldTypes...> replace_value(T&& _val) const {
|
||||||
using FieldType = std::remove_cvref_t<Field>;
|
using FieldType = std::remove_cvref_t<Field>;
|
||||||
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
|
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
|
||||||
auto values = values_;
|
auto values = values_;
|
||||||
return make_replaced<index, Values, T>(std::move(values),
|
return make_replaced<index, Values, T>(
|
||||||
std::forward<T>(_val));
|
std::move(values), std::forward<T>(_val)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the elements of a tuple to a newly created named tuple,
|
/// Adds the elements of a tuple to a newly created named tuple,
|
||||||
|
@ -532,7 +551,8 @@ namespace rfl {
|
||||||
template <class... OtherFieldTypes, class... Args>
|
template <class... OtherFieldTypes, class... Args>
|
||||||
constexpr static Fields retrieve_fields(
|
constexpr static Fields retrieve_fields(
|
||||||
std::tuple<OtherFieldTypes...>&& _other_fields,
|
std::tuple<OtherFieldTypes...>&& _other_fields,
|
||||||
Args&&... _args) {
|
Args&&... _args
|
||||||
|
) {
|
||||||
constexpr auto size = sizeof...(Args);
|
constexpr auto size = sizeof...(Args);
|
||||||
|
|
||||||
constexpr bool retrieved_all_fields = size == std::tuple_size_v<Fields>;
|
constexpr bool retrieved_all_fields = size == std::tuple_size_v<Fields>;
|
||||||
|
@ -553,7 +573,8 @@ namespace rfl {
|
||||||
return retrieve_fields(
|
return retrieve_fields(
|
||||||
std::forward<std::tuple<OtherFieldTypes...>>(_other_fields),
|
std::forward<std::tuple<OtherFieldTypes...>>(_other_fields),
|
||||||
std::forward<Args>(_args)...,
|
std::forward<Args>(_args)...,
|
||||||
FieldType(std::forward<T>(std::get<index>(_other_fields).value_)));
|
FieldType(std::forward<T>(std::get<index>(_other_fields).value_))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,8 +624,8 @@ namespace rfl {
|
||||||
/// Template specialization for NamedTuple, so we can pass fields from other
|
/// Template specialization for NamedTuple, so we can pass fields from other
|
||||||
/// named tuples.
|
/// named tuples.
|
||||||
template <class... TupContent, class... Tail>
|
template <class... TupContent, class... Tail>
|
||||||
auto add(NamedTuple<TupContent...> _named_tuple,
|
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail)
|
||||||
const Tail&... _tail) const {
|
const {
|
||||||
return add(_named_tuple.fields(), _tail...);
|
return add(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,59 +657,73 @@ namespace rfl {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <internal::StringLiteral _name1,
|
template <
|
||||||
class Type1,
|
internal::StringLiteral _name1,
|
||||||
internal::StringLiteral _name2,
|
class Type1,
|
||||||
class Type2>
|
internal::StringLiteral _name2,
|
||||||
inline auto operator*(const rfl::Field<_name1, Type1>& _f1,
|
class Type2>
|
||||||
const rfl::Field<_name2, Type2>& _f2) {
|
inline auto operator*(
|
||||||
|
const rfl::Field<_name1, Type1>& _f1,
|
||||||
|
const rfl::Field<_name2, Type2>& _f2
|
||||||
|
) {
|
||||||
return NamedTuple(_f1, _f2);
|
return NamedTuple(_f1, _f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
||||||
inline auto operator*(const NamedTuple<FieldTypes...>& _tup,
|
inline auto operator*(
|
||||||
const rfl::Field<_name, Type>& _f) {
|
const NamedTuple<FieldTypes...>& _tup,
|
||||||
|
const rfl::Field<_name, Type>& _f
|
||||||
|
) {
|
||||||
return _tup.add(_f);
|
return _tup.add(_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
||||||
inline auto operator*(const rfl::Field<_name, Type>& _f,
|
inline auto operator*(
|
||||||
const NamedTuple<FieldTypes...>& _tup) {
|
const rfl::Field<_name, Type>& _f,
|
||||||
|
const NamedTuple<FieldTypes...>& _tup
|
||||||
|
) {
|
||||||
return NamedTuple(_f).add(_tup);
|
return NamedTuple(_f).add(_tup);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... FieldTypes1, class... FieldTypes2>
|
template <class... FieldTypes1, class... FieldTypes2>
|
||||||
inline auto operator*(const NamedTuple<FieldTypes1...>& _tup1,
|
inline auto operator*(
|
||||||
const NamedTuple<FieldTypes2...>& _tup2) {
|
const NamedTuple<FieldTypes1...>& _tup1,
|
||||||
|
const NamedTuple<FieldTypes2...>& _tup2
|
||||||
|
) {
|
||||||
return _tup1.add(_tup2);
|
return _tup1.add(_tup2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name1,
|
template <
|
||||||
class Type1,
|
internal::StringLiteral _name1,
|
||||||
internal::StringLiteral _name2,
|
class Type1,
|
||||||
class Type2>
|
internal::StringLiteral _name2,
|
||||||
inline auto operator*(rfl::Field<_name1, Type1>&& _f1,
|
class Type2>
|
||||||
rfl::Field<_name2, Type2>&& _f2) {
|
inline auto
|
||||||
return NamedTuple(std::forward<Field<_name1, Type1>>(_f1),
|
operator*(rfl::Field<_name1, Type1>&& _f1, rfl::Field<_name2, Type2>&& _f2) {
|
||||||
std::forward<Field<_name2, Type2>>(_f2));
|
return NamedTuple(
|
||||||
|
std::forward<Field<_name1, Type1>>(_f1),
|
||||||
|
std::forward<Field<_name2, Type2>>(_f2)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
||||||
inline auto operator*(NamedTuple<FieldTypes...>&& _tup,
|
inline auto
|
||||||
rfl::Field<_name, Type>&& _f) {
|
operator*(NamedTuple<FieldTypes...>&& _tup, rfl::Field<_name, Type>&& _f) {
|
||||||
return _tup.add(std::forward<Field<_name, Type>>(_f));
|
return _tup.add(std::forward<Field<_name, Type>>(_f));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
||||||
inline auto operator*(rfl::Field<_name, Type>&& _f,
|
inline auto
|
||||||
NamedTuple<FieldTypes...>&& _tup) {
|
operator*(rfl::Field<_name, Type>&& _f, NamedTuple<FieldTypes...>&& _tup) {
|
||||||
return NamedTuple(std::forward<Field<_name, Type>>(_f))
|
return NamedTuple(std::forward<Field<_name, Type>>(_f))
|
||||||
.add(std::forward<NamedTuple<FieldTypes...>>(_tup));
|
.add(std::forward<NamedTuple<FieldTypes...>>(_tup));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... FieldTypes1, class... FieldTypes2>
|
template <class... FieldTypes1, class... FieldTypes2>
|
||||||
inline auto operator*(NamedTuple<FieldTypes1...>&& _tup1,
|
inline auto operator*(
|
||||||
NamedTuple<FieldTypes2...>&& _tup2) {
|
NamedTuple<FieldTypes1...>&& _tup1,
|
||||||
|
NamedTuple<FieldTypes2...>&& _tup2
|
||||||
|
) {
|
||||||
return _tup1.add(std::forward<NamedTuple<FieldTypes2...>>(_tup2));
|
return _tup1.add(std::forward<NamedTuple<FieldTypes2...>>(_tup2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace rfl {
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto types = std::vector<ValidationType>(
|
const auto types = std::vector<ValidationType>(
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...});
|
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
||||||
|
);
|
||||||
return ValidationType {ValidationType::OneOf {.types_ = types}};
|
return ValidationType {ValidationType::OneOf {.types_ = types}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class Head, class... Tail>
|
template <class T, class Head, class... Tail>
|
||||||
static rfl::Result<T> validate_impl(const T& _value,
|
static rfl::Result<T>
|
||||||
std::vector<Error> _errors) {
|
validate_impl(const T& _value, std::vector<Error> _errors) {
|
||||||
const auto push_back = [&](Error&& _err) -> rfl::Result<T> {
|
const auto push_back = [&](Error&& _err) -> rfl::Result<T> {
|
||||||
_errors.emplace_back(std::forward<Error>(_err));
|
_errors.emplace_back(std::forward<Error>(_err));
|
||||||
return _err;
|
return _err;
|
||||||
|
@ -55,7 +56,8 @@ namespace rfl {
|
||||||
return make_error_message(_errors);
|
return make_error_message(_errors);
|
||||||
} else {
|
} else {
|
||||||
return validate_impl<T, Tail...>(
|
return validate_impl<T, Tail...>(
|
||||||
_value, std::forward<std::vector<Error>>(_errors));
|
_value, std::forward<std::vector<Error>>(_errors)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@ namespace rfl {
|
||||||
if (ctre::match<_regex.arr_>(_str)) {
|
if (ctre::match<_regex.arr_>(_str)) {
|
||||||
return _str;
|
return _str;
|
||||||
} else {
|
} else {
|
||||||
return rfl::Error("String '" + _str + "' did not match format '" +
|
return rfl::Error(
|
||||||
_name.str() + "': '" + _regex.str() + "'.");
|
"String '" + _str + "' did not match format '" + _name.str() +
|
||||||
|
"': '" + _regex.str() + "'."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,15 @@ namespace rfl {
|
||||||
|
|
||||||
template <class Head, class... Tail>
|
template <class Head, class... Tail>
|
||||||
struct Processors<Head, Tail...> {
|
struct Processors<Head, Tail...> {
|
||||||
static constexpr bool all_required_ =
|
static constexpr bool all_required_ = std::disjunction_v<
|
||||||
std::disjunction_v<internal::is_no_optionals<Head>,
|
internal::is_no_optionals<Head>,
|
||||||
internal::is_no_optionals<Tail>...>;
|
internal::is_no_optionals<Tail>...>;
|
||||||
|
|
||||||
template <class T, class NamedTupleType>
|
template <class T, class NamedTupleType>
|
||||||
static auto process(NamedTupleType&& _named_tuple) {
|
static auto process(NamedTupleType&& _named_tuple) {
|
||||||
return Processors<Tail...>::template process<T>(
|
return Processors<Tail...>::template process<T>(
|
||||||
Head::template process<T>(std::move(_named_tuple)));
|
Head::template process<T>(std::move(_named_tuple))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -116,9 +116,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class CharT, class Traits, class T>
|
template <class CharT, class Traits, class T>
|
||||||
inline std::basic_ostream<CharT, Traits>& operator<<(
|
inline std::basic_ostream<CharT, Traits>&
|
||||||
std::basic_ostream<CharT, Traits>& _os,
|
operator<<(std::basic_ostream<CharT, Traits>& _os, const Ref<T>& _b) {
|
||||||
const Ref<T>& _b) {
|
|
||||||
_os << _b.get();
|
_os << _b.get();
|
||||||
return _os;
|
return _os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,25 +39,29 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Rename(Rename<_name, U>&& _field) : value_(_field.get()) {}
|
Rename(Rename<_name, U>&& _field) : value_(_field.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Rename(const U& _value) : value_(_value) {}
|
Rename(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Rename(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
Rename(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Rename(const Rename<_name, U>& _field) : value_(_field.value()) {}
|
Rename(const Rename<_name, U>& _field) : value_(_field.value()) {}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
Rename(const Default& _default) : value_(Type()) {}
|
Rename(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Rename() = default;
|
~Rename() = default;
|
||||||
|
@ -87,18 +91,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -40,8 +40,10 @@ namespace rfl {
|
||||||
/// The Result class is used for monadic error handling.
|
/// The Result class is used for monadic error handling.
|
||||||
template <class T>
|
template <class T>
|
||||||
class Result {
|
class Result {
|
||||||
static_assert(!std::is_same<T, Error>(),
|
static_assert(
|
||||||
"The result type cannot be Error.");
|
!std::is_same<T, Error>(),
|
||||||
|
"The result type cannot be Error."
|
||||||
|
);
|
||||||
|
|
||||||
using TOrErr =
|
using TOrErr =
|
||||||
std::array<unsigned char, std::max(sizeof(T), sizeof(Error))>;
|
std::array<unsigned char, std::max(sizeof(T), sizeof(Error))>;
|
||||||
|
@ -75,8 +77,9 @@ namespace rfl {
|
||||||
class U,
|
class U,
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
Result(Result<U>&& _other) : success_(_other && true) {
|
Result(Result<U>&& _other) : success_(_other && true) {
|
||||||
auto temp = std::forward<Result<U>>(_other).transform(
|
auto temp = std::forward<Result<U>>(_other).transform([](U&& _u) {
|
||||||
[](U&& _u) { return T(std::forward<U>(_u)); });
|
return T(std::forward<U>(_u));
|
||||||
|
});
|
||||||
move_from_other(temp);
|
move_from_other(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,11 @@ namespace rfl {
|
||||||
/// Applies the logic to a single field.
|
/// Applies the logic to a single field.
|
||||||
template <class FieldType>
|
template <class FieldType>
|
||||||
static auto handle_one_field(FieldType&& _f) {
|
static auto handle_one_field(FieldType&& _f) {
|
||||||
using NewFieldType =
|
using NewFieldType = Field<
|
||||||
Field<internal::transform_snake_case<FieldType::name_,
|
internal::transform_snake_case<
|
||||||
/*capitalize=*/false>(),
|
FieldType::name_,
|
||||||
typename FieldType::Type>;
|
/*capitalize=*/false>(),
|
||||||
|
typename FieldType::Type>;
|
||||||
return NewFieldType(_f.value());
|
return NewFieldType(_f.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,10 +25,11 @@ namespace rfl {
|
||||||
/// Applies the logic to a single field.
|
/// Applies the logic to a single field.
|
||||||
template <class FieldType>
|
template <class FieldType>
|
||||||
static auto handle_one_field(FieldType&& _f) {
|
static auto handle_one_field(FieldType&& _f) {
|
||||||
using NewFieldType =
|
using NewFieldType = Field<
|
||||||
Field<internal::transform_snake_case<FieldType::name_,
|
internal::transform_snake_case<
|
||||||
/*capitalize=*/true>(),
|
FieldType::name_,
|
||||||
typename FieldType::Type>;
|
/*capitalize=*/true>(),
|
||||||
|
typename FieldType::Type>;
|
||||||
return NewFieldType(_f.value());
|
return NewFieldType(_f.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,20 +27,22 @@ namespace rfl {
|
||||||
TaggedUnion(VariantType&& _variant) noexcept
|
TaggedUnion(VariantType&& _variant) noexcept
|
||||||
: variant_(std::move(_variant)) {}
|
: variant_(std::move(_variant)) {}
|
||||||
|
|
||||||
TaggedUnion(const TaggedUnion<_discriminator, Ts...>& _tagged_union) =
|
TaggedUnion(const TaggedUnion<_discriminator, Ts...>& _tagged_union
|
||||||
default;
|
) = default;
|
||||||
|
|
||||||
TaggedUnion(TaggedUnion<_discriminator, Ts...>&& _tagged_union) noexcept =
|
TaggedUnion(TaggedUnion<_discriminator, Ts...>&& _tagged_union
|
||||||
default;
|
) noexcept = default;
|
||||||
|
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
TaggedUnion(const T& _t) : variant_(_t) {}
|
TaggedUnion(const T& _t) : variant_(_t) {}
|
||||||
|
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
TaggedUnion(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
TaggedUnion(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
||||||
|
|
||||||
~TaggedUnion() = default;
|
~TaggedUnion() = default;
|
||||||
|
@ -58,18 +60,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(T&& _variant) {
|
TaggedUnion<_discriminator, Ts...>& operator=(T&& _variant) {
|
||||||
variant_ = std::forward<T>(_variant);
|
variant_ = std::forward<T>(_variant);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(const T& _variant) {
|
TaggedUnion<_discriminator, Ts...>& operator=(const T& _variant) {
|
||||||
variant_ = _variant;
|
variant_ = _variant;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -77,11 +81,13 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(
|
TaggedUnion<_discriminator, Ts...>& operator=(
|
||||||
const TaggedUnion<_discriminator, Ts...>& _other) = default;
|
const TaggedUnion<_discriminator, Ts...>& _other
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(
|
TaggedUnion<_discriminator, Ts...>& operator=(
|
||||||
TaggedUnion<_discriminator, Ts...>&& _other) = default;
|
TaggedUnion<_discriminator, Ts...>&& _other
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Returns the underlying variant.
|
/// Returns the underlying variant.
|
||||||
VariantType& variant() { return variant_; }
|
VariantType& variant() { return variant_; }
|
||||||
|
@ -89,8 +95,10 @@ namespace rfl {
|
||||||
/// Returns the underlying variant.
|
/// Returns the underlying variant.
|
||||||
const VariantType& variant() const { return variant_; }
|
const VariantType& variant() const { return variant_; }
|
||||||
|
|
||||||
static_assert(!PossibleTags::has_duplicates(),
|
static_assert(
|
||||||
"Duplicate tags are not allowed inside tagged unions.");
|
!PossibleTags::has_duplicates(),
|
||||||
|
"Duplicate tags are not allowed inside tagged unions."
|
||||||
|
);
|
||||||
|
|
||||||
/// The underlying variant - a TaggedUnion is a thin wrapper
|
/// The underlying variant - a TaggedUnion is a thin wrapper
|
||||||
/// around a variant that is mainly used for parsing.
|
/// around a variant that is mainly used for parsing.
|
||||||
|
@ -105,15 +113,18 @@ namespace rfl {
|
||||||
/// Retrieves the indicated value from the tuple.
|
/// Retrieves the indicated value from the tuple.
|
||||||
template <int _index>
|
template <int _index>
|
||||||
static inline auto& get(
|
static inline auto& get(
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<_index>(
|
return Getter<std::variant<NamedTupleTypes...>>::template get<_index>(
|
||||||
_tu.variant_);
|
_tu.variant_
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a field by name.
|
/// Gets a field by name.
|
||||||
template <StringLiteral _field_name>
|
template <StringLiteral _field_name>
|
||||||
static inline auto& get(
|
static inline auto& get(
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<
|
return Getter<std::variant<NamedTupleTypes...>>::template get<
|
||||||
_field_name>(_tu.variant_);
|
_field_name>(_tu.variant_);
|
||||||
}
|
}
|
||||||
|
@ -121,15 +132,18 @@ namespace rfl {
|
||||||
/// Gets a field by the field type.
|
/// Gets a field by the field type.
|
||||||
template <class Field>
|
template <class Field>
|
||||||
static inline auto& get(
|
static inline auto& get(
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<Field>(
|
return Getter<std::variant<NamedTupleTypes...>>::template get<Field>(
|
||||||
_tu.variant_);
|
_tu.variant_
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the indicated value from the tuple.
|
/// Retrieves the indicated value from the tuple.
|
||||||
template <int _index>
|
template <int _index>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
||||||
_index>(_tu.variant_);
|
_index>(_tu.variant_);
|
||||||
}
|
}
|
||||||
|
@ -137,7 +151,8 @@ namespace rfl {
|
||||||
/// Gets a field by name.
|
/// Gets a field by name.
|
||||||
template <StringLiteral _field_name>
|
template <StringLiteral _field_name>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
||||||
_field_name>(_tu.variant_);
|
_field_name>(_tu.variant_);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +160,8 @@ namespace rfl {
|
||||||
/// Gets a field by the field type.
|
/// Gets a field by the field type.
|
||||||
template <class Field>
|
template <class Field>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
|
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu
|
||||||
|
) {
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
|
||||||
Field>(_tu.variant_);
|
Field>(_tu.variant_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,10 @@ namespace rfl {
|
||||||
Timestamp(const char* _str) : tm_(std::tm {}) {
|
Timestamp(const char* _str) : tm_(std::tm {}) {
|
||||||
const auto r = strptime(_str, _format.str().c_str(), &tm_);
|
const auto r = strptime(_str, _format.str().c_str(), &tm_);
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
throw std::runtime_error("String '" + std::string(_str) +
|
throw std::runtime_error(
|
||||||
"' did not match format '" + Format().str() +
|
"String '" + std::string(_str) + "' did not match format '" +
|
||||||
"'.");
|
Format().str() + "'."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,12 +70,12 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Validator<T, V, Vs...>& operator=(const Validator<T, V, Vs...>& _other) =
|
Validator<T, V, Vs...>& operator=(const Validator<T, V, Vs...>& _other
|
||||||
default;
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Validator<T, V, Vs...>& operator=(
|
Validator<T, V, Vs...>& operator=(Validator<T, V, Vs...>&& _other
|
||||||
Validator<T, V, Vs...>&& _other) noexcept = default;
|
) noexcept = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <
|
||||||
|
@ -115,8 +115,10 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class V, class... Vs>
|
template <class T, class V, class... Vs>
|
||||||
inline auto operator<=>(const Validator<T, V, Vs...>& _v1,
|
inline auto operator<=>(
|
||||||
const Validator<T, V, Vs...>& _v2) {
|
const Validator<T, V, Vs...>& _v1,
|
||||||
|
const Validator<T, V, Vs...>& _v2
|
||||||
|
) {
|
||||||
return _v1.value() <=> _v2.value();
|
return _v1.value() <=> _v2.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,16 @@ namespace rfl {
|
||||||
|
|
||||||
Variant(Variant<AlternativeTypes...>&& _variant) noexcept = default;
|
Variant(Variant<AlternativeTypes...>&& _variant) noexcept = default;
|
||||||
|
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
Variant(const T& _t) : variant_(_t) {}
|
Variant(const T& _t) : variant_(_t) {}
|
||||||
|
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
Variant(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
Variant(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
||||||
|
|
||||||
~Variant() = default;
|
~Variant() = default;
|
||||||
|
@ -43,18 +45,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
Variant<AlternativeTypes...>& operator=(T&& _variant) {
|
Variant<AlternativeTypes...>& operator=(T&& _variant) {
|
||||||
variant_ = std::forward<T>(_variant);
|
variant_ = std::forward<T>(_variant);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class T,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>,
|
class T,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
||||||
|
type = true>
|
||||||
Variant<AlternativeTypes...>& operator=(const T& _variant) {
|
Variant<AlternativeTypes...>& operator=(const T& _variant) {
|
||||||
variant_ = _variant;
|
variant_ = _variant;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -62,11 +66,13 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Variant<AlternativeTypes...>& operator=(
|
Variant<AlternativeTypes...>& operator=(
|
||||||
const Variant<AlternativeTypes...>& _other) = default;
|
const Variant<AlternativeTypes...>& _other
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Variant<AlternativeTypes...>& operator=(
|
Variant<AlternativeTypes...>& operator=(
|
||||||
Variant<AlternativeTypes...>&& _other) = default;
|
Variant<AlternativeTypes...>&& _other
|
||||||
|
) = default;
|
||||||
|
|
||||||
/// Returns the underlying variant.
|
/// Returns the underlying variant.
|
||||||
VariantType& variant() { return variant_; }
|
VariantType& variant() { return variant_; }
|
||||||
|
|
|
@ -15,7 +15,8 @@ namespace rfl {
|
||||||
} else {
|
} else {
|
||||||
return from_named_tuple<T>(
|
return from_named_tuple<T>(
|
||||||
to_named_tuple(std::forward<Head>(_head))
|
to_named_tuple(std::forward<Head>(_head))
|
||||||
.add(to_named_tuple(std::forward<Tail>(_tail))...));
|
.add(to_named_tuple(std::forward<Tail>(_tail))...)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +26,8 @@ namespace rfl {
|
||||||
if constexpr (sizeof...(_tail) == 0) {
|
if constexpr (sizeof...(_tail) == 0) {
|
||||||
return from_named_tuple<T>(to_named_tuple(_head));
|
return from_named_tuple<T>(to_named_tuple(_head));
|
||||||
} else {
|
} else {
|
||||||
return from_named_tuple<T>(
|
return from_named_tuple<T>(to_named_tuple(_head).add(to_named_tuple(_tail
|
||||||
to_named_tuple(_head).add(to_named_tuple(_tail)...));
|
)...));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,24 @@ namespace rfl::parsing {
|
||||||
|
|
||||||
using ParentType = Parent<W>;
|
using ParentType = Parent<W>;
|
||||||
|
|
||||||
static Result<bson_oid_t> read(const R& _r,
|
static Result<bson_oid_t>
|
||||||
const InputVarType& _var) noexcept {
|
read(const R& _r, const InputVarType& _var) noexcept {
|
||||||
return _r.template to_basic_type<bson_oid_t>(_var);
|
return _r.template to_basic_type<bson_oid_t>(_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
static void write(const W& _w,
|
static void
|
||||||
const bson_oid_t& _oid,
|
write(const W& _w, const bson_oid_t& _oid, const P& _parent) noexcept {
|
||||||
const P& _parent) noexcept {
|
|
||||||
ParentType::add_value(_w, _oid, _parent);
|
ParentType::add_value(_w, _oid, _parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static schema::Type to_schema(
|
static schema::Type to_schema(
|
||||||
std::map<std::string, schema::Type>* _definitions) {
|
std::map<std::string, schema::Type>* _definitions
|
||||||
static_assert(rfl::always_false_v<R>,
|
) {
|
||||||
"bson_oid_t cannot be expressed inside a JSON schema.");
|
static_assert(
|
||||||
|
rfl::always_false_v<R>,
|
||||||
|
"bson_oid_t cannot be expressed inside a JSON schema."
|
||||||
|
);
|
||||||
return schema::Type {schema::Type::String {}};
|
return schema::Type {schema::Type::String {}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,11 +50,12 @@ namespace rfl {
|
||||||
(requires(InputVarType var) { T::from_bson_obj(var); });
|
(requires(InputVarType var) { T::from_bson_obj(var); });
|
||||||
|
|
||||||
rfl::Result<InputVarType> get_field(
|
rfl::Result<InputVarType> get_field(
|
||||||
const std::string& _name,
|
const std::string& _name,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
bson_t b;
|
) const noexcept {
|
||||||
|
bson_t b;
|
||||||
bson_iter_t iter;
|
bson_iter_t iter;
|
||||||
const auto doc = _obj.val_->val_.value.v_doc;
|
const auto doc = _obj.val_->val_.value.v_doc;
|
||||||
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
||||||
if (bson_iter_init(&iter, &b)) {
|
if (bson_iter_init(&iter, &b)) {
|
||||||
while (bson_iter_next(&iter)) {
|
while (bson_iter_next(&iter)) {
|
||||||
|
@ -84,7 +85,8 @@ namespace rfl {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return rfl::Error(
|
return rfl::Error(
|
||||||
"Could not cast to string. The type must be UTF8 or symbol.");
|
"Could not cast to string. The type must be UTF8 or symbol."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
if (btype != BSON_TYPE_BOOL) {
|
if (btype != BSON_TYPE_BOOL) {
|
||||||
|
@ -109,10 +111,11 @@ namespace rfl {
|
||||||
default:
|
default:
|
||||||
return rfl::Error(
|
return rfl::Error(
|
||||||
"Could not cast to numeric value. The type must be double, "
|
"Could not cast to numeric value. The type must be double, "
|
||||||
"int32, int64 or date_time.");
|
"int32, int64 or date_time."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>(
|
||||||
bson_oid_t>()) {
|
)) {
|
||||||
if (btype != BSON_TYPE_OID) {
|
if (btype != BSON_TYPE_OID) {
|
||||||
return rfl::Error("Could not cast to OID.");
|
return rfl::Error("Could not cast to OID.");
|
||||||
}
|
}
|
||||||
|
@ -122,8 +125,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(
|
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
const auto btype = _var.val_->val_.value_type;
|
const auto btype = _var.val_->val_.value_type;
|
||||||
if (btype != BSON_TYPE_ARRAY && btype != BSON_TYPE_DOCUMENT) {
|
if (btype != BSON_TYPE_ARRAY && btype != BSON_TYPE_DOCUMENT) {
|
||||||
return Error("Could not cast to an array.");
|
return Error("Could not cast to an array.");
|
||||||
|
@ -133,11 +136,12 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(
|
||||||
const ArrayReader& _array_reader,
|
const ArrayReader& _array_reader,
|
||||||
const InputArrayType& _arr) const noexcept {
|
const InputArrayType& _arr
|
||||||
bson_t b;
|
) const noexcept {
|
||||||
|
bson_t b;
|
||||||
bson_iter_t iter;
|
bson_iter_t iter;
|
||||||
const auto doc = _arr.val_->val_.value.v_doc;
|
const auto doc = _arr.val_->val_.value.v_doc;
|
||||||
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
||||||
if (bson_iter_init(&iter, &b)) {
|
if (bson_iter_init(&iter, &b)) {
|
||||||
while (bson_iter_next(&iter)) {
|
while (bson_iter_next(&iter)) {
|
||||||
|
@ -151,11 +155,12 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error> read_object(
|
||||||
const ObjectReader& _object_reader,
|
const ObjectReader& _object_reader,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
bson_t b;
|
) const noexcept {
|
||||||
|
bson_t b;
|
||||||
bson_iter_t iter;
|
bson_iter_t iter;
|
||||||
const auto doc = _obj.val_->val_.value.v_doc;
|
const auto doc = _obj.val_->val_.value.v_doc;
|
||||||
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
if (bson_init_static(&b, doc.data, doc.data_len)) {
|
||||||
if (bson_iter_init(&iter, &b)) {
|
if (bson_iter_init(&iter, &b)) {
|
||||||
while (bson_iter_next(&iter)) {
|
while (bson_iter_next(&iter)) {
|
||||||
|
@ -167,8 +172,8 @@ namespace rfl {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(
|
rfl::Result<InputObjectType> to_object(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
const auto btype = _var.val_->val_.value_type;
|
const auto btype = _var.val_->val_.value_type;
|
||||||
if (btype != BSON_TYPE_DOCUMENT) {
|
if (btype != BSON_TYPE_DOCUMENT) {
|
||||||
return Error("Could not cast to a document.");
|
return Error("Could not cast to a document.");
|
||||||
|
@ -177,8 +182,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(
|
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
try {
|
try {
|
||||||
return T::from_bson_obj(_var);
|
return T::from_bson_obj(_var);
|
||||||
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace rfl {
|
||||||
struct BSONOutputArray {
|
struct BSONOutputArray {
|
||||||
BSONOutputArray(bson_array_builder_t* _val, ParentType _parent)
|
BSONOutputArray(bson_array_builder_t* _val, ParentType _parent)
|
||||||
: parent_(_parent), val_(_val) {}
|
: parent_(_parent), val_(_val) {}
|
||||||
ParentType parent_;
|
ParentType parent_;
|
||||||
bson_array_builder_t* val_;
|
bson_array_builder_t* val_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ namespace rfl {
|
||||||
BSONOutputObject(bson_t* _val, ParentType _parent)
|
BSONOutputObject(bson_t* _val, ParentType _parent)
|
||||||
: parent_(_parent), val_(_val) {}
|
: parent_(_parent), val_(_val) {}
|
||||||
ParentType parent_;
|
ParentType parent_;
|
||||||
bson_t* val_;
|
bson_t* val_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSONOutputVar {};
|
struct BSONOutputVar {};
|
||||||
|
@ -79,14 +79,17 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType value_as_root(const T& _var) const noexcept {
|
OutputVarType value_as_root(const T& _var) const noexcept {
|
||||||
static_assert(rfl::always_false_v<T>,
|
static_assert(
|
||||||
"BSON only allows arrays or objects as its root.");
|
rfl::always_false_v<T>,
|
||||||
|
"BSON only allows arrays or objects as its root."
|
||||||
|
);
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
bson_array_builder_t* val;
|
bson_array_builder_t* val;
|
||||||
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
|
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
|
||||||
return OutputArrayType(val, IsArray {_parent->val_});
|
return OutputArrayType(val, IsArray {_parent->val_});
|
||||||
|
@ -94,52 +97,63 @@ namespace rfl {
|
||||||
|
|
||||||
OutputArrayType add_array_to_object(
|
OutputArrayType add_array_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
bson_array_builder_t* val;
|
bson_array_builder_t* val;
|
||||||
bson_append_array_builder_begin(_parent->val_, _name.data(),
|
bson_append_array_builder_begin(
|
||||||
static_cast<int>(_name.size()), &val);
|
_parent->val_, _name.data(), static_cast<int>(_name.size()), &val
|
||||||
|
);
|
||||||
return OutputArrayType(val, IsObject {_parent->val_});
|
return OutputArrayType(val, IsObject {_parent->val_});
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
subdocs_->emplace_back(rfl::Box<BSONType>());
|
subdocs_->emplace_back(rfl::Box<BSONType>());
|
||||||
bson_array_builder_append_document_begin(_parent->val_,
|
bson_array_builder_append_document_begin(
|
||||||
&(subdocs_->back()->val_));
|
_parent->val_, &(subdocs_->back()->val_)
|
||||||
return OutputObjectType(&subdocs_->back()->val_,
|
);
|
||||||
IsArray {_parent->val_});
|
return OutputObjectType(
|
||||||
|
&subdocs_->back()->val_, IsArray {_parent->val_}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_object(
|
OutputObjectType add_object_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
subdocs_->emplace_back(rfl::Box<BSONType>());
|
subdocs_->emplace_back(rfl::Box<BSONType>());
|
||||||
bson_append_document_begin(_parent->val_, _name.data(),
|
bson_append_document_begin(
|
||||||
static_cast<int>(_name.size()),
|
_parent->val_, _name.data(), static_cast<int>(_name.size()),
|
||||||
&(subdocs_->back()->val_));
|
&(subdocs_->back()->val_)
|
||||||
return OutputObjectType(&subdocs_->back()->val_,
|
);
|
||||||
IsObject {_parent->val_});
|
return OutputObjectType(
|
||||||
|
&subdocs_->back()->val_, IsObject {_parent->val_}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
|
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
|
||||||
const noexcept {
|
const noexcept {
|
||||||
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
||||||
bson_array_builder_append_utf8(_parent->val_, _var.c_str(),
|
bson_array_builder_append_utf8(
|
||||||
static_cast<int>(_var.size()));
|
_parent->val_, _var.c_str(), static_cast<int>(_var.size())
|
||||||
|
);
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
bson_array_builder_append_bool(_parent->val_, _var);
|
bson_array_builder_append_bool(_parent->val_, _var);
|
||||||
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
||||||
bson_array_builder_append_double(_parent->val_,
|
bson_array_builder_append_double(
|
||||||
static_cast<double>(_var));
|
_parent->val_, static_cast<double>(_var)
|
||||||
|
);
|
||||||
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
||||||
bson_array_builder_append_int64(_parent->val_,
|
bson_array_builder_append_int64(
|
||||||
static_cast<std::int64_t>(_var));
|
_parent->val_, static_cast<std::int64_t>(_var)
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
|
);
|
||||||
bson_oid_t>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>(
|
||||||
|
)) {
|
||||||
bson_array_builder_append_oid(_parent->val_, &_var);
|
bson_array_builder_append_oid(_parent->val_, &_var);
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
|
@ -150,27 +164,33 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_object(
|
OutputVarType add_value_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const T& _var,
|
const T& _var,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
||||||
bson_append_utf8(_parent->val_, _name.data(),
|
bson_append_utf8(
|
||||||
static_cast<int>(_name.size()), _var.c_str(),
|
_parent->val_, _name.data(), static_cast<int>(_name.size()),
|
||||||
static_cast<int>(_var.size()));
|
_var.c_str(), static_cast<int>(_var.size())
|
||||||
|
);
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
bson_append_bool(_parent->val_, _name.data(),
|
bson_append_bool(
|
||||||
static_cast<int>(_name.size()), _var);
|
_parent->val_, _name.data(), static_cast<int>(_name.size()), _var
|
||||||
|
);
|
||||||
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
||||||
bson_append_double(_parent->val_, _name.data(),
|
bson_append_double(
|
||||||
static_cast<int>(_name.size()),
|
_parent->val_, _name.data(), static_cast<int>(_name.size()),
|
||||||
static_cast<double>(_var));
|
static_cast<double>(_var)
|
||||||
|
);
|
||||||
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
||||||
bson_append_int64(_parent->val_, _name.data(),
|
bson_append_int64(
|
||||||
static_cast<int>(_name.size()),
|
_parent->val_, _name.data(), static_cast<int>(_name.size()),
|
||||||
static_cast<std::int64_t>(_var));
|
static_cast<std::int64_t>(_var)
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
|
);
|
||||||
bson_oid_t>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>(
|
||||||
bson_append_oid(_parent->val_, _name.data(),
|
)) {
|
||||||
static_cast<int>(_name.size()), &_var);
|
bson_append_oid(
|
||||||
|
_parent->val_, _name.data(), static_cast<int>(_name.size()), &_var
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
}
|
}
|
||||||
|
@ -184,9 +204,11 @@ namespace rfl {
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
bson_append_null(_parent->val_, _name.data(),
|
) const noexcept {
|
||||||
static_cast<int>(_name.size()));
|
bson_append_null(
|
||||||
|
_parent->val_, _name.data(), static_cast<int>(_name.size())
|
||||||
|
);
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,8 +216,9 @@ namespace rfl {
|
||||||
const auto handle = [&](const auto _parent) {
|
const auto handle = [&](const auto _parent) {
|
||||||
using Type = std::remove_cvref_t<decltype(_parent)>;
|
using Type = std::remove_cvref_t<decltype(_parent)>;
|
||||||
if constexpr (std::is_same<Type, IsArray>()) {
|
if constexpr (std::is_same<Type, IsArray>()) {
|
||||||
bson_array_builder_append_array_builder_end(_parent.ptr_,
|
bson_array_builder_append_array_builder_end(
|
||||||
_arr->val_);
|
_parent.ptr_, _arr->val_
|
||||||
|
);
|
||||||
} else if constexpr (std::is_same<Type, IsObject>()) {
|
} else if constexpr (std::is_same<Type, IsObject>()) {
|
||||||
bson_append_array_builder_end(_parent.ptr_, _arr->val_);
|
bson_append_array_builder_end(_parent.ptr_, _arr->val_);
|
||||||
} else if constexpr (std::is_same<Type, IsRoot>()) {
|
} else if constexpr (std::is_same<Type, IsRoot>()) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace rfl {
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(std::istream& _stream) {
|
auto read(std::istream& _stream) {
|
||||||
std::istreambuf_iterator<char> begin(_stream), end;
|
std::istreambuf_iterator<char> begin(_stream), end;
|
||||||
auto bytes = std::vector<char>(begin, end);
|
auto bytes = std::vector<char>(begin, end);
|
||||||
return read<T, Ps...>(bytes.data(), bytes.size());
|
return read<T, Ps...>(bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,18 @@ namespace rfl {
|
||||||
/// call bson_free on the returned pointer.
|
/// call bson_free on the returned pointer.
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
|
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
|
||||||
using T = std::remove_cvref_t<decltype(_obj)>;
|
using T = std::remove_cvref_t<decltype(_obj)>;
|
||||||
using ParentType = parsing::Parent<Writer>;
|
using ParentType = parsing::Parent<Writer>;
|
||||||
bson_t* doc = nullptr;
|
bson_t* doc = nullptr;
|
||||||
uint8_t* buf = nullptr;
|
uint8_t* buf = nullptr;
|
||||||
size_t buflen = 0;
|
size_t buflen = 0;
|
||||||
bson_writer_t* bson_writer =
|
bson_writer_t* bson_writer =
|
||||||
bson_writer_new(&buf, &buflen, 0, bson_realloc_ctx, NULL);
|
bson_writer_new(&buf, &buflen, 0, bson_realloc_ctx, NULL);
|
||||||
bson_writer_begin(bson_writer, &doc);
|
bson_writer_begin(bson_writer, &doc);
|
||||||
const auto rfl_writer = Writer(doc);
|
const auto rfl_writer = Writer(doc);
|
||||||
Parser<T, Processors<Ps...>>::write(rfl_writer, _obj,
|
Parser<T, Processors<Ps...>>::write(
|
||||||
typename ParentType::Root {});
|
rfl_writer, _obj, typename ParentType::Root {}
|
||||||
|
);
|
||||||
bson_writer_end(bson_writer);
|
bson_writer_end(bson_writer);
|
||||||
const auto len = bson_writer_get_length(bson_writer);
|
const auto len = bson_writer_get_length(bson_writer);
|
||||||
bson_writer_destroy(bson_writer);
|
bson_writer_destroy(bson_writer);
|
||||||
|
@ -39,8 +40,9 @@ namespace rfl {
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
std::vector<char> write(const auto& _obj) noexcept {
|
std::vector<char> write(const auto& _obj) noexcept {
|
||||||
auto [buf, len] = to_buffer<Ps...>(_obj);
|
auto [buf, len] = to_buffer<Ps...>(_obj);
|
||||||
const auto result = std::vector<char>(reinterpret_cast<char*>(buf),
|
const auto result = std::vector<char>(
|
||||||
reinterpret_cast<char*>(buf) + len);
|
reinterpret_cast<char*>(buf), reinterpret_cast<char*>(buf) + len
|
||||||
|
);
|
||||||
bson_free(buf);
|
bson_free(buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,29 +12,33 @@ namespace rfl {
|
||||||
/// Because of that, we require all of the fields and then set them to
|
/// Because of that, we require all of the fields and then set them to
|
||||||
/// nullptr, if necessary.
|
/// nullptr, if necessary.
|
||||||
template <class ProcessorsType, class... FieldTypes>
|
template <class ProcessorsType, class... FieldTypes>
|
||||||
requires AreReaderAndWriter<cbor::Reader,
|
requires AreReaderAndWriter<
|
||||||
cbor::Writer,
|
cbor::Reader,
|
||||||
NamedTuple<FieldTypes...>>
|
cbor::Writer,
|
||||||
struct Parser<cbor::Reader,
|
NamedTuple<FieldTypes...>>
|
||||||
cbor::Writer,
|
struct Parser<
|
||||||
NamedTuple<FieldTypes...>,
|
cbor::Reader,
|
||||||
ProcessorsType>
|
cbor::Writer,
|
||||||
: public NamedTupleParser<cbor::Reader,
|
NamedTuple<FieldTypes...>,
|
||||||
cbor::Writer,
|
ProcessorsType>
|
||||||
/*_ignore_empty_containers=*/false,
|
: public NamedTupleParser<
|
||||||
/*_all_required=*/true,
|
cbor::Reader,
|
||||||
ProcessorsType,
|
cbor::Writer,
|
||||||
FieldTypes...> {};
|
/*_ignore_empty_containers=*/false,
|
||||||
|
/*_all_required=*/true,
|
||||||
|
ProcessorsType,
|
||||||
|
FieldTypes...> {};
|
||||||
|
|
||||||
template <class ProcessorsType, class... Ts>
|
template <class ProcessorsType, class... Ts>
|
||||||
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, std::tuple<Ts...>>
|
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, std::tuple<Ts...>>
|
||||||
struct Parser<cbor::Reader, cbor::Writer, std::tuple<Ts...>, ProcessorsType>
|
struct Parser<cbor::Reader, cbor::Writer, std::tuple<Ts...>, ProcessorsType>
|
||||||
: public TupleParser<cbor::Reader,
|
: public TupleParser<
|
||||||
cbor::Writer,
|
cbor::Reader,
|
||||||
/*_ignore_empty_containers=*/false,
|
cbor::Writer,
|
||||||
/*_all_required=*/true,
|
/*_ignore_empty_containers=*/false,
|
||||||
ProcessorsType,
|
/*_all_required=*/true,
|
||||||
Ts...> {};
|
ProcessorsType,
|
||||||
|
Ts...> {};
|
||||||
|
|
||||||
} // namespace parsing
|
} // namespace parsing
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -46,11 +46,12 @@ namespace rfl {
|
||||||
(requires(InputVarType var) { T::from_cbor_obj(var); });
|
(requires(InputVarType var) { T::from_cbor_obj(var); });
|
||||||
|
|
||||||
rfl::Result<InputVarType> get_field(
|
rfl::Result<InputVarType> get_field(
|
||||||
const std::string& _name,
|
const std::string& _name,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
CborValue val;
|
CborValue val;
|
||||||
auto buffer = std::vector<char>();
|
auto buffer = std::vector<char>();
|
||||||
auto err = cbor_value_enter_container(_obj.val_, &val);
|
auto err = cbor_value_enter_container(_obj.val_, &val);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
err = cbor_value_get_map_length(_obj.val_, &length);
|
err = cbor_value_get_map_length(_obj.val_, &length);
|
||||||
|
@ -81,55 +82,56 @@ namespace rfl {
|
||||||
return Error("Could not cast to string.");
|
return Error("Could not cast to string.");
|
||||||
}
|
}
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
const auto err = get_string(_var.val_, &buffer);
|
const auto err = get_string(_var.val_, &buffer);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
return std::string(buffer.data());
|
return std::string(buffer.data());
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
if (!cbor_value_is_boolean(_var.val_)) {
|
if (!cbor_value_is_boolean(_var.val_)) {
|
||||||
return rfl::Error("Could not cast to boolean.");
|
return rfl::Error("Could not cast to boolean.");
|
||||||
}
|
}
|
||||||
bool result = false;
|
bool result = false;
|
||||||
const auto err = cbor_value_get_boolean(_var.val_, &result);
|
const auto err = cbor_value_get_boolean(_var.val_, &result);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
return result;
|
return result;
|
||||||
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>() ||
|
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>() ||
|
||||||
std::is_integral<std::remove_cvref_t<T>>()) {
|
std::is_integral<std::remove_cvref_t<T>>()) {
|
||||||
if (cbor_value_is_integer(_var.val_)) {
|
if (cbor_value_is_integer(_var.val_)) {
|
||||||
std::int64_t result = 0;
|
std::int64_t result = 0;
|
||||||
const auto err = cbor_value_get_int64(_var.val_, &result);
|
const auto err = cbor_value_get_int64(_var.val_, &result);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
return static_cast<T>(result);
|
return static_cast<T>(result);
|
||||||
} else if (cbor_value_is_float(_var.val_)) {
|
} else if (cbor_value_is_float(_var.val_)) {
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
const auto err = cbor_value_get_float(_var.val_, &result);
|
const auto err = cbor_value_get_float(_var.val_, &result);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
return static_cast<T>(result);
|
return static_cast<T>(result);
|
||||||
} else if (cbor_value_is_double(_var.val_)) {
|
} else if (cbor_value_is_double(_var.val_)) {
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
const auto err = cbor_value_get_double(_var.val_, &result);
|
const auto err = cbor_value_get_double(_var.val_, &result);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
return static_cast<T>(result);
|
return static_cast<T>(result);
|
||||||
}
|
}
|
||||||
return rfl::Error(
|
return rfl::Error(
|
||||||
"Could not cast to numeric value. The type must be integral, "
|
"Could not cast to numeric value. The type must be integral, "
|
||||||
"float "
|
"float "
|
||||||
"or double.");
|
"or double."
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(
|
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (!cbor_value_is_array(_var.val_)) {
|
if (!cbor_value_is_array(_var.val_)) {
|
||||||
return Error("Could not cast to an array.");
|
return Error("Could not cast to an array.");
|
||||||
}
|
}
|
||||||
return InputArrayType {_var.val_};
|
return InputArrayType {_var.val_};
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(
|
rfl::Result<InputObjectType> to_object(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (!cbor_value_is_map(_var.val_)) {
|
if (!cbor_value_is_map(_var.val_)) {
|
||||||
return Error("Could not cast to an object.");
|
return Error("Could not cast to an object.");
|
||||||
}
|
}
|
||||||
|
@ -138,11 +140,12 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(
|
||||||
const ArrayReader& _array_reader,
|
const ArrayReader& _array_reader,
|
||||||
const InputArrayType& _arr) const noexcept {
|
const InputArrayType& _arr
|
||||||
|
) const noexcept {
|
||||||
CborValue val;
|
CborValue val;
|
||||||
auto buffer = std::vector<char>();
|
auto buffer = std::vector<char>();
|
||||||
auto err = cbor_value_enter_container(_arr.val_, &val);
|
auto err = cbor_value_enter_container(_arr.val_, &val);
|
||||||
if (err != CborNoError && err != CborErrorOutOfMemory) {
|
if (err != CborNoError && err != CborErrorOutOfMemory) {
|
||||||
return Error(cbor_error_string(err));
|
return Error(cbor_error_string(err));
|
||||||
}
|
}
|
||||||
|
@ -164,10 +167,11 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error> read_object(
|
||||||
const ObjectReader& _object_reader,
|
const ObjectReader& _object_reader,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
auto err = cbor_value_get_map_length(_obj.val_, &length);
|
auto err = cbor_value_get_map_length(_obj.val_, &length);
|
||||||
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
if (err != CborNoError) { return Error(cbor_error_string(err)); }
|
||||||
|
|
||||||
CborValue val;
|
CborValue val;
|
||||||
|
@ -190,23 +194,24 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(
|
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
try {
|
try {
|
||||||
return T::from_cbor_obj(_var);
|
return T::from_cbor_obj(_var);
|
||||||
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CborError get_string(const CborValue* _ptr,
|
CborError get_string(const CborValue* _ptr, std::vector<char>* _buffer)
|
||||||
std::vector<char>* _buffer) const noexcept {
|
const noexcept {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
auto err = cbor_value_get_string_length(_ptr, &length);
|
auto err = cbor_value_get_string_length(_ptr, &length);
|
||||||
if (err != CborNoError && err != CborErrorOutOfMemory) { return err; }
|
if (err != CborNoError && err != CborErrorOutOfMemory) { return err; }
|
||||||
_buffer->resize(length + 1);
|
_buffer->resize(length + 1);
|
||||||
(*_buffer)[length] = '\0';
|
(*_buffer)[length] = '\0';
|
||||||
return cbor_value_copy_text_string(_ptr, _buffer->data(), &length,
|
return cbor_value_copy_text_string(
|
||||||
NULL);
|
_ptr, _buffer->data(), &length, NULL
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputVarType to_input_var(CborValue* _ptr) const noexcept {
|
InputVarType to_input_var(CborValue* _ptr) const noexcept {
|
||||||
|
|
|
@ -61,29 +61,33 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_array(_size, _parent->encoder_);
|
return new_array(_size, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_object(
|
OutputArrayType add_array_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
||||||
return new_array(_size, _parent->encoder_);
|
return new_array(_size, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_object(_size, _parent->encoder_);
|
return new_object(_size, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_object(
|
OutputObjectType add_object_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
||||||
return new_object(_size, _parent->encoder_);
|
return new_object(_size, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
@ -97,8 +101,9 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_object(
|
OutputVarType add_value_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const T& _var,
|
const T& _var,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
||||||
return new_value(_var, _parent->encoder_);
|
return new_value(_var, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +115,8 @@ namespace rfl {
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
|
||||||
cbor_encode_null(_parent->encoder_);
|
cbor_encode_null(_parent->encoder_);
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
|
@ -125,23 +131,23 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutputArrayType new_array(const size_t _size,
|
OutputArrayType new_array(const size_t _size, CborEncoder* _parent)
|
||||||
CborEncoder* _parent) const noexcept {
|
const noexcept {
|
||||||
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
|
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
|
||||||
cbor_encoder_create_array(_parent, subencoders_->back().get(), _size);
|
cbor_encoder_create_array(_parent, subencoders_->back().get(), _size);
|
||||||
return OutputArrayType {subencoders_->back().get(), _parent};
|
return OutputArrayType {subencoders_->back().get(), _parent};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType new_object(const size_t _size,
|
OutputObjectType new_object(const size_t _size, CborEncoder* _parent)
|
||||||
CborEncoder* _parent) const noexcept {
|
const noexcept {
|
||||||
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
|
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
|
||||||
cbor_encoder_create_map(_parent, subencoders_->back().get(), _size);
|
cbor_encoder_create_map(_parent, subencoders_->back().get(), _size);
|
||||||
return OutputObjectType {subencoders_->back().get(), _parent};
|
return OutputObjectType {subencoders_->back().get(), _parent};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType new_value(const T& _var,
|
OutputVarType new_value(const T& _var, CborEncoder* _parent)
|
||||||
CborEncoder* _parent) const noexcept {
|
const noexcept {
|
||||||
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
||||||
cbor_encode_text_string(_parent, _var.c_str(), _var.size());
|
cbor_encode_text_string(_parent, _var.c_str(), _var.size());
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
|
|
|
@ -25,12 +25,13 @@ namespace rfl {
|
||||||
|
|
||||||
/// Parses an object from CBOR using reflection.
|
/// Parses an object from CBOR using reflection.
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
|
Result<internal::wrap_in_rfl_array_t<T>>
|
||||||
const size_t _size) {
|
read(const char* _bytes, const size_t _size) {
|
||||||
CborParser parser;
|
CborParser parser;
|
||||||
CborValue value;
|
CborValue value;
|
||||||
cbor_parser_init(reinterpret_cast<const uint8_t*>(_bytes), _size, 0,
|
cbor_parser_init(
|
||||||
&parser, &value);
|
reinterpret_cast<const uint8_t*>(_bytes), _size, 0, &parser, &value
|
||||||
|
);
|
||||||
auto doc = InputVarType {&value};
|
auto doc = InputVarType {&value};
|
||||||
auto result = read<T, Ps...>(doc);
|
auto result = read<T, Ps...>(doc);
|
||||||
return result;
|
return result;
|
||||||
|
@ -46,7 +47,7 @@ namespace rfl {
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(std::istream& _stream) {
|
auto read(std::istream& _stream) {
|
||||||
std::istreambuf_iterator<char> begin(_stream), end;
|
std::istreambuf_iterator<char> begin(_stream), end;
|
||||||
auto bytes = std::vector<char>(begin, end);
|
auto bytes = std::vector<char>(begin, end);
|
||||||
return read<T, Ps...>(bytes.data(), bytes.size());
|
return read<T, Ps...>(bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,23 +15,28 @@ namespace rfl {
|
||||||
namespace cbor {
|
namespace cbor {
|
||||||
|
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
void write_into_buffer(const auto& _obj,
|
void write_into_buffer(
|
||||||
CborEncoder* _encoder,
|
const auto& _obj,
|
||||||
std::vector<char>* _buffer) noexcept {
|
CborEncoder* _encoder,
|
||||||
|
std::vector<char>* _buffer
|
||||||
|
) noexcept {
|
||||||
using T = std::remove_cvref_t<decltype(_obj)>;
|
using T = std::remove_cvref_t<decltype(_obj)>;
|
||||||
using ParentType = parsing::Parent<Writer>;
|
using ParentType = parsing::Parent<Writer>;
|
||||||
cbor_encoder_init(_encoder, reinterpret_cast<uint8_t*>(_buffer->data()),
|
cbor_encoder_init(
|
||||||
_buffer->size(), 0);
|
_encoder, reinterpret_cast<uint8_t*>(_buffer->data()),
|
||||||
|
_buffer->size(), 0
|
||||||
|
);
|
||||||
const auto writer = Writer(_encoder);
|
const auto writer = Writer(_encoder);
|
||||||
Parser<T, Processors<Ps...>>::write(writer, _obj,
|
Parser<T, Processors<Ps...>>::write(
|
||||||
typename ParentType::Root {});
|
writer, _obj, typename ParentType::Root {}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns CBOR bytes.
|
/// Returns CBOR bytes.
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
std::vector<char> write(const auto& _obj) noexcept {
|
std::vector<char> write(const auto& _obj) noexcept {
|
||||||
std::vector<char> buffer(4096);
|
std::vector<char> buffer(4096);
|
||||||
CborEncoder encoder;
|
CborEncoder encoder;
|
||||||
write_into_buffer<Ps...>(_obj, &encoder, &buffer);
|
write_into_buffer<Ps...>(_obj, &encoder, &buffer);
|
||||||
const auto total_bytes_needed =
|
const auto total_bytes_needed =
|
||||||
buffer.size() + cbor_encoder_get_extra_bytes_needed(&encoder);
|
buffer.size() + cbor_encoder_get_extra_bytes_needed(&encoder);
|
||||||
|
@ -40,7 +45,8 @@ namespace rfl {
|
||||||
write_into_buffer<Ps...>(_obj, &encoder, &buffer);
|
write_into_buffer<Ps...>(_obj, &encoder, &buffer);
|
||||||
}
|
}
|
||||||
const auto length = cbor_encoder_get_buffer_size(
|
const auto length = cbor_encoder_get_buffer_size(
|
||||||
&encoder, reinterpret_cast<uint8_t*>(buffer.data()));
|
&encoder, reinterpret_cast<uint8_t*>(buffer.data())
|
||||||
|
);
|
||||||
buffer.resize(length);
|
buffer.resize(length);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value != threshold) {
|
if (_value != threshold) {
|
||||||
return Error("Value expected to be equal to " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to be equal to " + std::to_string(threshold) +
|
||||||
std::to_string(_value) + ".");
|
", but got " + std::to_string(_value) + "."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
@ -38,9 +39,11 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value < threshold) {
|
if (_value < threshold) {
|
||||||
return Error("Value expected to be greater than or equal to " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to be greater than or equal to " +
|
||||||
std::to_string(_value) + ".");
|
std::to_string(threshold) + ", but got " + std::to_string(_value) +
|
||||||
|
"."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +65,10 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value <= threshold) {
|
if (_value <= threshold) {
|
||||||
return Error("Value expected to be greater than " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to be greater than " + std::to_string(threshold) +
|
||||||
std::to_string(_value) + ".");
|
", but got " + std::to_string(_value) + "."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
@ -76,8 +80,8 @@ namespace rfl {
|
||||||
std::is_floating_point_v<T>
|
std::is_floating_point_v<T>
|
||||||
? std::variant<double, int>(static_cast<double>(_threshold))
|
? std::variant<double, int>(static_cast<double>(_threshold))
|
||||||
: std::variant<double, int>(static_cast<int>(_threshold));
|
: std::variant<double, int>(static_cast<int>(_threshold));
|
||||||
return ValidationType {
|
return ValidationType {ValidationType::ExclusiveMinimum {.value_ = value}
|
||||||
ValidationType::ExclusiveMinimum {.value_ = value}};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,9 +91,11 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value > threshold) {
|
if (_value > threshold) {
|
||||||
return Error("Value expected to be less than or equal to " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to be less than or equal to " +
|
||||||
std::to_string(_value) + ".");
|
std::to_string(threshold) + ", but got " + std::to_string(_value) +
|
||||||
|
"."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
@ -111,9 +117,10 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value >= threshold) {
|
if (_value >= threshold) {
|
||||||
return Error("Value expected to be less than " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to be less than " + std::to_string(threshold) +
|
||||||
std::to_string(_value) + ".");
|
", but got " + std::to_string(_value) + "."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
@ -125,8 +132,8 @@ namespace rfl {
|
||||||
std::is_floating_point_v<T>
|
std::is_floating_point_v<T>
|
||||||
? std::variant<double, int>(static_cast<double>(_threshold))
|
? std::variant<double, int>(static_cast<double>(_threshold))
|
||||||
: std::variant<double, int>(static_cast<int>(_threshold));
|
: std::variant<double, int>(static_cast<int>(_threshold));
|
||||||
return ValidationType {
|
return ValidationType {ValidationType::ExclusiveMaximum {.value_ = value}
|
||||||
ValidationType::ExclusiveMaximum {.value_ = value}};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,9 +143,10 @@ namespace rfl {
|
||||||
static Result<T> validate(T _value) noexcept {
|
static Result<T> validate(T _value) noexcept {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value == threshold) {
|
if (_value == threshold) {
|
||||||
return Error("Value expected to not be equal to " +
|
return Error(
|
||||||
std::to_string(threshold) + ", but got " +
|
"Value expected to not be equal to " + std::to_string(threshold) +
|
||||||
std::to_string(_value) + ".");
|
", but got " + std::to_string(_value) + "."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
namespace rfl {
|
namespace rfl {
|
||||||
|
|
||||||
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
|
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
|
||||||
using define_tagged_union_t =
|
using define_tagged_union_t = typename internal::
|
||||||
typename internal::define_tagged_union<_discriminator,
|
define_tagged_union<_discriminator, TaggedUnionTypes...>::type;
|
||||||
TaggedUnionTypes...>::type;
|
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,15 @@ namespace rfl {
|
||||||
// Converts an enum value to a string.
|
// Converts an enum value to a string.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
std::string enum_to_string(EnumType _enum) {
|
std::string enum_to_string(EnumType _enum) {
|
||||||
return rfl::internal::enums::StringConverter<EnumType>::enum_to_string(
|
return rfl::internal::enums::StringConverter<EnumType>::enum_to_string(_enum
|
||||||
_enum);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a string to a value of the given enum type.
|
// Converts a string to a value of the given enum type.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
rfl::Result<EnumType> string_to_enum(const std::string& _str) {
|
rfl::Result<EnumType> string_to_enum(const std::string& _str) {
|
||||||
return rfl::internal::enums::StringConverter<EnumType>::string_to_enum(
|
return rfl::internal::enums::StringConverter<EnumType>::string_to_enum(_str
|
||||||
_str);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a named tuple mapping names of enumerators of the given enum type
|
// Returns a named tuple mapping names of enumerators of the given enum type
|
||||||
|
|
|
@ -28,31 +28,32 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
struct has_from_flexbuf<
|
struct has_from_flexbuf<
|
||||||
T,
|
T,
|
||||||
std::enable_if_t<std::is_invocable_r<T,
|
std::enable_if_t<
|
||||||
decltype(T::from_flexbuf),
|
std::is_invocable_r<T, decltype(T::from_flexbuf), InputVarType>::
|
||||||
InputVarType>::value>>
|
value>> : std::true_type {};
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct has_from_flexbuf<
|
struct has_from_flexbuf<
|
||||||
T,
|
T,
|
||||||
std::enable_if_t<std::is_invocable_r<rfl::Result<T>,
|
std::enable_if_t<std::is_invocable_r<
|
||||||
decltype(T::from_flexbuf),
|
rfl::Result<T>,
|
||||||
InputVarType>::value>>
|
decltype(T::from_flexbuf),
|
||||||
: std::true_type {};
|
InputVarType>::value>> : std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static constexpr bool has_custom_constructor = has_from_flexbuf<T>::value;
|
static constexpr bool has_custom_constructor = has_from_flexbuf<T>::value;
|
||||||
|
|
||||||
rfl::Result<InputVarType> get_field(
|
rfl::Result<InputVarType> get_field(
|
||||||
const std::string& _name,
|
const std::string& _name,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
const auto keys = _obj.Keys();
|
const auto keys = _obj.Keys();
|
||||||
for (size_t i = 0; i < keys.size(); ++i) {
|
for (size_t i = 0; i < keys.size(); ++i) {
|
||||||
if (_name == keys[i].AsString().c_str()) { return _obj.Values()[i]; }
|
if (_name == keys[i].AsString().c_str()) { return _obj.Values()[i]; }
|
||||||
}
|
}
|
||||||
return rfl::Error("Map does not contain any element called '" + _name +
|
return rfl::Error(
|
||||||
"'.");
|
"Map does not contain any element called '" + _name + "'."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_empty(const InputVarType& _var) const noexcept {
|
bool is_empty(const InputVarType& _var) const noexcept {
|
||||||
|
@ -88,8 +89,9 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(
|
||||||
const ArrayReader& _array_reader,
|
const ArrayReader& _array_reader,
|
||||||
const InputArrayType& _arr) const noexcept {
|
const InputArrayType& _arr
|
||||||
|
) const noexcept {
|
||||||
const auto size = _arr.size();
|
const auto size = _arr.size();
|
||||||
for (size_t i = 0; i < size; ++i) {
|
for (size_t i = 0; i < size; ++i) {
|
||||||
const auto err = _array_reader.read(InputVarType(_arr[i]));
|
const auto err = _array_reader.read(InputVarType(_arr[i]));
|
||||||
|
@ -100,37 +102,39 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error> read_object(
|
||||||
const ObjectReader& _object_reader,
|
const ObjectReader& _object_reader,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
const auto keys = _obj.Keys();
|
const auto keys = _obj.Keys();
|
||||||
const auto values = _obj.Values();
|
const auto values = _obj.Values();
|
||||||
const auto num_values = std::min(keys.size(), values.size());
|
const auto num_values = std::min(keys.size(), values.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < num_values; ++i) {
|
for (size_t i = 0; i < num_values; ++i) {
|
||||||
_object_reader.read(std::string_view(keys[i].AsString().c_str()),
|
_object_reader.read(
|
||||||
values[i]);
|
std::string_view(keys[i].AsString().c_str()), values[i]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(
|
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (!_var.IsVector()) {
|
if (!_var.IsVector()) {
|
||||||
return rfl::Error("Could not cast to Vector.");
|
return rfl::Error("Could not cast to Vector.");
|
||||||
}
|
}
|
||||||
return _var.AsVector();
|
return _var.AsVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(
|
rfl::Result<InputObjectType> to_object(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (!_var.IsMap()) { return rfl::Error("Could not cast to Map!"); }
|
if (!_var.IsMap()) { return rfl::Error("Could not cast to Map!"); }
|
||||||
return _var.AsMap();
|
return _var.AsMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(
|
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
try {
|
try {
|
||||||
return T::from_flexbuf(_var);
|
return T::from_flexbuf(_var);
|
||||||
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
||||||
|
|
|
@ -58,28 +58,32 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_array();
|
return new_array();
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_object(
|
OutputArrayType add_array_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_array(_name);
|
return new_array(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_object();
|
return new_object();
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_object(
|
OutputObjectType add_object_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_object(_name);
|
return new_object(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +96,9 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_object(
|
OutputVarType add_value_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const T& _var,
|
const T& _var,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
return insert_value(_name, _var);
|
return insert_value(_name, _var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +109,8 @@ namespace rfl {
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
fbb_->Null(_name.data());
|
fbb_->Null(_name.data());
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
@ -119,8 +125,8 @@ namespace rfl {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType insert_value(const std::string_view& _name,
|
OutputVarType insert_value(const std::string_view& _name, const T& _var)
|
||||||
const T& _var) const noexcept {
|
const noexcept {
|
||||||
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
|
||||||
fbb_->String(_name.data(), _var);
|
fbb_->String(_name.data(), _var);
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
|
@ -161,8 +167,8 @@ namespace rfl {
|
||||||
return OutputArrayType {start};
|
return OutputArrayType {start};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType new_object(
|
OutputObjectType new_object(const std::string_view& _name
|
||||||
const std::string_view& _name) const noexcept {
|
) const noexcept {
|
||||||
const auto start = fbb_->StartMap(_name.data());
|
const auto start = fbb_->StartMap(_name.data());
|
||||||
return OutputObjectType {start};
|
return OutputObjectType {start};
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace rfl {
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(std::istream& _stream) {
|
auto read(std::istream& _stream) {
|
||||||
std::istreambuf_iterator<char> begin(_stream), end;
|
std::istreambuf_iterator<char> begin(_stream), end;
|
||||||
const auto bytes = std::vector<char>(begin, end);
|
const auto bytes = std::vector<char>(begin, end);
|
||||||
return read<T, Ps...>(bytes.data(), bytes.size());
|
return read<T, Ps...>(bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,10 @@ namespace rfl {
|
||||||
using T = std::remove_cvref_t<decltype(_obj)>;
|
using T = std::remove_cvref_t<decltype(_obj)>;
|
||||||
using ParentType = parsing::Parent<Writer>;
|
using ParentType = parsing::Parent<Writer>;
|
||||||
const auto fbb = Ref<flexbuffers::Builder>::make();
|
const auto fbb = Ref<flexbuffers::Builder>::make();
|
||||||
auto w = Writer(fbb);
|
auto w = Writer(fbb);
|
||||||
Parser<T, Processors<Ps...>>::write(w, _obj,
|
Parser<T, Processors<Ps...>>::write(
|
||||||
typename ParentType::Root {});
|
w, _obj, typename ParentType::Root {}
|
||||||
|
);
|
||||||
fbb->Finish();
|
fbb->Finish();
|
||||||
return fbb->GetBuffer();
|
return fbb->GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ namespace rfl {
|
||||||
template <class T, class NamedTupleType>
|
template <class T, class NamedTupleType>
|
||||||
auto from_named_tuple(NamedTupleType&& _n) {
|
auto from_named_tuple(NamedTupleType&& _n) {
|
||||||
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
|
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
|
||||||
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
|
if constexpr (!std::is_same<
|
||||||
RequiredType>()) {
|
std::remove_cvref_t<NamedTupleType>, RequiredType>()) {
|
||||||
return from_named_tuple<T>(
|
return from_named_tuple<T>(RequiredType(std::forward<NamedTupleType>(_n))
|
||||||
RequiredType(std::forward<NamedTupleType>(_n)));
|
);
|
||||||
} else if constexpr (internal::has_fields<T>()) {
|
} else if constexpr (internal::has_fields<T>()) {
|
||||||
if constexpr (std::is_lvalue_reference<NamedTupleType> {}) {
|
if constexpr (std::is_lvalue_reference<NamedTupleType> {}) {
|
||||||
return internal::copy_from_named_tuple<T>(_n);
|
return internal::copy_from_named_tuple<T>(_n);
|
||||||
|
@ -39,8 +39,8 @@ namespace rfl {
|
||||||
template <class T, class NamedTupleType>
|
template <class T, class NamedTupleType>
|
||||||
auto from_named_tuple(const NamedTupleType& _n) {
|
auto from_named_tuple(const NamedTupleType& _n) {
|
||||||
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
|
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
|
||||||
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
|
if constexpr (!std::is_same<
|
||||||
RequiredType>()) {
|
std::remove_cvref_t<NamedTupleType>, RequiredType>()) {
|
||||||
return from_named_tuple<T>(RequiredType(_n));
|
return from_named_tuple<T>(RequiredType(_n));
|
||||||
} else if constexpr (internal::has_fields<T>()) {
|
} else if constexpr (internal::has_fields<T>()) {
|
||||||
return internal::copy_from_named_tuple<T>(_n);
|
return internal::copy_from_named_tuple<T>(_n);
|
||||||
|
|
|
@ -34,7 +34,8 @@ namespace rfl {
|
||||||
template <internal::StringLiteral _field_name, class NamedTupleType>
|
template <internal::StringLiteral _field_name, class NamedTupleType>
|
||||||
inline const auto& get(const NamedTupleType& _tup) {
|
inline const auto& get(const NamedTupleType& _tup) {
|
||||||
return internal::Getter<NamedTupleType>::template get_const<_field_name>(
|
return internal::Getter<NamedTupleType>::template get_const<_field_name>(
|
||||||
_tup);
|
_tup
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a field by the field type.
|
/// Gets a field by the field type.
|
||||||
|
|
|
@ -40,12 +40,14 @@ namespace rfl::internal {
|
||||||
constexpr auto index =
|
constexpr auto index =
|
||||||
find_index<Field::name_, typename NamedTupleType::Fields>();
|
find_index<Field::name_, typename NamedTupleType::Fields>();
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<typename std::tuple_element<
|
std::is_same<
|
||||||
index, typename NamedTupleType::Fields>::type::Type,
|
typename std::tuple_element<
|
||||||
typename Field::Type>(),
|
index, typename NamedTupleType::Fields>::type::Type,
|
||||||
|
typename Field::Type>(),
|
||||||
"If two fields have the same name, "
|
"If two fields have the same name, "
|
||||||
"their type must be the same as "
|
"their type must be the same as "
|
||||||
"well.");
|
"well."
|
||||||
|
);
|
||||||
return Getter<NamedTupleType>::template get<index>(_tup);
|
return Getter<NamedTupleType>::template get<index>(_tup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +71,14 @@ namespace rfl::internal {
|
||||||
constexpr auto index =
|
constexpr auto index =
|
||||||
find_index<Field::name_, typename NamedTupleType::Fields>();
|
find_index<Field::name_, typename NamedTupleType::Fields>();
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<typename std::tuple_element<
|
std::is_same<
|
||||||
index, typename NamedTupleType::Fields>::type::Type,
|
typename std::tuple_element<
|
||||||
typename Field::Type>(),
|
index, typename NamedTupleType::Fields>::type::Type,
|
||||||
|
typename Field::Type>(),
|
||||||
"If two fields have the same name, "
|
"If two fields have the same name, "
|
||||||
"their type must be the same as "
|
"their type must be the same as "
|
||||||
"well.");
|
"well."
|
||||||
|
);
|
||||||
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -118,7 +122,8 @@ namespace rfl::internal {
|
||||||
/// Retrieves the indicated value from the tuple.
|
/// Retrieves the indicated value from the tuple.
|
||||||
template <int _index>
|
template <int _index>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const std::variant<NamedTupleTypes...>& _tup) {
|
const std::variant<NamedTupleTypes...>& _tup
|
||||||
|
) {
|
||||||
const auto apply = [](const auto& _tup) -> const auto& {
|
const auto apply = [](const auto& _tup) -> const auto& {
|
||||||
using NamedTupleType = std::remove_cvref_t<decltype(_tup)>;
|
using NamedTupleType = std::remove_cvref_t<decltype(_tup)>;
|
||||||
return Getter<NamedTupleType>::template get_const<_index>(_tup);
|
return Getter<NamedTupleType>::template get_const<_index>(_tup);
|
||||||
|
@ -129,7 +134,8 @@ namespace rfl::internal {
|
||||||
/// Gets a field by name.
|
/// Gets a field by name.
|
||||||
template <StringLiteral _field_name>
|
template <StringLiteral _field_name>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const std::variant<NamedTupleTypes...>& _tup) {
|
const std::variant<NamedTupleTypes...>& _tup
|
||||||
|
) {
|
||||||
const auto apply = [](const auto& _t) -> const auto& {
|
const auto apply = [](const auto& _t) -> const auto& {
|
||||||
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
||||||
return Getter<NamedTupleType>::template get_const<_field_name>(_t);
|
return Getter<NamedTupleType>::template get_const<_field_name>(_t);
|
||||||
|
@ -140,7 +146,8 @@ namespace rfl::internal {
|
||||||
/// Gets a field by the field type.
|
/// Gets a field by the field type.
|
||||||
template <class Field>
|
template <class Field>
|
||||||
static inline const auto& get_const(
|
static inline const auto& get_const(
|
||||||
const std::variant<NamedTupleTypes...>& _tup) {
|
const std::variant<NamedTupleTypes...>& _tup
|
||||||
|
) {
|
||||||
const auto apply = [](const auto& _t) -> const auto& {
|
const auto apply = [](const auto& _t) -> const auto& {
|
||||||
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
||||||
return Getter<NamedTupleType>::template get_const<Field>(_t);
|
return Getter<NamedTupleType>::template get_const<Field>(_t);
|
||||||
|
|
|
@ -39,27 +39,31 @@ namespace rfl::internal {
|
||||||
template <class U, bool _skip_s, bool _skip_d>
|
template <class U, bool _skip_s, bool _skip_d>
|
||||||
Skip(Skip<U, _skip_s, _skip_d>&& _other) : value_(_other.get()) {}
|
Skip(Skip<U, _skip_s, _skip_d>&& _other) : value_(_other.get()) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Skip(const U& _value) : value_(_value) {}
|
Skip(const U& _value) : value_(_value) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Skip(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
Skip(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||||
|
|
||||||
template <class U,
|
template <
|
||||||
bool _skip_s,
|
class U,
|
||||||
bool _skip_d,
|
bool _skip_s,
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
bool _skip_d,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
Skip(const Skip<U, _skip_s, _skip_d>& _skip) : value_(_skip.value()) {}
|
Skip(const Skip<U, _skip_s, _skip_d>& _skip) : value_(_skip.value()) {}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
Skip(const Default& _default) : value_(Type()) {}
|
Skip(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Skip() = default;
|
~Skip() = default;
|
||||||
|
@ -89,18 +93,20 @@ namespace rfl::internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U,
|
template <
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
class U,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||||
|
true>
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = _value;
|
value_ = _value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <class U = Type,
|
template <
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
class U = Type,
|
||||||
bool>::type = true>
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||||
|
type = true>
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -34,15 +34,19 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t N1, size_t N2>
|
template <size_t N1, size_t N2>
|
||||||
constexpr inline bool operator==(const StringLiteral<N1>& _first,
|
constexpr inline bool operator==(
|
||||||
const StringLiteral<N2>& _second) {
|
const StringLiteral<N1>& _first,
|
||||||
|
const StringLiteral<N2>& _second
|
||||||
|
) {
|
||||||
if constexpr (N1 != N2) { return false; }
|
if constexpr (N1 != N2) { return false; }
|
||||||
return _first.string_view() == _second.string_view();
|
return _first.string_view() == _second.string_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N1, size_t N2>
|
template <size_t N1, size_t N2>
|
||||||
constexpr inline bool operator!=(const StringLiteral<N1>& _first,
|
constexpr inline bool operator!=(
|
||||||
const StringLiteral<N2>& _second) {
|
const StringLiteral<N1>& _first,
|
||||||
|
const StringLiteral<N2>& _second
|
||||||
|
) {
|
||||||
return !(_first == _second);
|
return !(_first == _second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ namespace rfl {
|
||||||
struct VisitTree {
|
struct VisitTree {
|
||||||
/// Evaluates a visitor pattern using a tree-like structure.
|
/// Evaluates a visitor pattern using a tree-like structure.
|
||||||
template <int _begin, int _end, class Visitor, class... Args>
|
template <int _begin, int _end, class Visitor, class... Args>
|
||||||
static inline auto visit(const auto& _v,
|
static inline auto
|
||||||
const int _i,
|
visit(const auto& _v, const int _i, const Args&... _args) {
|
||||||
const Args&... _args) {
|
|
||||||
static_assert(_end > _begin, "_end needs to be greater than _begin.");
|
static_assert(_end > _begin, "_end needs to be greater than _begin.");
|
||||||
if constexpr (_end - _begin == 1) {
|
if constexpr (_end - _begin == 1) {
|
||||||
return _v.template visit<_begin>(_args...);
|
return _v.template visit<_begin>(_args...);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -13,8 +13,10 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class FieldNames, class... Fields>
|
template <class FieldNames, class... Fields>
|
||||||
auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple,
|
auto copy_flattened_tuple_to_named_tuple(
|
||||||
Fields&&... _fields) {
|
const auto& _flattened_tuple,
|
||||||
|
Fields&&... _fields
|
||||||
|
) {
|
||||||
constexpr auto size =
|
constexpr auto size =
|
||||||
std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
|
std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
|
||||||
constexpr auto i = sizeof...(_fields);
|
constexpr auto i = sizeof...(_fields);
|
||||||
|
@ -22,11 +24,13 @@ namespace rfl {
|
||||||
return make_named_tuple(std::move(_fields)...);
|
return make_named_tuple(std::move(_fields)...);
|
||||||
} else {
|
} else {
|
||||||
const auto name_literal = FieldNames::template name_of<i>();
|
const auto name_literal = FieldNames::template name_of<i>();
|
||||||
auto new_field = rfl::make_field<
|
auto new_field = rfl::make_field<
|
||||||
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
||||||
std::get<i>(_flattened_tuple));
|
std::get<i>(_flattened_tuple)
|
||||||
|
);
|
||||||
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
||||||
_flattened_tuple, std::move(_fields)..., std::move(new_field));
|
_flattened_tuple, std::move(_fields)..., std::move(new_field)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,17 @@ namespace rfl {
|
||||||
struct define_literal;
|
struct define_literal;
|
||||||
|
|
||||||
/// General case
|
/// General case
|
||||||
template <StringLiteral... _content1,
|
template <
|
||||||
StringLiteral... _content2,
|
StringLiteral... _content1,
|
||||||
class... Tail>
|
StringLiteral... _content2,
|
||||||
struct define_literal<Literal<_content1...>,
|
class... Tail>
|
||||||
Literal<_content2...>,
|
struct define_literal<
|
||||||
Tail...> {
|
Literal<_content1...>,
|
||||||
using type = typename define_literal<Literal<_content1..., _content2...>,
|
Literal<_content2...>,
|
||||||
Tail...>::type;
|
Tail...> {
|
||||||
|
using type = typename define_literal<
|
||||||
|
Literal<_content1..., _content2...>,
|
||||||
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Special case - only a single literal is left
|
/// Special case - only a single literal is left
|
||||||
|
|
|
@ -20,20 +20,22 @@ namespace rfl {
|
||||||
/// Recursive case - first type is NamedTuple, second type is field.
|
/// Recursive case - first type is NamedTuple, second type is field.
|
||||||
template <class Head, class... TupContent, class... Tail>
|
template <class Head, class... TupContent, class... Tail>
|
||||||
struct define_named_tuple<NamedTuple<TupContent...>, Head, Tail...> {
|
struct define_named_tuple<NamedTuple<TupContent...>, Head, Tail...> {
|
||||||
using type = typename define_named_tuple<NamedTuple<TupContent..., Head>,
|
using type = typename define_named_tuple<
|
||||||
Tail...>::type;
|
NamedTuple<TupContent..., Head>,
|
||||||
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Allows you to combine several named tuples and/or additional fields.
|
/// Allows you to combine several named tuples and/or additional fields.
|
||||||
/// Recursive case - first type is NamedTuple, second type is also
|
/// Recursive case - first type is NamedTuple, second type is also
|
||||||
/// NamedTuple.
|
/// NamedTuple.
|
||||||
template <class... TupContent, class... TupContent2, class... Tail>
|
template <class... TupContent, class... TupContent2, class... Tail>
|
||||||
struct define_named_tuple<NamedTuple<TupContent...>,
|
struct define_named_tuple<
|
||||||
NamedTuple<TupContent2...>,
|
NamedTuple<TupContent...>,
|
||||||
Tail...> {
|
NamedTuple<TupContent2...>,
|
||||||
using type =
|
Tail...> {
|
||||||
typename define_named_tuple<NamedTuple<TupContent..., TupContent2...>,
|
using type = typename define_named_tuple<
|
||||||
Tail...>::type;
|
NamedTuple<TupContent..., TupContent2...>,
|
||||||
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Allows you to combine several named tuples and/or additional fields.
|
/// Allows you to combine several named tuples and/or additional fields.
|
||||||
|
|
|
@ -12,14 +12,16 @@ namespace rfl {
|
||||||
struct define_tagged_union;
|
struct define_tagged_union;
|
||||||
|
|
||||||
/// Recursive case - both tagged union.
|
/// Recursive case - both tagged union.
|
||||||
template <StringLiteral _discriminator,
|
template <
|
||||||
class... NamedTupleTypes1,
|
StringLiteral _discriminator,
|
||||||
class... NamedTupleTypes2,
|
class... NamedTupleTypes1,
|
||||||
class... Tail>
|
class... NamedTupleTypes2,
|
||||||
struct define_tagged_union<_discriminator,
|
class... Tail>
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
struct define_tagged_union<
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
_discriminator,
|
||||||
Tail...> {
|
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
||||||
|
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
||||||
|
Tail...> {
|
||||||
using type = typename define_tagged_union<
|
using type = typename define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
|
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
|
||||||
|
@ -27,27 +29,31 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - tagged union plus named tuple.
|
/// Recursive case - tagged union plus named tuple.
|
||||||
template <StringLiteral _discriminator,
|
template <
|
||||||
class... NamedTupleTypes,
|
StringLiteral _discriminator,
|
||||||
class... FieldTypes,
|
class... NamedTupleTypes,
|
||||||
class... Tail>
|
class... FieldTypes,
|
||||||
struct define_tagged_union<_discriminator,
|
class... Tail>
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
struct define_tagged_union<
|
||||||
NamedTuple<FieldTypes...>,
|
_discriminator,
|
||||||
Tail...> {
|
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
||||||
using type =
|
NamedTuple<FieldTypes...>,
|
||||||
typename define_tagged_union<_discriminator,
|
Tail...> {
|
||||||
TaggedUnion<_discriminator,
|
using type = typename define_tagged_union<
|
||||||
NamedTupleTypes...,
|
_discriminator,
|
||||||
NamedTuple<FieldTypes...>>,
|
TaggedUnion<
|
||||||
Tail...>::type;
|
_discriminator,
|
||||||
|
NamedTupleTypes...,
|
||||||
|
NamedTuple<FieldTypes...>>,
|
||||||
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - named tuple.
|
/// Recursive case - named tuple.
|
||||||
template <StringLiteral _discriminator, class... FieldTypes, class... Tail>
|
template <StringLiteral _discriminator, class... FieldTypes, class... Tail>
|
||||||
struct define_tagged_union<_discriminator,
|
struct define_tagged_union<
|
||||||
NamedTuple<FieldTypes...>,
|
_discriminator,
|
||||||
Tail...> {
|
NamedTuple<FieldTypes...>,
|
||||||
|
Tail...> {
|
||||||
using type = typename define_tagged_union<
|
using type = typename define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<_discriminator, NamedTuple<FieldTypes...>>,
|
TaggedUnion<_discriminator, NamedTuple<FieldTypes...>>,
|
||||||
|
|
|
@ -12,11 +12,13 @@ namespace rfl {
|
||||||
|
|
||||||
/// Recursive case - both variants.
|
/// Recursive case - both variants.
|
||||||
template <class... Vars1, class... Vars2, class... Tail>
|
template <class... Vars1, class... Vars2, class... Tail>
|
||||||
struct define_variant<std::variant<Vars1...>,
|
struct define_variant<
|
||||||
std::variant<Vars2...>,
|
std::variant<Vars1...>,
|
||||||
Tail...> {
|
std::variant<Vars2...>,
|
||||||
using type = typename define_variant<std::variant<Vars1..., Vars2...>,
|
Tail...> {
|
||||||
Tail...>::type;
|
using type =
|
||||||
|
typename define_variant<std::variant<Vars1..., Vars2...>, Tail...>::
|
||||||
|
type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - variant plus other type.
|
/// Recursive case - variant plus other type.
|
||||||
|
|
|
@ -29,63 +29,86 @@ namespace rfl {
|
||||||
constexpr static std::array<EnumType, N> enums_ =
|
constexpr static std::array<EnumType, N> enums_ =
|
||||||
std::array<EnumType, N> {_enums...};
|
std::array<EnumType, N> {_enums...};
|
||||||
|
|
||||||
static_assert(N == 0 || LiteralType::size() == N,
|
static_assert(
|
||||||
"Size of literal and enum do not match.");
|
N == 0 || LiteralType::size() == N,
|
||||||
|
"Size of literal and enum do not match."
|
||||||
|
);
|
||||||
|
|
||||||
template <class NewLiteral, auto _new_enum>
|
template <class NewLiteral, auto _new_enum>
|
||||||
using AddOneType =
|
using AddOneType = std::conditional_t<
|
||||||
std::conditional_t<N == 0,
|
N == 0,
|
||||||
Names<EnumType, NewLiteral, 1, _new_enum>,
|
Names<EnumType, NewLiteral, 1, _new_enum>,
|
||||||
Names<EnumType,
|
Names<
|
||||||
define_literal_t<LiteralType, NewLiteral>,
|
EnumType,
|
||||||
N + 1,
|
define_literal_t<LiteralType, NewLiteral>,
|
||||||
_enums...,
|
N + 1,
|
||||||
_new_enum>>;
|
_enums...,
|
||||||
|
_new_enum>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EnumType,
|
template <
|
||||||
size_t N,
|
class EnumType,
|
||||||
StringLiteral... _names,
|
size_t N,
|
||||||
auto... _enums>
|
StringLiteral... _names,
|
||||||
auto names_to_enumerator_named_tuple(
|
auto... _enums>
|
||||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
auto names_to_enumerator_named_tuple(Names<
|
||||||
|
EnumType,
|
||||||
|
Literal<_names...>,
|
||||||
|
N,
|
||||||
|
_enums...>) {
|
||||||
return make_named_tuple(Field<_names, EnumType> {_enums}...);
|
return make_named_tuple(Field<_names, EnumType> {_enums}...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class EnumType,
|
template <
|
||||||
size_t N,
|
class EnumType,
|
||||||
StringLiteral... _names,
|
size_t N,
|
||||||
auto... _enums>
|
StringLiteral... _names,
|
||||||
auto names_to_underlying_enumerator_named_tuple(
|
auto... _enums>
|
||||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
auto names_to_underlying_enumerator_named_tuple(Names<
|
||||||
|
EnumType,
|
||||||
|
Literal<_names...>,
|
||||||
|
N,
|
||||||
|
_enums...>) {
|
||||||
return make_named_tuple(
|
return make_named_tuple(
|
||||||
Field<_names, std::underlying_type_t<EnumType>> {
|
Field<_names, std::underlying_type_t<EnumType>> {
|
||||||
static_cast<std::underlying_type_t<EnumType>>(_enums)}...);
|
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
||||||
|
}...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class EnumType,
|
template <
|
||||||
size_t N,
|
class EnumType,
|
||||||
StringLiteral... _names,
|
size_t N,
|
||||||
auto... _enums>
|
StringLiteral... _names,
|
||||||
|
auto... _enums>
|
||||||
constexpr std::array<std::pair<std::string_view, EnumType>, N>
|
constexpr std::array<std::pair<std::string_view, EnumType>, N>
|
||||||
names_to_enumerator_array(
|
names_to_enumerator_array(Names<
|
||||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
EnumType,
|
||||||
return {std::make_pair(LiteralHelper<_names>::field_.string_view(),
|
Literal<_names...>,
|
||||||
_enums)...};
|
N,
|
||||||
|
_enums...>) {
|
||||||
|
return {std::make_pair(
|
||||||
|
LiteralHelper<_names>::field_.string_view(), _enums
|
||||||
|
)...};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class EnumType,
|
template <
|
||||||
size_t N,
|
class EnumType,
|
||||||
StringLiteral... _names,
|
size_t N,
|
||||||
auto... _enums>
|
StringLiteral... _names,
|
||||||
|
auto... _enums>
|
||||||
constexpr std::array<
|
constexpr std::array<
|
||||||
std::pair<std::string_view, std::underlying_type_t<EnumType>>,
|
std::pair<std::string_view, std::underlying_type_t<EnumType>>,
|
||||||
N>
|
N>
|
||||||
names_to_underlying_enumerator_array(
|
names_to_underlying_enumerator_array(Names<
|
||||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
EnumType,
|
||||||
|
Literal<_names...>,
|
||||||
|
N,
|
||||||
|
_enums...>) {
|
||||||
return {std::make_pair(
|
return {std::make_pair(
|
||||||
LiteralHelper<_names>::field_.string_view(),
|
LiteralHelper<_names>::field_.string_view(),
|
||||||
static_cast<std::underlying_type_t<EnumType>>(_enums))...};
|
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
||||||
|
)...};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace rfl {
|
||||||
static_assert(
|
static_assert(
|
||||||
names_.size != 0,
|
names_.size != 0,
|
||||||
"No enum could be identified. Please choose enum values "
|
"No enum could be identified. Please choose enum values "
|
||||||
"between 0 to 127 or for flag enums choose 1,2,4,8,16,...");
|
"between 0 to 127 or for flag enums choose 1,2,4,8,16,..."
|
||||||
|
);
|
||||||
if constexpr (is_flag_enum_) {
|
if constexpr (is_flag_enum_) {
|
||||||
return string_to_flag_enum(_str);
|
return string_to_flag_enum(_str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,15 +56,16 @@ namespace rfl {
|
||||||
/// Iterates through the enum bit by bit and matches it against the
|
/// Iterates through the enum bit by bit and matches it against the
|
||||||
/// flags.
|
/// flags.
|
||||||
static std::string flag_enum_to_string(const EnumType _e) {
|
static std::string flag_enum_to_string(const EnumType _e) {
|
||||||
using T = std::underlying_type_t<EnumType>;
|
using T = std::underlying_type_t<EnumType>;
|
||||||
auto val = static_cast<T>(_e);
|
auto val = static_cast<T>(_e);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
std::vector<std::string> flags;
|
std::vector<std::string> flags;
|
||||||
while (val != 0) {
|
while (val != 0) {
|
||||||
const auto bit = val & static_cast<T>(1);
|
const auto bit = val & static_cast<T>(1);
|
||||||
if (bit == 1) {
|
if (bit == 1) {
|
||||||
auto str = enum_to_single_string(
|
auto str = enum_to_single_string(
|
||||||
static_cast<EnumType>(static_cast<T>(1) << i));
|
static_cast<EnumType>(static_cast<T>(1) << i)
|
||||||
|
);
|
||||||
flags.emplace_back(std::move(str));
|
flags.emplace_back(std::move(str));
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
|
@ -80,14 +82,16 @@ namespace rfl {
|
||||||
for (size_t i = 0; i < names_.size; ++i) {
|
for (size_t i = 0; i < names_.size; ++i) {
|
||||||
if (names_.enums_[i] == _enum) {
|
if (names_.enums_[i] == _enum) {
|
||||||
return NamesLiteral::from_value(
|
return NamesLiteral::from_value(
|
||||||
static_cast<typename NamesLiteral::ValueType>(i))
|
static_cast<typename NamesLiteral::ValueType>(i)
|
||||||
|
)
|
||||||
.transform(to_str)
|
.transform(to_str)
|
||||||
.value();
|
.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::to_string(
|
return std::to_string(
|
||||||
static_cast<std::underlying_type_t<EnumType>>(_enum));
|
static_cast<std::underlying_type_t<EnumType>>(_enum)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the enum matching the literal.
|
/// Finds the enum matching the literal.
|
||||||
|
@ -111,11 +115,11 @@ namespace rfl {
|
||||||
|
|
||||||
/// Only relevant if this is a flag enum - combines the different
|
/// Only relevant if this is a flag enum - combines the different
|
||||||
/// matches using |.
|
/// matches using |.
|
||||||
static Result<EnumType> string_to_flag_enum(
|
static Result<EnumType> string_to_flag_enum(const std::string& _str
|
||||||
const std::string& _str) noexcept {
|
) noexcept {
|
||||||
using T = std::underlying_type_t<EnumType>;
|
using T = std::underlying_type_t<EnumType>;
|
||||||
const auto split = strings::split(_str, "|");
|
const auto split = strings::split(_str, "|");
|
||||||
auto res = static_cast<T>(0);
|
auto res = static_cast<T>(0);
|
||||||
for (const auto& s : split) {
|
for (const auto& s : split) {
|
||||||
const auto r = single_string_to_enum(s);
|
const auto r = single_string_to_enum(s);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|
|
@ -63,7 +63,8 @@ namespace rfl {
|
||||||
static_assert(
|
static_assert(
|
||||||
false,
|
false,
|
||||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||||
"or MSVC or use rfl::Literal.");
|
"or MSVC or use rfl::Literal."
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,11 +106,12 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class EnumType,
|
template <
|
||||||
class NamesType,
|
class EnumType,
|
||||||
auto _max,
|
class NamesType,
|
||||||
bool _is_flag,
|
auto _max,
|
||||||
int _i>
|
bool _is_flag,
|
||||||
|
int _i>
|
||||||
consteval auto get_enum_names_impl() {
|
consteval auto get_enum_names_impl() {
|
||||||
using T = std::underlying_type_t<EnumType>;
|
using T = std::underlying_type_t<EnumType>;
|
||||||
|
|
||||||
|
@ -121,8 +123,8 @@ namespace rfl {
|
||||||
if constexpr (j == _max) {
|
if constexpr (j == _max) {
|
||||||
return NamesType {};
|
return NamesType {};
|
||||||
} else {
|
} else {
|
||||||
return get_enum_names_impl<EnumType, NamesType, _max, _is_flag,
|
return get_enum_names_impl<
|
||||||
_i + 1>();
|
EnumType, NamesType, _max, _is_flag, _i + 1>();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
using NewNames = typename NamesType::template AddOneType<
|
using NewNames = typename NamesType::template AddOneType<
|
||||||
|
@ -131,8 +133,8 @@ namespace rfl {
|
||||||
if constexpr (j == _max) {
|
if constexpr (j == _max) {
|
||||||
return NewNames {};
|
return NewNames {};
|
||||||
} else {
|
} else {
|
||||||
return get_enum_names_impl<EnumType, NewNames, _max, _is_flag,
|
return get_enum_names_impl<
|
||||||
_i + 1>();
|
EnumType, NewNames, _max, _is_flag, _i + 1>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,10 +144,13 @@ namespace rfl {
|
||||||
static_assert(
|
static_assert(
|
||||||
is_scoped_enum<EnumType>,
|
is_scoped_enum<EnumType>,
|
||||||
"You must use scoped enums (using class or struct) for the "
|
"You must use scoped enums (using class or struct) for the "
|
||||||
"parsing to work!");
|
"parsing to work!"
|
||||||
|
);
|
||||||
|
|
||||||
static_assert(std::is_integral_v<std::underlying_type_t<EnumType>>,
|
static_assert(
|
||||||
"The underlying type of any Enum must be integral!");
|
std::is_integral_v<std::underlying_type_t<EnumType>>,
|
||||||
|
"The underlying type of any Enum must be integral!"
|
||||||
|
);
|
||||||
|
|
||||||
constexpr auto max =
|
constexpr auto max =
|
||||||
get_max<std::underlying_type_t<EnumType>, _is_flag>();
|
get_max<std::underlying_type_t<EnumType>, _is_flag>();
|
||||||
|
|
|
@ -35,9 +35,10 @@ namespace rfl {
|
||||||
|
|
||||||
/// For variants - in this case the FieldType returned by all options must
|
/// For variants - in this case the FieldType returned by all options must
|
||||||
/// be the same.
|
/// be the same.
|
||||||
template <StringLiteral _field_name,
|
template <
|
||||||
class FirstAlternativeType,
|
StringLiteral _field_name,
|
||||||
class... OtherAlternativeTypes>
|
class FirstAlternativeType,
|
||||||
|
class... OtherAlternativeTypes>
|
||||||
struct FieldType<
|
struct FieldType<
|
||||||
_field_name,
|
_field_name,
|
||||||
std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
|
std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
|
||||||
|
@ -51,15 +52,17 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// For tagged union - just defers to the variant.
|
/// For tagged union - just defers to the variant.
|
||||||
template <StringLiteral _field_name,
|
template <
|
||||||
StringLiteral _discriminator_name,
|
StringLiteral _field_name,
|
||||||
class... VarTypes>
|
StringLiteral _discriminator_name,
|
||||||
struct FieldType<_field_name,
|
class... VarTypes>
|
||||||
TaggedUnion<_discriminator_name, VarTypes...>> {
|
struct FieldType<
|
||||||
|
_field_name,
|
||||||
|
TaggedUnion<_discriminator_name, VarTypes...>> {
|
||||||
using Type = typename FieldType<
|
using Type = typename FieldType<
|
||||||
_field_name,
|
_field_name,
|
||||||
typename TaggedUnion<_discriminator_name,
|
typename TaggedUnion<_discriminator_name, VarTypes...>::VariantType>::
|
||||||
VarTypes...>::VariantType>::Type;
|
Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -10,9 +10,8 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using flattened_ptr_tuple_t =
|
using flattened_ptr_tuple_t = typename std::
|
||||||
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>),
|
invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
|
||||||
T>::type;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct wrapper {
|
struct wrapper {
|
||||||
const T value;
|
const T value;
|
||||||
static const wrapper<T> report_if_you_see_a_link_error_with_this_object;
|
static const wrapper<T> report_if_you_see_a_link_error_with_this_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,15 @@ namespace rfl::internal {
|
||||||
static_assert(
|
static_assert(
|
||||||
false,
|
false,
|
||||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||||
"or MSVC or switch to the rfl::Field-syntax.");
|
"or MSVC or switch to the rfl::Field-syntax."
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, auto ptr>
|
template <class T, auto ptr>
|
||||||
consteval auto get_field_name_str_lit() {
|
consteval auto get_field_name_str_lit() {
|
||||||
constexpr auto name = get_field_name_str_view<T, ptr>();
|
constexpr auto name = get_field_name_str_view<T, ptr>();
|
||||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||||
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
||||||
};
|
};
|
||||||
return to_str_lit(std::make_index_sequence<name.size()> {});
|
return to_str_lit(std::make_index_sequence<name.size()> {});
|
||||||
|
@ -99,8 +100,10 @@ namespace rfl::internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <StringLiteral... _names1, StringLiteral... _names2>
|
template <StringLiteral... _names1, StringLiteral... _names2>
|
||||||
auto concat_two_literals(const rfl::Literal<_names1...>& _lit1,
|
auto concat_two_literals(
|
||||||
const rfl::Literal<_names2...>& _lit2) {
|
const rfl::Literal<_names1...>& _lit1,
|
||||||
|
const rfl::Literal<_names2...>& _lit2
|
||||||
|
) {
|
||||||
return rfl::Literal<_names1..., _names2...>::template from_value<0>();
|
return rfl::Literal<_names1..., _names2...>::template from_value<0>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,14 +138,16 @@ namespace rfl::internal {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||||
return concat_literals(
|
return concat_literals(
|
||||||
get_field_name<Type, wrap(std::get<Is>(
|
get_field_name<
|
||||||
bind_fake_object_to_tuple<T>()))>()...);
|
Type, wrap(std::get<Is>(bind_fake_object_to_tuple<T>()))>()...
|
||||||
|
);
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||||
return concat_literals(
|
return concat_literals(
|
||||||
get_field_name<Type,
|
get_field_name<Type, std::get<Is>(bind_fake_object_to_tuple<T>())>(
|
||||||
std::get<Is>(bind_fake_object_to_tuple<T>())>()...);
|
)...
|
||||||
|
);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
return get(std::make_index_sequence<num_fields<T>>());
|
return get(std::make_index_sequence<num_fields<T>>());
|
||||||
|
|
|
@ -23,7 +23,8 @@ namespace rfl {
|
||||||
auto type = type_name_t<typename FieldType::Type>().str();
|
auto type = type_name_t<typename FieldType::Type>().str();
|
||||||
return get_meta_fields<NamedTupleType>(
|
return get_meta_fields<NamedTupleType>(
|
||||||
std::move(_already_extracted)...,
|
std::move(_already_extracted)...,
|
||||||
MetaField(std::move(name), std::move(type)));
|
MetaField(std::move(name), std::move(type))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,19 @@ namespace rfl {
|
||||||
static_assert(
|
static_assert(
|
||||||
false,
|
false,
|
||||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||||
"or MSVC or explicitly tag your structs using 'Tag' or 'Name'.");
|
"or MSVC or explicitly tag your structs using 'Tag' or 'Name'."
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
consteval auto get_type_name() {
|
consteval auto get_type_name() {
|
||||||
static_assert(get_type_name_str_view<int>() == "int",
|
static_assert(
|
||||||
"Expected 'int', got something else.");
|
get_type_name_str_view<int>() == "int",
|
||||||
constexpr auto name = get_type_name_str_view<T>();
|
"Expected 'int', got something else."
|
||||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
);
|
||||||
|
constexpr auto name = get_type_name_str_view<T>();
|
||||||
|
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||||
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
||||||
};
|
};
|
||||||
return to_str_lit(std::make_index_sequence<name.size()> {});
|
return to_str_lit(std::make_index_sequence<name.size()> {});
|
||||||
|
|
|
@ -57,7 +57,8 @@ namespace rfl {
|
||||||
"If some of your fields are annotated using rfl::Field<...>, "
|
"If some of your fields are annotated using rfl::Field<...>, "
|
||||||
"then you must annotate all of your fields. "
|
"then you must annotate all of your fields. "
|
||||||
"Also, you cannot combine annotated and "
|
"Also, you cannot combine annotated and "
|
||||||
"unannotated fields using rfl::Flatten<...>.");
|
"unannotated fields using rfl::Flatten<...>."
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,11 +20,14 @@ namespace rfl {
|
||||||
return move_and_flatten_field_tuple(
|
return move_and_flatten_field_tuple(
|
||||||
std::move(_t), std::move(_args)...,
|
std::move(_t), std::move(_args)...,
|
||||||
move_and_flatten_field_tuple(
|
move_and_flatten_field_tuple(
|
||||||
move_to_field_tuple(std::move(std::get<i>(_t).value_))));
|
move_to_field_tuple(std::move(std::get<i>(_t).value_))
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return move_and_flatten_field_tuple(
|
return move_and_flatten_field_tuple(
|
||||||
std::move(_t), std::move(_args)...,
|
std::move(_t), std::move(_args)...,
|
||||||
std::make_tuple(std::move(std::get<i>(_t))));
|
std::make_tuple(std::move(std::get<i>(_t)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,23 +29,25 @@ namespace rfl {
|
||||||
std::remove_cvref_t<std::remove_pointer_t<typename Field::Type>>;
|
std::remove_cvref_t<std::remove_pointer_t<typename Field::Type>>;
|
||||||
|
|
||||||
if constexpr (is_named_tuple_v<T>) {
|
if constexpr (is_named_tuple_v<T>) {
|
||||||
using SubPtrNamedTupleType =
|
using SubPtrNamedTupleType = typename std::invoke_result<
|
||||||
typename std::invoke_result<decltype(nt_to_ptr_named_tuple<T>),
|
decltype(nt_to_ptr_named_tuple<T>), T>::type;
|
||||||
T>::type;
|
|
||||||
|
|
||||||
return make_ptr_fields<PtrFieldTupleType>(
|
return make_ptr_fields<PtrFieldTupleType>(
|
||||||
_n, _args..., SubPtrNamedTupleType(_n).fields());
|
_n, _args..., SubPtrNamedTupleType(_n).fields()
|
||||||
|
);
|
||||||
|
|
||||||
} else if constexpr (is_flatten_field<Field>::value) {
|
} else if constexpr (is_flatten_field<Field>::value) {
|
||||||
using SubPtrFieldTupleType =
|
using SubPtrFieldTupleType =
|
||||||
std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||||
|
|
||||||
return make_ptr_fields<PtrFieldTupleType>(
|
return make_ptr_fields<PtrFieldTupleType>(
|
||||||
_n, _args..., make_ptr_fields<SubPtrFieldTupleType>(_n));
|
_n, _args..., make_ptr_fields<SubPtrFieldTupleType>(_n)
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return make_ptr_fields<PtrFieldTupleType>(
|
return make_ptr_fields<PtrFieldTupleType>(
|
||||||
_n, _args..., _n.template get_field<Field::name_>());
|
_n, _args..., _n.template get_field<Field::name_>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +65,9 @@ namespace rfl {
|
||||||
return move_from_ptr_fields<T>(
|
return move_from_ptr_fields<T>(
|
||||||
_ptrs, std::move(_args)...,
|
_ptrs, std::move(_args)...,
|
||||||
rfl::make_field<FieldType::name_>(
|
rfl::make_field<FieldType::name_>(
|
||||||
std::move(*std::get<i>(_ptrs).value())));
|
std::move(*std::get<i>(_ptrs).value())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||||
|
@ -73,7 +77,8 @@ namespace rfl {
|
||||||
|
|
||||||
return move_from_ptr_fields<T>(
|
return move_from_ptr_fields<T>(
|
||||||
_ptrs, std::move(_args)...,
|
_ptrs, std::move(_args)...,
|
||||||
move_from_ptr_fields<U>(std::get<i>(_ptrs)));
|
move_from_ptr_fields<U>(std::get<i>(_ptrs))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +92,9 @@ namespace rfl {
|
||||||
if constexpr (is_named_tuple_v<std::remove_cvref_t<T>>) {
|
if constexpr (is_named_tuple_v<std::remove_cvref_t<T>>) {
|
||||||
return std::move(_n);
|
return std::move(_n);
|
||||||
|
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<NamedTupleType>,
|
} else if constexpr (std::is_same<
|
||||||
RequiredType>()) {
|
std::remove_cvref_t<NamedTupleType>,
|
||||||
|
RequiredType>()) {
|
||||||
auto ptr_named_tuple = nt_to_ptr_named_tuple(_n);
|
auto ptr_named_tuple = nt_to_ptr_named_tuple(_n);
|
||||||
|
|
||||||
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||||
|
@ -98,8 +104,8 @@ namespace rfl {
|
||||||
return move_from_ptr_fields<T>(pointers);
|
return move_from_ptr_fields<T>(pointers);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return move_from_named_tuple<T, RequiredType>(
|
return move_from_named_tuple<T, RequiredType>(RequiredType(std::move(_n)
|
||||||
RequiredType(std::move(_n)));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,11 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TargetTupleType,
|
template <
|
||||||
class PtrTupleType,
|
class TargetTupleType,
|
||||||
int _j = 0,
|
class PtrTupleType,
|
||||||
class... Args>
|
int _j = 0,
|
||||||
|
class... Args>
|
||||||
auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
|
auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
|
||||||
constexpr auto i = sizeof...(Args);
|
constexpr auto i = sizeof...(Args);
|
||||||
|
|
||||||
|
@ -52,14 +53,16 @@ namespace rfl {
|
||||||
constexpr int flattened_size =
|
constexpr int flattened_size =
|
||||||
calc_flattened_size<SubTargetTupleType>();
|
calc_flattened_size<SubTargetTupleType>();
|
||||||
|
|
||||||
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType,
|
return unflatten_ptr_tuple<
|
||||||
_j + flattened_size>(
|
TargetTupleType, PtrTupleType, _j + flattened_size>(
|
||||||
_t, _args...,
|
_t, _args...,
|
||||||
unflatten_ptr_tuple<SubTargetTupleType, PtrTupleType, _j>(_t));
|
unflatten_ptr_tuple<SubTargetTupleType, PtrTupleType, _j>(_t)
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType, _j + 1>(
|
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType, _j + 1>(
|
||||||
_t, _args..., std::get<_j>(_t));
|
_t, _args..., std::get<_j>(_t)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +77,9 @@ namespace rfl {
|
||||||
std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
|
std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
|
||||||
|
|
||||||
if constexpr (std::is_pointer_v<FieldType>) {
|
if constexpr (std::is_pointer_v<FieldType>) {
|
||||||
return move_from_pointers<T>(_ptrs, std::move(_args)...,
|
return move_from_pointers<T>(
|
||||||
std::move(*std::get<i>(_ptrs)));
|
_ptrs, std::move(_args)..., std::move(*std::get<i>(_ptrs))
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
using PtrTupleType = ptr_tuple_t<std::remove_cvref_t<T>>;
|
using PtrTupleType = ptr_tuple_t<std::remove_cvref_t<T>>;
|
||||||
|
@ -85,7 +89,8 @@ namespace rfl {
|
||||||
|
|
||||||
return move_from_pointers<T>(
|
return move_from_pointers<T>(
|
||||||
_ptrs, std::move(_args)...,
|
_ptrs, std::move(_args)...,
|
||||||
move_from_pointers<U>(std::get<i>(_ptrs)));
|
move_from_pointers<U>(std::get<i>(_ptrs))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,16 @@ namespace rfl {
|
||||||
using FieldType = typename std::tuple_element<i, Fields>::type;
|
using FieldType = typename std::tuple_element<i, Fields>::type;
|
||||||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||||
return nt_to_ptr_named_tuple(
|
return nt_to_ptr_named_tuple(
|
||||||
_nt, _a...,
|
_nt, _a..., Field<FieldType::name_, T*>(&std::get<i>(_nt.values()))
|
||||||
Field<FieldType::name_, T*>(&std::get<i>(_nt.values())));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a named tuple that contains pointers to the original values in
|
/// Generates a named tuple that contains pointers to the original values in
|
||||||
/// the struct from a named tuple.
|
/// the struct from a named tuple.
|
||||||
template <class NamedTupleType, class... AlreadyExtracted>
|
template <class NamedTupleType, class... AlreadyExtracted>
|
||||||
auto nt_to_ptr_named_tuple(const NamedTupleType& _nt,
|
auto
|
||||||
AlreadyExtracted... _a) {
|
nt_to_ptr_named_tuple(const NamedTupleType& _nt, AlreadyExtracted... _a) {
|
||||||
using Fields = typename NamedTupleType::Fields;
|
using Fields = typename NamedTupleType::Fields;
|
||||||
|
|
||||||
constexpr auto i = sizeof...(AlreadyExtracted);
|
constexpr auto i = sizeof...(AlreadyExtracted);
|
||||||
|
@ -46,7 +46,8 @@ namespace rfl {
|
||||||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||||
return nt_to_ptr_named_tuple(
|
return nt_to_ptr_named_tuple(
|
||||||
_nt, _a...,
|
_nt, _a...,
|
||||||
Field<FieldType::name_, const T*>(&std::get<i>(_nt.values())));
|
Field<FieldType::name_, const T*>(&std::get<i>(_nt.values()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,7 @@ namespace rfl {
|
||||||
struct any_empty_base {
|
struct any_empty_base {
|
||||||
any_empty_base(std::size_t);
|
any_empty_base(std::size_t);
|
||||||
template <class Base>
|
template <class Base>
|
||||||
requires(std::is_empty_v<std::remove_cvref_t<Base>> &&
|
requires(std::is_empty_v<std::remove_cvref_t<Base>> && std::is_base_of_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>> && !std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
|
||||||
std::is_base_of_v<std::remove_cvref_t<Base>,
|
|
||||||
std::remove_cv_t<Derived>> &&
|
|
||||||
!std::is_same_v<std::remove_cvref_t<Base>,
|
|
||||||
std::remove_cv_t<Derived>>)
|
|
||||||
constexpr operator Base&() const noexcept;
|
constexpr operator Base&() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,10 +61,7 @@ namespace rfl {
|
||||||
struct any_base {
|
struct any_base {
|
||||||
any_base(std::size_t);
|
any_base(std::size_t);
|
||||||
template <class Base>
|
template <class Base>
|
||||||
requires(std::is_base_of_v<std::remove_cvref_t<Base>,
|
requires(std::is_base_of_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>> && !std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
|
||||||
std::remove_cv_t<Derived>> &&
|
|
||||||
!std::is_same_v<std::remove_cvref_t<Base>,
|
|
||||||
std::remove_cv_t<Derived>>)
|
|
||||||
constexpr operator Base&() const noexcept;
|
constexpr operator Base&() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,12 +82,13 @@ namespace rfl {
|
||||||
|
|
||||||
template <std::size_t l, std::size_t nested, std::size_t r>
|
template <std::size_t l, std::size_t nested, std::size_t r>
|
||||||
static consteval bool constructible_with_nested() {
|
static consteval bool constructible_with_nested() {
|
||||||
return []<std::size_t... i, std::size_t... j, std::size_t... k>(
|
return
|
||||||
std::index_sequence<i...>, std::index_sequence<j...>,
|
[]<std::size_t... i, std::size_t... j,
|
||||||
std::index_sequence<k...>) {
|
std::
|
||||||
return requires { T {any(i)..., {any(j)...}, any(k)...}; };
|
size_t... k>(std::index_sequence<i...>, std::index_sequence<j...>, std::index_sequence<k...>) {
|
||||||
}(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
|
return requires { T {any(i)..., {any(j)...}, any(k)...}; };
|
||||||
std::make_index_sequence<r>());
|
}(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
|
||||||
|
std::make_index_sequence<r>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t n = 0>
|
template <std::size_t n = 0>
|
||||||
|
@ -112,8 +106,8 @@ namespace rfl {
|
||||||
if constexpr (size < 1) {
|
if constexpr (size < 1) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if constexpr (constructible_with_nested<index, size, rest>() &&
|
} else if constexpr (constructible_with_nested<index, size, rest>() &&
|
||||||
!constructible_with_nested<index, size,
|
!constructible_with_nested<index, size, rest + 1>(
|
||||||
rest + 1>()) {
|
)) {
|
||||||
return size;
|
return size;
|
||||||
} else {
|
} else {
|
||||||
return get_nested_array_size<index, size - 1, rest + 1>();
|
return get_nested_array_size<index, size - 1, rest + 1>();
|
||||||
|
@ -123,17 +117,20 @@ namespace rfl {
|
||||||
template <std::size_t max_args, std::size_t index = 0>
|
template <std::size_t max_args, std::size_t index = 0>
|
||||||
static consteval std::size_t find_the_sole_non_empty_base_index() {
|
static consteval std::size_t find_the_sole_non_empty_base_index() {
|
||||||
static_assert(index < max_args);
|
static_assert(index < max_args);
|
||||||
constexpr auto check = []<std::size_t... l, std::size_t... r>(
|
constexpr auto check =
|
||||||
std::index_sequence<l...>,
|
[]<std::size_t... l,
|
||||||
std::index_sequence<r...>) {
|
std::
|
||||||
return requires {
|
size_t... r>(std::index_sequence<l...>, std::index_sequence<r...>) {
|
||||||
T {any_empty_base<T>(l)..., any_base<T>(0),
|
return requires {
|
||||||
any_empty_base<T>(r)...};
|
T {any_empty_base<T>(l)..., any_base<T>(0),
|
||||||
};
|
any_empty_base<T>(r)...};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if constexpr (check(std::make_index_sequence<index>(),
|
if constexpr (check(
|
||||||
std::make_index_sequence<max_args - index - 1>())) {
|
std::make_index_sequence<index>(),
|
||||||
|
std::make_index_sequence<max_args - index - 1>()
|
||||||
|
)) {
|
||||||
return index;
|
return index;
|
||||||
} else {
|
} else {
|
||||||
return find_the_sole_non_empty_base_index<max_args, index + 1>();
|
return find_the_sole_non_empty_base_index<max_args, index + 1>();
|
||||||
|
@ -154,10 +151,13 @@ namespace rfl {
|
||||||
template <std::size_t n, std::size_t max_arg_num>
|
template <std::size_t n, std::size_t max_arg_num>
|
||||||
static consteval bool has_n_base_param() {
|
static consteval bool has_n_base_param() {
|
||||||
constexpr auto right_len = max_arg_num >= n ? max_arg_num - n : 0;
|
constexpr auto right_len = max_arg_num >= n ? max_arg_num - n : 0;
|
||||||
return []<std::size_t... l, std::size_t... r>(
|
return
|
||||||
std::index_sequence<l...>, std::index_sequence<r...>) {
|
[]<std::size_t... l,
|
||||||
return requires { T {any_base<T>(l)..., any(r)...}; };
|
std::
|
||||||
}(std::make_index_sequence<n>(), std::make_index_sequence<right_len>());
|
size_t... r>(std::index_sequence<l...>, std::index_sequence<r...>) {
|
||||||
|
return requires { T {any_base<T>(l)..., any(r)...}; };
|
||||||
|
}(std::make_index_sequence<n>(),
|
||||||
|
std::make_index_sequence<right_len>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t max_arg_num, std::size_t index = 0>
|
template <std::size_t max_arg_num, std::size_t index = 0>
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace rfl::internal {
|
||||||
struct Processed<StructType, Processors<Ps...>> {
|
struct Processed<StructType, Processors<Ps...>> {
|
||||||
using NamedTupleType = named_tuple_t<StructType>;
|
using NamedTupleType = named_tuple_t<StructType>;
|
||||||
using type = typename std::invoke_result<
|
using type = typename std::invoke_result<
|
||||||
decltype(Processors<Ps...>::template process<StructType,
|
decltype(Processors<
|
||||||
NamedTupleType>),
|
Ps...>::template process<StructType, NamedTupleType>),
|
||||||
NamedTupleType>::type;
|
NamedTupleType>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,28 +14,32 @@ namespace rfl {
|
||||||
|
|
||||||
/// Recursively builds a new NamedTuple type from the FieldTypes, leaving
|
/// Recursively builds a new NamedTuple type from the FieldTypes, leaving
|
||||||
/// out the field signified by _name.
|
/// out the field signified by _name.
|
||||||
template <class _OldNamedTupleType,
|
template <
|
||||||
StringLiteral _name,
|
class _OldNamedTupleType,
|
||||||
class _NewNamedTupleType,
|
StringLiteral _name,
|
||||||
int _i>
|
class _NewNamedTupleType,
|
||||||
|
int _i>
|
||||||
struct remove_single_field;
|
struct remove_single_field;
|
||||||
|
|
||||||
/// Special case - _i == 0
|
/// Special case - _i == 0
|
||||||
template <class _OldNamedTupleType,
|
template <
|
||||||
StringLiteral _name,
|
class _OldNamedTupleType,
|
||||||
class _NewNamedTupleType>
|
StringLiteral _name,
|
||||||
struct remove_single_field<_OldNamedTupleType,
|
class _NewNamedTupleType>
|
||||||
_name,
|
struct remove_single_field<
|
||||||
_NewNamedTupleType,
|
_OldNamedTupleType,
|
||||||
0> {
|
_name,
|
||||||
|
_NewNamedTupleType,
|
||||||
|
0> {
|
||||||
using type = _NewNamedTupleType;
|
using type = _NewNamedTupleType;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// General case.
|
/// General case.
|
||||||
template <class _OldNamedTupleType,
|
template <
|
||||||
StringLiteral _name,
|
class _OldNamedTupleType,
|
||||||
class _NewNamedTupleType,
|
StringLiteral _name,
|
||||||
int _i>
|
class _NewNamedTupleType,
|
||||||
|
int _i>
|
||||||
struct remove_single_field {
|
struct remove_single_field {
|
||||||
using OldNamedTupleType = std::remove_cvref_t<_OldNamedTupleType>;
|
using OldNamedTupleType = std::remove_cvref_t<_OldNamedTupleType>;
|
||||||
|
|
||||||
|
@ -51,17 +55,19 @@ namespace rfl {
|
||||||
_NewNamedTupleType,
|
_NewNamedTupleType,
|
||||||
define_named_tuple_t<_NewNamedTupleType, FieldType>>;
|
define_named_tuple_t<_NewNamedTupleType, FieldType>>;
|
||||||
|
|
||||||
using type = typename remove_single_field<OldNamedTupleType,
|
using type = typename remove_single_field<
|
||||||
_name,
|
OldNamedTupleType,
|
||||||
NewNamedTupleType,
|
_name,
|
||||||
_i - 1>::type;
|
NewNamedTupleType,
|
||||||
|
_i - 1>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursively removes all of the fields signified by _head and _tail from
|
/// Recursively removes all of the fields signified by _head and _tail from
|
||||||
/// the NamedTupleType.
|
/// the NamedTupleType.
|
||||||
template <class _NamedTupleType,
|
template <
|
||||||
StringLiteral _head,
|
class _NamedTupleType,
|
||||||
StringLiteral... _tail>
|
StringLiteral _head,
|
||||||
|
StringLiteral... _tail>
|
||||||
struct remove_fields;
|
struct remove_fields;
|
||||||
|
|
||||||
/// Special case - only head is left.
|
/// Special case - only head is left.
|
||||||
|
@ -72,26 +78,29 @@ namespace rfl {
|
||||||
constexpr static int num_fields =
|
constexpr static int num_fields =
|
||||||
std::tuple_size_v<typename NamedTupleType::Fields>;
|
std::tuple_size_v<typename NamedTupleType::Fields>;
|
||||||
|
|
||||||
using type = typename remove_single_field<NamedTupleType,
|
using type = typename remove_single_field<
|
||||||
_head,
|
NamedTupleType,
|
||||||
NamedTuple<>,
|
_head,
|
||||||
num_fields>::type;
|
NamedTuple<>,
|
||||||
|
num_fields>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// General case.
|
/// General case.
|
||||||
template <class _NamedTupleType,
|
template <
|
||||||
StringLiteral _head,
|
class _NamedTupleType,
|
||||||
StringLiteral... _tail>
|
StringLiteral _head,
|
||||||
|
StringLiteral... _tail>
|
||||||
struct remove_fields {
|
struct remove_fields {
|
||||||
using NamedTupleType = std::remove_cvref_t<_NamedTupleType>;
|
using NamedTupleType = std::remove_cvref_t<_NamedTupleType>;
|
||||||
|
|
||||||
constexpr static int num_fields =
|
constexpr static int num_fields =
|
||||||
std::tuple_size_v<typename NamedTupleType::Fields>;
|
std::tuple_size_v<typename NamedTupleType::Fields>;
|
||||||
|
|
||||||
using NewNamedTupleType = typename remove_single_field<NamedTupleType,
|
using NewNamedTupleType = typename remove_single_field<
|
||||||
_head,
|
NamedTupleType,
|
||||||
NamedTuple<>,
|
_head,
|
||||||
num_fields>::type;
|
NamedTuple<>,
|
||||||
|
num_fields>::type;
|
||||||
|
|
||||||
using type = typename remove_fields<NewNamedTupleType, _tail...>::type;
|
using type = typename remove_fields<NewNamedTupleType, _tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,11 +12,11 @@ namespace rfl {
|
||||||
|
|
||||||
template <StringLiteral _name>
|
template <StringLiteral _name>
|
||||||
consteval auto remove_namespaces() {
|
consteval auto remove_namespaces() {
|
||||||
constexpr auto name = _name.string_view();
|
constexpr auto name = _name.string_view();
|
||||||
constexpr size_t pos = name.find_last_of(":");
|
constexpr size_t pos = name.find_last_of(":");
|
||||||
if constexpr (pos == std::string_view::npos) { return _name; }
|
if constexpr (pos == std::string_view::npos) { return _name; }
|
||||||
constexpr auto substr = name.substr(pos + 1);
|
constexpr auto substr = name.substr(pos + 1);
|
||||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||||
return StringLiteral<sizeof...(Ns) + 1> {substr[Ns]...};
|
return StringLiteral<sizeof...(Ns) + 1> {substr[Ns]...};
|
||||||
};
|
};
|
||||||
return to_str_lit(std::make_index_sequence<substr.size()> {});
|
return to_str_lit(std::make_index_sequence<substr.size()> {});
|
||||||
|
|
|
@ -9,8 +9,10 @@ namespace rfl {
|
||||||
namespace strings {
|
namespace strings {
|
||||||
|
|
||||||
/// Joins a string using the delimiter
|
/// Joins a string using the delimiter
|
||||||
inline std::string join(const std::string& _delimiter,
|
inline std::string join(
|
||||||
const std::vector<std::string>& _strings) {
|
const std::string& _delimiter,
|
||||||
|
const std::vector<std::string>& _strings
|
||||||
|
) {
|
||||||
if (_strings.size() == 0) { return ""; }
|
if (_strings.size() == 0) { return ""; }
|
||||||
auto res = _strings[0];
|
auto res = _strings[0];
|
||||||
for (size_t i = 1; i < _strings.size(); ++i) {
|
for (size_t i = 1; i < _strings.size(); ++i) {
|
||||||
|
|
|
@ -8,9 +8,11 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
namespace strings {
|
namespace strings {
|
||||||
|
|
||||||
inline std::string replace_all(const std::string& _str,
|
inline std::string replace_all(
|
||||||
const std::string& _from,
|
const std::string& _str,
|
||||||
const std::string& _to) {
|
const std::string& _from,
|
||||||
|
const std::string& _to
|
||||||
|
) {
|
||||||
auto str = _str;
|
auto str = _str;
|
||||||
|
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|
|
@ -9,10 +9,10 @@ namespace rfl {
|
||||||
namespace strings {
|
namespace strings {
|
||||||
|
|
||||||
/// Splits a string alongside the delimiter
|
/// Splits a string alongside the delimiter
|
||||||
inline std::vector<std::string> split(const std::string& _str,
|
inline std::vector<std::string>
|
||||||
const std::string& _delimiter) {
|
split(const std::string& _str, const std::string& _delimiter) {
|
||||||
auto str = _str;
|
auto str = _str;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
while ((pos = str.find(_delimiter)) != std::string::npos) {
|
while ((pos = str.find(_delimiter)) != std::string::npos) {
|
||||||
result.emplace_back(str.substr(0, pos));
|
result.emplace_back(str.substr(0, pos));
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
namespace rfl::internal {
|
namespace rfl::internal {
|
||||||
|
|
||||||
template <internal::StringLiteral _discriminator, class T>
|
template <internal::StringLiteral _discriminator, class T>
|
||||||
using tag_t =
|
using tag_t = typename std::
|
||||||
typename std::invoke_result<decltype(make_tag<_discriminator, T>),
|
invoke_result<decltype(make_tag<_discriminator, T>), T>::type;
|
||||||
T>::type;
|
|
||||||
|
|
||||||
} // namespace rfl::internal
|
} // namespace rfl::internal
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,13 @@ namespace rfl {
|
||||||
if constexpr (is_flatten_field_v<T>) {
|
if constexpr (is_flatten_field_v<T>) {
|
||||||
return flatten_ptr_tuple(
|
return flatten_ptr_tuple(
|
||||||
std::forward<PtrTuple>(_t), std::forward<Args>(_args)...,
|
std::forward<PtrTuple>(_t), std::forward<Args>(_args)...,
|
||||||
flatten_ptr_tuple(to_ptr_tuple(std::get<i>(_t)->get())));
|
flatten_ptr_tuple(to_ptr_tuple(std::get<i>(_t)->get()))
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return flatten_ptr_tuple(std::forward<PtrTuple>(_t),
|
return flatten_ptr_tuple(
|
||||||
std::forward<Args>(_args)...,
|
std::forward<PtrTuple>(_t), std::forward<Args>(_args)...,
|
||||||
std::make_tuple(std::get<i>(_t)));
|
std::make_tuple(std::get<i>(_t))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,14 @@ namespace rfl {
|
||||||
using T = std::tuple_element_t<i, std::remove_cvref_t<PtrFieldTuple>>;
|
using T = std::tuple_element_t<i, std::remove_cvref_t<PtrFieldTuple>>;
|
||||||
if constexpr (internal::is_flatten_field<T>::value) {
|
if constexpr (internal::is_flatten_field<T>::value) {
|
||||||
auto subtuple = internal::to_ptr_field_tuple(*std::get<i>(_t).get());
|
auto subtuple = internal::to_ptr_field_tuple(*std::get<i>(_t).get());
|
||||||
return flatten_ptr_field_tuple(_t, std::forward<Args>(_args)...,
|
return flatten_ptr_field_tuple(
|
||||||
flatten_ptr_field_tuple(subtuple));
|
_t, std::forward<Args>(_args)...,
|
||||||
|
flatten_ptr_field_tuple(subtuple)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return flatten_ptr_field_tuple(_t, std::forward<Args>(_args)...,
|
return flatten_ptr_field_tuple(
|
||||||
std::make_tuple(std::get<i>(_t)));
|
_t, std::forward<Args>(_args)..., std::make_tuple(std::get<i>(_t))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +74,8 @@ namespace rfl {
|
||||||
using FieldNames = rfl::field_names_t<T>;
|
using FieldNames = rfl::field_names_t<T>;
|
||||||
auto flattened_ptr_tuple = to_flattened_ptr_tuple(_t);
|
auto flattened_ptr_tuple = to_flattened_ptr_tuple(_t);
|
||||||
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
||||||
flattened_ptr_tuple);
|
flattened_ptr_tuple
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace rfl::internal {
|
||||||
constexpr size_t n = StdArrayType<Type>::size;
|
constexpr size_t n = StdArrayType<Type>::size;
|
||||||
const auto fct = [&]<std::size_t... _i>(std::index_sequence<_i...>) {
|
const auto fct = [&]<std::size_t... _i>(std::index_sequence<_i...>) {
|
||||||
return to_std_array_t<Type>({to_std_array(
|
return to_std_array_t<Type>({to_std_array(
|
||||||
std::forward<typename StdArrayType<Type>::ValueType>(_t[_i]))...});
|
std::forward<typename StdArrayType<Type>::ValueType>(_t[_i])
|
||||||
|
)...});
|
||||||
};
|
};
|
||||||
return fct(std::make_index_sequence<n>());
|
return fct(std::make_index_sequence<n>());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,10 +16,11 @@ namespace rfl::internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms the field name from snake case to camel case.
|
/// Transforms the field name from snake case to camel case.
|
||||||
template <internal::StringLiteral _name,
|
template <
|
||||||
bool _capitalize,
|
internal::StringLiteral _name,
|
||||||
size_t _i = 0,
|
bool _capitalize,
|
||||||
char... chars>
|
size_t _i = 0,
|
||||||
|
char... chars>
|
||||||
consteval auto transform_snake_case() {
|
consteval auto transform_snake_case() {
|
||||||
if constexpr (_i == _name.arr_.size()) {
|
if constexpr (_i == _name.arr_.size()) {
|
||||||
return StringLiteral<sizeof...(chars) + 1>(chars...);
|
return StringLiteral<sizeof...(chars) + 1>(chars...);
|
||||||
|
@ -28,11 +29,11 @@ namespace rfl::internal {
|
||||||
} else if constexpr (_name.arr_[_i] == '\0') {
|
} else if constexpr (_name.arr_[_i] == '\0') {
|
||||||
return transform_snake_case<_name, false, _name.arr_.size(), chars...>();
|
return transform_snake_case<_name, false, _name.arr_.size(), chars...>();
|
||||||
} else if constexpr (_capitalize) {
|
} else if constexpr (_capitalize) {
|
||||||
return transform_snake_case<_name, false, _i + 1, chars...,
|
return transform_snake_case<
|
||||||
to_upper<_name.arr_[_i]>()>();
|
_name, false, _i + 1, chars..., to_upper<_name.arr_[_i]>()>();
|
||||||
} else {
|
} else {
|
||||||
return transform_snake_case<_name, false, _i + 1, chars...,
|
return transform_snake_case<
|
||||||
_name.arr_[_i]>();
|
_name, false, _i + 1, chars..., _name.arr_[_i]>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace rfl::internal
|
} // namespace rfl::internal
|
||||||
|
|
|
@ -28,14 +28,17 @@ namespace rfl {
|
||||||
constexpr auto n_skip = std::tuple_size_v<
|
constexpr auto n_skip = std::tuple_size_v<
|
||||||
std::remove_cvref_t<flattened_ptr_tuple_t<typename Type::Type>>>;
|
std::remove_cvref_t<flattened_ptr_tuple_t<typename Type::Type>>>;
|
||||||
return wrap_in_fields<FieldNames, j + n_skip>(
|
return wrap_in_fields<FieldNames, j + n_skip>(
|
||||||
std::move(_tuple), std::move(_fields)..., std::move(value));
|
std::move(_tuple), std::move(_fields)..., std::move(value)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const auto name_literal = FieldNames::template name_of<j>();
|
const auto name_literal = FieldNames::template name_of<j>();
|
||||||
auto new_field = rfl::make_field<
|
auto new_field = rfl::make_field<
|
||||||
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
||||||
std::move(value));
|
std::move(value)
|
||||||
|
);
|
||||||
return wrap_in_fields<FieldNames, j + 1>(
|
return wrap_in_fields<FieldNames, j + 1>(
|
||||||
std::move(_tuple), std::move(_fields)..., std::move(new_field));
|
std::move(_tuple), std::move(_fields)..., std::move(new_field)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace rfl {
|
||||||
std::ifstream input(_fname, std::ios::binary);
|
std::ifstream input(_fname, std::ios::binary);
|
||||||
if (input.is_open()) {
|
if (input.is_open()) {
|
||||||
std::istreambuf_iterator<char> begin(input), end;
|
std::istreambuf_iterator<char> begin(input), end;
|
||||||
const auto bytes = std::vector<char>(begin, end);
|
const auto bytes = std::vector<char>(begin, end);
|
||||||
input.close();
|
input.close();
|
||||||
return bytes;
|
return bytes;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,13 +13,16 @@ namespace rfl {
|
||||||
inline Result<std::string> load_string(const std::string& _fname) {
|
inline Result<std::string> load_string(const std::string& _fname) {
|
||||||
std::ifstream infile(_fname);
|
std::ifstream infile(_fname);
|
||||||
if (infile.is_open()) {
|
if (infile.is_open()) {
|
||||||
auto r = std::string(std::istreambuf_iterator<char>(infile),
|
auto r = std::string(
|
||||||
std::istreambuf_iterator<char>());
|
std::istreambuf_iterator<char>(infile),
|
||||||
|
std::istreambuf_iterator<char>()
|
||||||
|
);
|
||||||
infile.close();
|
infile.close();
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
return Error("Unable to open file '" + _fname +
|
return Error(
|
||||||
"' or file could not be found.");
|
"Unable to open file '" + _fname + "' or file could not be found."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,11 @@ namespace rfl {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
template <class T, class WriteFunction>
|
template <class T, class WriteFunction>
|
||||||
Result<Nothing> save_bytes(const std::string& _fname,
|
Result<Nothing> save_bytes(
|
||||||
const T& _obj,
|
const std::string& _fname,
|
||||||
const WriteFunction& _write) {
|
const T& _obj,
|
||||||
|
const WriteFunction& _write
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
std::ofstream output(_fname, std::ios::out | std::ios::binary);
|
std::ofstream output(_fname, std::ios::out | std::ios::binary);
|
||||||
_write(_obj, output);
|
_write(_obj, output);
|
||||||
|
|
|
@ -11,9 +11,11 @@ namespace rfl {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
template <class T, class WriteFunction>
|
template <class T, class WriteFunction>
|
||||||
Result<Nothing> save_string(const std::string& _fname,
|
Result<Nothing> save_string(
|
||||||
const T& _obj,
|
const std::string& _fname,
|
||||||
const WriteFunction& _write) {
|
const T& _obj,
|
||||||
|
const WriteFunction& _write
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
std::ofstream outfile;
|
std::ofstream outfile;
|
||||||
outfile.open(_fname);
|
outfile.open(_fname);
|
||||||
|
|
|
@ -47,8 +47,9 @@ namespace rfl {
|
||||||
(requires(InputVarType var) { T::from_json_obj(var); });
|
(requires(InputVarType var) { T::from_json_obj(var); });
|
||||||
|
|
||||||
rfl::Result<InputVarType> get_field(
|
rfl::Result<InputVarType> get_field(
|
||||||
const std::string& _name,
|
const std::string& _name,
|
||||||
const InputObjectType _obj) const noexcept {
|
const InputObjectType _obj
|
||||||
|
) const noexcept {
|
||||||
const auto var = InputVarType(yyjson_obj_get(_obj.val_, _name.c_str()));
|
const auto var = InputVarType(yyjson_obj_get(_obj.val_, _name.c_str()));
|
||||||
if (!var.val_) {
|
if (!var.val_) {
|
||||||
return rfl::Error("Object contains no field named '" + _name + "'.");
|
return rfl::Error("Object contains no field named '" + _name + "'.");
|
||||||
|
@ -62,9 +63,10 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(
|
||||||
const ArrayReader& _array_reader,
|
const ArrayReader& _array_reader,
|
||||||
const InputArrayType& _arr) const noexcept {
|
const InputArrayType& _arr
|
||||||
yyjson_val* val;
|
) const noexcept {
|
||||||
|
yyjson_val* val;
|
||||||
yyjson_arr_iter iter;
|
yyjson_arr_iter iter;
|
||||||
yyjson_arr_iter_init(_arr.val_, &iter);
|
yyjson_arr_iter_init(_arr.val_, &iter);
|
||||||
while ((val = yyjson_arr_iter_next(&iter))) {
|
while ((val = yyjson_arr_iter_next(&iter))) {
|
||||||
|
@ -76,8 +78,9 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error> read_object(
|
||||||
const ObjectReader& _object_reader,
|
const ObjectReader& _object_reader,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
yyjson_obj_iter iter;
|
yyjson_obj_iter iter;
|
||||||
yyjson_obj_iter_init(_obj.val_, &iter);
|
yyjson_obj_iter_init(_obj.val_, &iter);
|
||||||
yyjson_val* key;
|
yyjson_val* key;
|
||||||
|
@ -119,16 +122,16 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(
|
rfl::Result<InputArrayType> to_array(const InputVarType _var
|
||||||
const InputVarType _var) const noexcept {
|
) const noexcept {
|
||||||
if (!yyjson_is_arr(_var.val_)) {
|
if (!yyjson_is_arr(_var.val_)) {
|
||||||
return rfl::Error("Could not cast to array!");
|
return rfl::Error("Could not cast to array!");
|
||||||
}
|
}
|
||||||
return InputArrayType(_var.val_);
|
return InputArrayType(_var.val_);
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(
|
rfl::Result<InputObjectType> to_object(const InputVarType _var
|
||||||
const InputVarType _var) const noexcept {
|
) const noexcept {
|
||||||
if (!yyjson_is_obj(_var.val_)) {
|
if (!yyjson_is_obj(_var.val_)) {
|
||||||
return rfl::Error("Could not cast to object!");
|
return rfl::Error("Could not cast to object!");
|
||||||
}
|
}
|
||||||
|
@ -136,8 +139,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(
|
rfl::Result<T> use_custom_constructor(const InputVarType _var
|
||||||
const InputVarType _var) const noexcept {
|
) const noexcept {
|
||||||
try {
|
try {
|
||||||
return T::from_json_obj(_var);
|
return T::from_json_obj(_var);
|
||||||
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
||||||
|
|
|
@ -73,8 +73,9 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto arr = yyjson_mut_arr(doc_);
|
const auto arr = yyjson_mut_arr(doc_);
|
||||||
yyjson_mut_arr_add_val(_parent->val_, arr);
|
yyjson_mut_arr_add_val(_parent->val_, arr);
|
||||||
return OutputArrayType(arr);
|
return OutputArrayType(arr);
|
||||||
|
@ -82,17 +83,20 @@ namespace rfl {
|
||||||
|
|
||||||
OutputArrayType add_array_to_object(
|
OutputArrayType add_array_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto arr = yyjson_mut_arr(doc_);
|
const auto arr = yyjson_mut_arr(doc_);
|
||||||
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
|
yyjson_mut_obj_add(
|
||||||
arr);
|
_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), arr
|
||||||
|
);
|
||||||
return OutputArrayType(arr);
|
return OutputArrayType(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto obj = yyjson_mut_obj(doc_);
|
const auto obj = yyjson_mut_obj(doc_);
|
||||||
yyjson_mut_arr_add_val(_parent->val_, obj);
|
yyjson_mut_arr_add_val(_parent->val_, obj);
|
||||||
return OutputObjectType(obj);
|
return OutputObjectType(obj);
|
||||||
|
@ -100,11 +104,13 @@ namespace rfl {
|
||||||
|
|
||||||
OutputObjectType add_object_to_object(
|
OutputObjectType add_object_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto obj = yyjson_mut_obj(doc_);
|
const auto obj = yyjson_mut_obj(doc_);
|
||||||
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
|
yyjson_mut_obj_add(
|
||||||
obj);
|
_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), obj
|
||||||
|
);
|
||||||
return OutputObjectType(obj);
|
return OutputObjectType(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,11 +125,13 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_object(
|
OutputVarType add_value_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const T& _var,
|
const T& _var,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto val = from_basic_type(_var);
|
const auto val = from_basic_type(_var);
|
||||||
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
|
yyjson_mut_obj_add(
|
||||||
val.val_);
|
_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), val.val_
|
||||||
|
);
|
||||||
return OutputVarType(val);
|
return OutputVarType(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,10 +143,12 @@ namespace rfl {
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
const auto null = yyjson_mut_null(doc_);
|
const auto null = yyjson_mut_null(doc_);
|
||||||
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
|
yyjson_mut_obj_add(
|
||||||
null);
|
_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), null
|
||||||
|
);
|
||||||
return OutputVarType(null);
|
return OutputVarType(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,14 +164,15 @@ namespace rfl {
|
||||||
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
|
||||||
return OutputVarType(yyjson_mut_bool(doc_, _var));
|
return OutputVarType(yyjson_mut_bool(doc_, _var));
|
||||||
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
|
||||||
return OutputVarType(
|
return OutputVarType(yyjson_mut_real(doc_, static_cast<double>(_var))
|
||||||
yyjson_mut_real(doc_, static_cast<double>(_var)));
|
);
|
||||||
} else if constexpr (std::is_unsigned<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_unsigned<std::remove_cvref_t<T>>()) {
|
||||||
return OutputVarType(
|
return OutputVarType(
|
||||||
yyjson_mut_uint(doc_, static_cast<uint64_t>(_var)));
|
yyjson_mut_uint(doc_, static_cast<uint64_t>(_var))
|
||||||
|
);
|
||||||
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
|
||||||
return OutputVarType(
|
return OutputVarType(yyjson_mut_int(doc_, static_cast<int64_t>(_var))
|
||||||
yyjson_mut_int(doc_, static_cast<int64_t>(_var)));
|
);
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ namespace rfl {
|
||||||
|
|
||||||
/// Parses an object from JSON using reflection.
|
/// Parses an object from JSON using reflection.
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<internal::wrap_in_rfl_array_t<T>> read(
|
Result<internal::wrap_in_rfl_array_t<T>> read(const std::string& _json_str
|
||||||
const std::string& _json_str) {
|
) {
|
||||||
yyjson_doc* doc = yyjson_read(_json_str.c_str(), _json_str.size(), 0);
|
yyjson_doc* doc = yyjson_read(_json_str.c_str(), _json_str.size(), 0);
|
||||||
if (!doc) { return Error("Could not parse document"); }
|
if (!doc) { return Error("Could not parse document"); }
|
||||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||||
const auto r = Reader();
|
const auto r = Reader();
|
||||||
auto res = Parser<T, Processors<Ps...>>::read(r, InputVarType(root));
|
auto res = Parser<T, Processors<Ps...>>::read(r, InputVarType(root));
|
||||||
yyjson_doc_free(doc);
|
yyjson_doc_free(doc);
|
||||||
return res;
|
return res;
|
||||||
|
@ -39,8 +39,10 @@ namespace rfl {
|
||||||
/// Parses an object from a stringstream.
|
/// Parses an object from a stringstream.
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(std::istream& _stream) {
|
auto read(std::istream& _stream) {
|
||||||
const auto json_str = std::string(std::istreambuf_iterator<char>(_stream),
|
const auto json_str = std::string(
|
||||||
std::istreambuf_iterator<char>());
|
std::istreambuf_iterator<char>(_stream),
|
||||||
|
std::istreambuf_iterator<char>()
|
||||||
|
);
|
||||||
return read<T, Ps...>(json_str);
|
return read<T, Ps...>(json_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,13 @@ namespace rfl {
|
||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
Result<Nothing> save(const std::string& _fname,
|
Result<Nothing> save(
|
||||||
const auto& _obj,
|
const std::string& _fname,
|
||||||
const yyjson_write_flag _flag = 0) {
|
const auto& _obj,
|
||||||
const auto write_func = [_flag](const auto& _obj,
|
const yyjson_write_flag _flag = 0
|
||||||
auto& _stream) -> auto& {
|
) {
|
||||||
|
const auto write_func =
|
||||||
|
[_flag](const auto& _obj, auto& _stream) -> auto& {
|
||||||
return write<Ps...>(_obj, _stream, _flag);
|
return write<Ps...>(_obj, _stream, _flag);
|
||||||
};
|
};
|
||||||
return rfl::io::save_string(_fname, _obj, write_func);
|
return rfl::io::save_string(_fname, _obj, write_func);
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace rfl::json::schema {
|
||||||
template <class T>
|
template <class T>
|
||||||
struct JSONSchema {
|
struct JSONSchema {
|
||||||
Rename<"$schema", Literal<"https://json-schema.org/draft/2020-12/schema">>
|
Rename<"$schema", Literal<"https://json-schema.org/draft/2020-12/schema">>
|
||||||
schema;
|
schema;
|
||||||
Flatten<T> root;
|
Flatten<T> root;
|
||||||
std::map<std::string, Type> definitions;
|
std::map<std::string, Type> definitions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,21 +16,21 @@ namespace rfl::json::schema {
|
||||||
struct Type {
|
struct Type {
|
||||||
struct Boolean {
|
struct Boolean {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
Literal<"boolean"> type;
|
Literal<"boolean"> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Integer {
|
struct Integer {
|
||||||
Literal<"integer"> type;
|
Literal<"integer"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Number {
|
struct Number {
|
||||||
Literal<"number"> type;
|
Literal<"number"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct String {
|
struct String {
|
||||||
Literal<"string"> type;
|
Literal<"string"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,119 +38,120 @@ namespace rfl::json::schema {
|
||||||
|
|
||||||
struct AllOf {
|
struct AllOf {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::vector<Type> allOf;
|
std::vector<Type> allOf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnyOf {
|
struct AnyOf {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::vector<Type> anyOf;
|
std::vector<Type> anyOf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExclusiveMaximum {
|
struct ExclusiveMaximum {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::variant<double, int> exclusiveMaximum;
|
std::variant<double, int> exclusiveMaximum;
|
||||||
std::string type;
|
std::string type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExclusiveMinimum {
|
struct ExclusiveMinimum {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::variant<double, int> exclusiveMinimum;
|
std::variant<double, int> exclusiveMinimum;
|
||||||
std::string type;
|
std::string type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FixedSizeTypedArray {
|
struct FixedSizeTypedArray {
|
||||||
Literal<"array"> type;
|
Literal<"array"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
rfl::Ref<Type> items;
|
rfl::Ref<Type> items;
|
||||||
size_t minContains;
|
size_t minContains;
|
||||||
size_t maxContains;
|
size_t maxContains;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Maximum {
|
struct Maximum {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::variant<double, int> maximum;
|
std::variant<double, int> maximum;
|
||||||
std::string type;
|
std::string type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Minimum {
|
struct Minimum {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::variant<double, int> minimum;
|
std::variant<double, int> minimum;
|
||||||
std::string type;
|
std::string type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Null {
|
struct Null {
|
||||||
Literal<"null"> type;
|
Literal<"null"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Object {
|
struct Object {
|
||||||
Literal<"object"> type;
|
Literal<"object"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::map<std::string, Type> properties;
|
std::map<std::string, Type> properties;
|
||||||
std::vector<std::string> required;
|
std::vector<std::string> required;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OneOf {
|
struct OneOf {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::vector<Type> oneOf;
|
std::vector<Type> oneOf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Reference {
|
struct Reference {
|
||||||
Rename<"$ref", std::optional<std::string>> ref;
|
Rename<"$ref", std::optional<std::string>> ref;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Regex {
|
struct Regex {
|
||||||
Literal<"string"> type;
|
Literal<"string"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringEnum {
|
struct StringEnum {
|
||||||
Literal<"string"> type;
|
Literal<"string"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
rfl::Rename<"enum", std::vector<std::string>> values;
|
rfl::Rename<"enum", std::vector<std::string>> values;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringMap {
|
struct StringMap {
|
||||||
Literal<"object"> type;
|
Literal<"object"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
rfl::Ref<Type> additionalProperties;
|
rfl::Ref<Type> additionalProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tuple {
|
struct Tuple {
|
||||||
Literal<"array"> type;
|
Literal<"array"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
std::vector<Type> prefixItems;
|
std::vector<Type> prefixItems;
|
||||||
bool items = false;
|
bool items = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypedArray {
|
struct TypedArray {
|
||||||
Literal<"array"> type;
|
Literal<"array"> type;
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
rfl::Ref<Type> items;
|
rfl::Ref<Type> items;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ReflectionType = std::variant<AllOf,
|
using ReflectionType = std::variant<
|
||||||
AnyOf,
|
AllOf,
|
||||||
Boolean,
|
AnyOf,
|
||||||
ExclusiveMaximum,
|
Boolean,
|
||||||
ExclusiveMinimum,
|
ExclusiveMaximum,
|
||||||
FixedSizeTypedArray,
|
ExclusiveMinimum,
|
||||||
Integer,
|
FixedSizeTypedArray,
|
||||||
Maximum,
|
Integer,
|
||||||
Minimum,
|
Maximum,
|
||||||
Number,
|
Minimum,
|
||||||
Null,
|
Number,
|
||||||
Object,
|
Null,
|
||||||
OneOf,
|
Object,
|
||||||
Reference,
|
OneOf,
|
||||||
Regex,
|
Reference,
|
||||||
String,
|
Regex,
|
||||||
StringEnum,
|
String,
|
||||||
StringMap,
|
StringEnum,
|
||||||
Tuple,
|
StringMap,
|
||||||
TypedArray>;
|
Tuple,
|
||||||
|
TypedArray>;
|
||||||
|
|
||||||
const auto& reflection() const { return value; }
|
const auto& reflection() const { return value; }
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
namespace rfl::json {
|
namespace rfl::json {
|
||||||
|
|
||||||
inline schema::Type type_to_json_schema_type(
|
inline schema::Type type_to_json_schema_type(
|
||||||
const parsing::schema::Type& _type);
|
const parsing::schema::Type& _type
|
||||||
|
);
|
||||||
|
|
||||||
inline bool is_optional(const parsing::schema::Type& _t) {
|
inline bool is_optional(const parsing::schema::Type& _t) {
|
||||||
const auto handle = [](const auto& _v) -> bool {
|
const auto handle = [](const auto& _v) -> bool {
|
||||||
|
@ -31,8 +32,8 @@ namespace rfl::json {
|
||||||
return std::visit(handle, _t.variant_);
|
return std::visit(handle, _t.variant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string numeric_type_to_string(
|
inline std::string numeric_type_to_string(const parsing::schema::Type& _type
|
||||||
const parsing::schema::Type& _type) {
|
) {
|
||||||
const auto handle_variant = [](const auto& _t) -> std::string {
|
const auto handle_variant = [](const auto& _t) -> std::string {
|
||||||
using T = std::remove_cvref_t<decltype(_t)>;
|
using T = std::remove_cvref_t<decltype(_t)>;
|
||||||
using Type = parsing::schema::Type;
|
using Type = parsing::schema::Type;
|
||||||
|
@ -50,8 +51,9 @@ namespace rfl::json {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline schema::Type handle_validation_type(
|
inline schema::Type handle_validation_type(
|
||||||
const parsing::schema::Type& _type,
|
const parsing::schema::Type& _type,
|
||||||
const parsing::schema::ValidationType& _validation_type) {
|
const parsing::schema::ValidationType& _validation_type
|
||||||
|
) {
|
||||||
const auto handle_variant = [&](const auto& _v) -> schema::Type {
|
const auto handle_variant = [&](const auto& _v) -> schema::Type {
|
||||||
using T = std::remove_cvref_t<decltype(_v)>;
|
using T = std::remove_cvref_t<decltype(_v)>;
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
|
@ -77,55 +79,84 @@ namespace rfl::json {
|
||||||
return schema::Type {.value = schema::Type::OneOf {.oneOf = one_of}};
|
return schema::Type {.value = schema::Type::OneOf {.oneOf = one_of}};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::Regex>()) {
|
} else if constexpr (std::is_same<T, ValidationType::Regex>()) {
|
||||||
return schema::Type {.value =
|
return schema::Type {
|
||||||
schema::Type::Regex {.pattern = _v.pattern_}};
|
.value = schema::Type::Regex {.pattern = _v.pattern_}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::Size>()) {
|
} else if constexpr (std::is_same<T, ValidationType::Size>()) {
|
||||||
return type_to_json_schema_type(_type);
|
return type_to_json_schema_type(_type);
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T,
|
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMaximum>(
|
||||||
ValidationType::ExclusiveMaximum>()) {
|
)) {
|
||||||
return schema::Type {.value = schema::Type::ExclusiveMaximum {
|
return schema::Type {
|
||||||
.exclusiveMaximum = _v.value_,
|
.value =
|
||||||
.type = numeric_type_to_string(_type)}};
|
schema::Type::ExclusiveMaximum {
|
||||||
|
.exclusiveMaximum = _v.value_,
|
||||||
|
.type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T,
|
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMinimum>(
|
||||||
ValidationType::ExclusiveMinimum>()) {
|
)) {
|
||||||
return schema::Type {.value = schema::Type::ExclusiveMinimum {
|
return schema::Type {
|
||||||
.exclusiveMinimum = _v.value_,
|
.value =
|
||||||
.type = numeric_type_to_string(_type)}};
|
schema::Type::ExclusiveMinimum {
|
||||||
|
.exclusiveMinimum = _v.value_,
|
||||||
|
.type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::Maximum>()) {
|
} else if constexpr (std::is_same<T, ValidationType::Maximum>()) {
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::Maximum {
|
.value =
|
||||||
.maximum = _v.value_, .type = numeric_type_to_string(_type)}};
|
schema::Type::Maximum {
|
||||||
|
.maximum = _v.value_, .type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::Minimum>()) {
|
} else if constexpr (std::is_same<T, ValidationType::Minimum>()) {
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::Minimum {
|
.value =
|
||||||
.minimum = _v.value_, .type = numeric_type_to_string(_type)}};
|
schema::Type::Minimum {
|
||||||
|
.minimum = _v.value_, .type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::EqualTo>()) {
|
} else if constexpr (std::is_same<T, ValidationType::EqualTo>()) {
|
||||||
const auto maximum = schema::Type {
|
const auto maximum = schema::Type {
|
||||||
.value = schema::Type::Maximum {
|
.value =
|
||||||
.maximum = _v.value_, .type = numeric_type_to_string(_type)}};
|
schema::Type::Maximum {
|
||||||
|
.maximum = _v.value_, .type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
const auto minimum = schema::Type {
|
const auto minimum = schema::Type {
|
||||||
.value = schema::Type::Minimum {
|
.value =
|
||||||
.minimum = _v.value_, .type = numeric_type_to_string(_type)}};
|
schema::Type::Minimum {
|
||||||
|
.minimum = _v.value_, .type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::AllOf {.allOf = {maximum, minimum}}};
|
.value = schema::Type::AllOf {.allOf = {maximum, minimum}}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, ValidationType::NotEqualTo>()) {
|
} else if constexpr (std::is_same<T, ValidationType::NotEqualTo>()) {
|
||||||
const auto excl_maximum =
|
const auto excl_maximum = schema::Type {
|
||||||
schema::Type {.value = schema::Type::ExclusiveMaximum {
|
.value =
|
||||||
.exclusiveMaximum = _v.value_,
|
schema::Type::ExclusiveMaximum {
|
||||||
.type = numeric_type_to_string(_type)}};
|
.exclusiveMaximum = _v.value_,
|
||||||
const auto excl_minimum =
|
.type = numeric_type_to_string(_type)
|
||||||
schema::Type {.value = schema::Type::ExclusiveMinimum {
|
}
|
||||||
.exclusiveMinimum = _v.value_,
|
};
|
||||||
.type = numeric_type_to_string(_type)}};
|
const auto excl_minimum = schema::Type {
|
||||||
return schema::Type {.value = schema::Type::AnyOf {
|
.value =
|
||||||
.anyOf = {excl_maximum, excl_minimum}}};
|
schema::Type::ExclusiveMinimum {
|
||||||
|
.exclusiveMinimum = _v.value_,
|
||||||
|
.type = numeric_type_to_string(_type)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return schema::Type {
|
||||||
|
.value = schema::Type::AnyOf {.anyOf = {excl_maximum, excl_minimum}}
|
||||||
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Not all cases were covered.");
|
static_assert(rfl::always_false_v<T>, "Not all cases were covered.");
|
||||||
|
@ -136,7 +167,8 @@ namespace rfl::json {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline schema::Type type_to_json_schema_type(
|
inline schema::Type type_to_json_schema_type(
|
||||||
const parsing::schema::Type& _type) {
|
const parsing::schema::Type& _type
|
||||||
|
) {
|
||||||
const auto handle_variant = [](const auto& _t) -> schema::Type {
|
const auto handle_variant = [](const auto& _t) -> schema::Type {
|
||||||
using T = std::remove_cvref_t<decltype(_t)>;
|
using T = std::remove_cvref_t<decltype(_t)>;
|
||||||
using Type = parsing::schema::Type;
|
using Type = parsing::schema::Type;
|
||||||
|
@ -165,7 +197,7 @@ namespace rfl::json {
|
||||||
return schema::Type {.value = schema::Type::AnyOf {.anyOf = any_of}};
|
return schema::Type {.value = schema::Type::AnyOf {.anyOf = any_of}};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Description>()) {
|
} else if constexpr (std::is_same<T, Type::Description>()) {
|
||||||
auto res = type_to_json_schema_type(*_t.type_);
|
auto res = type_to_json_schema_type(*_t.type_);
|
||||||
const auto update_prediction = [&](auto _v) -> schema::Type {
|
const auto update_prediction = [&](auto _v) -> schema::Type {
|
||||||
_v.description = _t.description_;
|
_v.description = _t.description_;
|
||||||
return schema::Type {_v};
|
return schema::Type {_v};
|
||||||
|
@ -173,15 +205,20 @@ namespace rfl::json {
|
||||||
return std::visit(update_prediction, res.value);
|
return std::visit(update_prediction, res.value);
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::FixedSizeTypedArray>()) {
|
} else if constexpr (std::is_same<T, Type::FixedSizeTypedArray>()) {
|
||||||
return schema::Type {.value = schema::Type::FixedSizeTypedArray {
|
return schema::Type {
|
||||||
.items = Ref<schema::Type>::make(
|
.value =
|
||||||
type_to_json_schema_type(*_t.type_)),
|
schema::Type::FixedSizeTypedArray {
|
||||||
.minContains = _t.size_,
|
.items = Ref<schema::Type>::make(
|
||||||
.maxContains = _t.size_}};
|
type_to_json_schema_type(*_t.type_)
|
||||||
|
), .minContains = _t.size_,
|
||||||
|
.maxContains = _t.size_
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Literal>()) {
|
} else if constexpr (std::is_same<T, Type::Literal>()) {
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::StringEnum {.values = _t.values_}};
|
.value = schema::Type::StringEnum {.values = _t.values_}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Object>()) {
|
} else if constexpr (std::is_same<T, Type::Object>()) {
|
||||||
auto properties = std::map<std::string, schema::Type>();
|
auto properties = std::map<std::string, schema::Type>();
|
||||||
|
@ -190,38 +227,57 @@ namespace rfl::json {
|
||||||
properties[k] = type_to_json_schema_type(v);
|
properties[k] = type_to_json_schema_type(v);
|
||||||
if (!is_optional(v)) { required.push_back(k); }
|
if (!is_optional(v)) { required.push_back(k); }
|
||||||
}
|
}
|
||||||
return schema::Type {.value =
|
return schema::Type {
|
||||||
schema::Type::Object {.properties = properties,
|
.value =
|
||||||
.required = required}};
|
schema::Type::Object {
|
||||||
|
.properties = properties, .required = required
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Optional>()) {
|
} else if constexpr (std::is_same<T, Type::Optional>()) {
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::AnyOf {
|
.value =
|
||||||
.anyOf = {type_to_json_schema_type(*_t.type_),
|
schema::Type::AnyOf {
|
||||||
schema::Type {schema::Type::Null {}}}}};
|
.anyOf =
|
||||||
|
{type_to_json_schema_type(*_t.type_),
|
||||||
|
schema::Type {schema::Type::Null {}}}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Reference>()) {
|
} else if constexpr (std::is_same<T, Type::Reference>()) {
|
||||||
return schema::Type {.value = schema::Type::Reference {
|
return schema::Type {
|
||||||
.ref = "#/definitions/" + _t.name_}};
|
.value =
|
||||||
|
schema::Type::Reference {.ref = "#/definitions/" + _t.name_}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::StringMap>()) {
|
} else if constexpr (std::is_same<T, Type::StringMap>()) {
|
||||||
return schema::Type {
|
return schema::Type {
|
||||||
.value = schema::Type::StringMap {
|
.value =
|
||||||
.additionalProperties = Ref<schema::Type>::make(
|
schema::Type::StringMap {
|
||||||
type_to_json_schema_type(*_t.value_type_))}};
|
.additionalProperties = Ref<schema::Type>::make(
|
||||||
|
type_to_json_schema_type(*_t.value_type_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Tuple>()) {
|
} else if constexpr (std::is_same<T, Type::Tuple>()) {
|
||||||
auto items = std::vector<schema::Type>();
|
auto items = std::vector<schema::Type>();
|
||||||
for (const auto& t : _t.types_) {
|
for (const auto& t : _t.types_) {
|
||||||
items.emplace_back(type_to_json_schema_type(t));
|
items.emplace_back(type_to_json_schema_type(t));
|
||||||
}
|
}
|
||||||
return schema::Type {.value =
|
return schema::Type {
|
||||||
schema::Type::Tuple {.prefixItems = items}};
|
.value = schema::Type::Tuple {.prefixItems = items}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::TypedArray>()) {
|
} else if constexpr (std::is_same<T, Type::TypedArray>()) {
|
||||||
return schema::Type {.value = schema::Type::TypedArray {
|
return schema::Type {
|
||||||
.items = Ref<schema::Type>::make(
|
.value =
|
||||||
type_to_json_schema_type(*_t.type_))}};
|
schema::Type::TypedArray {
|
||||||
|
.items = Ref<schema::Type>::make(
|
||||||
|
type_to_json_schema_type(*_t.type_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} else if constexpr (std::is_same<T, Type::Validated>()) {
|
} else if constexpr (std::is_same<T, Type::Validated>()) {
|
||||||
return handle_validation_type(*_t.type_, _t.validation_);
|
return handle_validation_type(*_t.type_, _t.validation_);
|
||||||
|
@ -255,10 +311,11 @@ namespace rfl::json {
|
||||||
typename TypeHelper<schema::Type::ReflectionType>::JSONSchemaType;
|
typename TypeHelper<schema::Type::ReflectionType>::JSONSchemaType;
|
||||||
const auto to_schema = [&](auto&& _root) -> JSONSchemaType {
|
const auto to_schema = [&](auto&& _root) -> JSONSchemaType {
|
||||||
using U = std::decay_t<decltype(_root)>;
|
using U = std::decay_t<decltype(_root)>;
|
||||||
return schema::JSONSchema<U> {.root = std::move(_root),
|
return schema::JSONSchema<U> {
|
||||||
.definitions = definitions};
|
.root = std::move(_root), .definitions = definitions
|
||||||
|
};
|
||||||
};
|
};
|
||||||
auto root = type_to_json_schema_type(internal_schema.root_);
|
auto root = type_to_json_schema_type(internal_schema.root_);
|
||||||
const auto json_schema = std::visit(to_schema, std::move(root.value));
|
const auto json_schema = std::visit(to_schema, std::move(root.value));
|
||||||
return write(json_schema, _flag);
|
return write(json_schema, _flag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,11 @@ namespace rfl {
|
||||||
using T = std::remove_cvref_t<decltype(_obj)>;
|
using T = std::remove_cvref_t<decltype(_obj)>;
|
||||||
using ParentType = parsing::Parent<Writer>;
|
using ParentType = parsing::Parent<Writer>;
|
||||||
auto w = Writer(yyjson_mut_doc_new(NULL));
|
auto w = Writer(yyjson_mut_doc_new(NULL));
|
||||||
Parser<T, Processors<Ps...>>::write(w, _obj,
|
Parser<T, Processors<Ps...>>::write(
|
||||||
typename ParentType::Root {});
|
w, _obj, typename ParentType::Root {}
|
||||||
|
);
|
||||||
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
|
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
|
||||||
const auto json_str = std::string(json_c_str);
|
const auto json_str = std::string(json_c_str);
|
||||||
free((void*)json_c_str);
|
free((void*)json_c_str);
|
||||||
yyjson_mut_doc_free(w.doc_);
|
yyjson_mut_doc_free(w.doc_);
|
||||||
return json_str;
|
return json_str;
|
||||||
|
@ -33,14 +34,17 @@ namespace rfl {
|
||||||
|
|
||||||
/// Writes a JSON into an ostream.
|
/// Writes a JSON into an ostream.
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
std::ostream& write(const auto& _obj,
|
std::ostream& write(
|
||||||
std::ostream& _stream,
|
const auto& _obj,
|
||||||
const yyjson_write_flag _flag = 0) {
|
std::ostream& _stream,
|
||||||
|
const yyjson_write_flag _flag = 0
|
||||||
|
) {
|
||||||
using T = std::remove_cvref_t<decltype(_obj)>;
|
using T = std::remove_cvref_t<decltype(_obj)>;
|
||||||
using ParentType = parsing::Parent<Writer>;
|
using ParentType = parsing::Parent<Writer>;
|
||||||
auto w = Writer(yyjson_mut_doc_new(NULL));
|
auto w = Writer(yyjson_mut_doc_new(NULL));
|
||||||
Parser<T, Processors<Ps...>>::write(w, _obj,
|
Parser<T, Processors<Ps...>>::write(
|
||||||
typename ParentType::Root {});
|
w, _obj, typename ParentType::Root {}
|
||||||
|
);
|
||||||
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
|
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
|
||||||
_stream << json_c_str;
|
_stream << json_c_str;
|
||||||
free((void*)json_c_str);
|
free((void*)json_c_str);
|
||||||
|
|
|
@ -12,7 +12,8 @@ namespace rfl {
|
||||||
template <class... FieldTypes>
|
template <class... FieldTypes>
|
||||||
inline auto make_named_tuple(FieldTypes&&... _args) {
|
inline auto make_named_tuple(FieldTypes&&... _args) {
|
||||||
return NamedTuple<std::remove_cvref_t<FieldTypes>...>(
|
return NamedTuple<std::remove_cvref_t<FieldTypes>...>(
|
||||||
std::forward<FieldTypes>(_args)...);
|
std::forward<FieldTypes>(_args)...
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience constructor that doesn't require you
|
/// Convenience constructor that doesn't require you
|
||||||
|
|
|
@ -12,34 +12,40 @@ namespace rfl {
|
||||||
/// Because of that, we require all of the fields and then set them to
|
/// Because of that, we require all of the fields and then set them to
|
||||||
/// nullptr, if necessary.
|
/// nullptr, if necessary.
|
||||||
template <class ProcessorsType, class... FieldTypes>
|
template <class ProcessorsType, class... FieldTypes>
|
||||||
requires AreReaderAndWriter<msgpack::Reader,
|
requires AreReaderAndWriter<
|
||||||
msgpack::Writer,
|
msgpack::Reader,
|
||||||
NamedTuple<FieldTypes...>>
|
msgpack::Writer,
|
||||||
struct Parser<msgpack::Reader,
|
NamedTuple<FieldTypes...>>
|
||||||
msgpack::Writer,
|
struct Parser<
|
||||||
NamedTuple<FieldTypes...>,
|
msgpack::Reader,
|
||||||
ProcessorsType>
|
msgpack::Writer,
|
||||||
: public NamedTupleParser<msgpack::Reader,
|
NamedTuple<FieldTypes...>,
|
||||||
msgpack::Writer,
|
ProcessorsType>
|
||||||
/*_ignore_empty_containers=*/false,
|
: public NamedTupleParser<
|
||||||
/*_all_required=*/true,
|
msgpack::Reader,
|
||||||
ProcessorsType,
|
msgpack::Writer,
|
||||||
FieldTypes...> {};
|
/*_ignore_empty_containers=*/false,
|
||||||
|
/*_all_required=*/true,
|
||||||
|
ProcessorsType,
|
||||||
|
FieldTypes...> {};
|
||||||
|
|
||||||
template <class ProcessorsType, class... Ts>
|
template <class ProcessorsType, class... Ts>
|
||||||
requires AreReaderAndWriter<msgpack::Reader,
|
requires AreReaderAndWriter<
|
||||||
msgpack::Writer,
|
msgpack::Reader,
|
||||||
std::tuple<Ts...>>
|
msgpack::Writer,
|
||||||
struct Parser<msgpack::Reader,
|
std::tuple<Ts...>>
|
||||||
msgpack::Writer,
|
struct Parser<
|
||||||
std::tuple<Ts...>,
|
msgpack::Reader,
|
||||||
ProcessorsType>
|
msgpack::Writer,
|
||||||
: public TupleParser<msgpack::Reader,
|
std::tuple<Ts...>,
|
||||||
msgpack::Writer,
|
ProcessorsType>
|
||||||
/*_ignore_empty_containers=*/false,
|
: public TupleParser<
|
||||||
/*_all_required=*/true,
|
msgpack::Reader,
|
||||||
ProcessorsType,
|
msgpack::Writer,
|
||||||
Ts...> {};
|
/*_ignore_empty_containers=*/false,
|
||||||
|
/*_all_required=*/true,
|
||||||
|
ProcessorsType,
|
||||||
|
Ts...> {};
|
||||||
|
|
||||||
} // namespace parsing
|
} // namespace parsing
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -33,13 +33,15 @@ namespace rfl {
|
||||||
(requires(InputVarType var) { T::from_msgpack_obj(var); });
|
(requires(InputVarType var) { T::from_msgpack_obj(var); });
|
||||||
|
|
||||||
rfl::Result<InputVarType> get_field(
|
rfl::Result<InputVarType> get_field(
|
||||||
const std::string& _name,
|
const std::string& _name,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
for (uint32_t i = 0; i < _obj.size; ++i) {
|
for (uint32_t i = 0; i < _obj.size; ++i) {
|
||||||
const auto& key = _obj.ptr[i].key;
|
const auto& key = _obj.ptr[i].key;
|
||||||
if (key.type != MSGPACK_OBJECT_STR) {
|
if (key.type != MSGPACK_OBJECT_STR) {
|
||||||
return Error("Key in element " + std::to_string(i) +
|
return Error(
|
||||||
" was not a string.");
|
"Key in element " + std::to_string(i) + " was not a string."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const auto current_name =
|
const auto current_name =
|
||||||
std::string_view(key.via.str.ptr, key.via.str.size);
|
std::string_view(key.via.str.ptr, key.via.str.size);
|
||||||
|
@ -79,22 +81,23 @@ namespace rfl {
|
||||||
return rfl::Error(
|
return rfl::Error(
|
||||||
"Could not cast to numeric value. The type must be integral, "
|
"Could not cast to numeric value. The type must be integral, "
|
||||||
"float "
|
"float "
|
||||||
"or double.");
|
"or double."
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(
|
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (_var.type != MSGPACK_OBJECT_ARRAY) {
|
if (_var.type != MSGPACK_OBJECT_ARRAY) {
|
||||||
return Error("Could not cast to an array.");
|
return Error("Could not cast to an array.");
|
||||||
}
|
}
|
||||||
return _var.via.array;
|
return _var.via.array;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(
|
rfl::Result<InputObjectType> to_object(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
if (_var.type != MSGPACK_OBJECT_MAP) {
|
if (_var.type != MSGPACK_OBJECT_MAP) {
|
||||||
return Error("Could not cast to a map.");
|
return Error("Could not cast to a map.");
|
||||||
}
|
}
|
||||||
|
@ -103,8 +106,9 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(
|
||||||
const ArrayReader& _array_reader,
|
const ArrayReader& _array_reader,
|
||||||
const InputArrayType& _arr) const noexcept {
|
const InputArrayType& _arr
|
||||||
|
) const noexcept {
|
||||||
for (uint32_t i = 0; i < _arr.size; ++i) {
|
for (uint32_t i = 0; i < _arr.size; ++i) {
|
||||||
const auto err = _array_reader.read(_arr.ptr[i]);
|
const auto err = _array_reader.read(_arr.ptr[i]);
|
||||||
if (err) { return err; }
|
if (err) { return err; }
|
||||||
|
@ -114,14 +118,16 @@ namespace rfl {
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error> read_object(
|
||||||
const ObjectReader& _object_reader,
|
const ObjectReader& _object_reader,
|
||||||
const InputObjectType& _obj) const noexcept {
|
const InputObjectType& _obj
|
||||||
|
) const noexcept {
|
||||||
for (uint32_t i = 0; i < _obj.size; ++i) {
|
for (uint32_t i = 0; i < _obj.size; ++i) {
|
||||||
const auto& key = _obj.ptr[i].key;
|
const auto& key = _obj.ptr[i].key;
|
||||||
const auto& val = _obj.ptr[i].val;
|
const auto& val = _obj.ptr[i].val;
|
||||||
if (key.type != MSGPACK_OBJECT_STR) {
|
if (key.type != MSGPACK_OBJECT_STR) {
|
||||||
return Error("Key in element " + std::to_string(i) +
|
return Error(
|
||||||
" was not a string.");
|
"Key in element " + std::to_string(i) + " was not a string."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const auto name = std::string_view(key.via.str.ptr, key.via.str.size);
|
const auto name = std::string_view(key.via.str.ptr, key.via.str.size);
|
||||||
_object_reader.read(name, val);
|
_object_reader.read(name, val);
|
||||||
|
@ -130,8 +136,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(
|
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
||||||
const InputVarType& _var) const noexcept {
|
) const noexcept {
|
||||||
try {
|
try {
|
||||||
return T::from_msgpack_obj(_var);
|
return T::from_msgpack_obj(_var);
|
||||||
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
} catch (std::exception& e) { return rfl::Error(e.what()); }
|
||||||
|
|
|
@ -54,46 +54,51 @@ namespace rfl::msgpack {
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_array(_size);
|
return new_array(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_object(
|
OutputArrayType add_array_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
msgpack_pack_str(pk_, _name.size());
|
msgpack_pack_str(pk_, _name.size());
|
||||||
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
||||||
return new_array(_size);
|
return new_array(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputArrayType* _parent) const noexcept {
|
OutputArrayType* _parent
|
||||||
|
) const noexcept {
|
||||||
return new_object(_size);
|
return new_object(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_object(
|
OutputObjectType add_object_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const size_t _size,
|
const size_t _size,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
msgpack_pack_str(pk_, _name.size());
|
msgpack_pack_str(pk_, _name.size());
|
||||||
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
||||||
return new_object(_size);
|
return new_object(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_array(const T& _var,
|
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
|
||||||
OutputArrayType* _parent) const noexcept {
|
const noexcept {
|
||||||
return new_value(_var);
|
return new_value(_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType add_value_to_object(
|
OutputVarType add_value_to_object(
|
||||||
const std::string_view& _name,
|
const std::string_view& _name,
|
||||||
const T& _var,
|
const T& _var,
|
||||||
OutputObjectType* _parent) const noexcept {
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
msgpack_pack_str(pk_, _name.size());
|
msgpack_pack_str(pk_, _name.size());
|
||||||
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
||||||
return new_value(_var);
|
return new_value(_var);
|
||||||
|
@ -104,8 +109,10 @@ namespace rfl::msgpack {
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputVarType add_null_to_object(const std::string_view& _name,
|
OutputVarType add_null_to_object(
|
||||||
OutputObjectType* _parent) const noexcept {
|
const std::string_view& _name,
|
||||||
|
OutputObjectType* _parent
|
||||||
|
) const noexcept {
|
||||||
msgpack_pack_str(pk_, _name.size());
|
msgpack_pack_str(pk_, _name.size());
|
||||||
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
msgpack_pack_str_body(pk_, _name.data(), _name.size());
|
||||||
msgpack_pack_nil(pk_);
|
msgpack_pack_nil(pk_);
|
||||||
|
|
|
@ -25,8 +25,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Parses an object from MSGPACK using reflection.
|
/// Parses an object from MSGPACK using reflection.
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
|
Result<internal::wrap_in_rfl_array_t<T>>
|
||||||
const size_t _size) {
|
read(const char* _bytes, const size_t _size) {
|
||||||
msgpack_zone mempool;
|
msgpack_zone mempool;
|
||||||
msgpack_zone_init(&mempool, 2048);
|
msgpack_zone_init(&mempool, 2048);
|
||||||
msgpack_object deserialized;
|
msgpack_object deserialized;
|
||||||
|
@ -46,7 +46,7 @@ namespace rfl {
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(std::istream& _stream) {
|
auto read(std::istream& _stream) {
|
||||||
std::istreambuf_iterator<char> begin(_stream), end;
|
std::istreambuf_iterator<char> begin(_stream), end;
|
||||||
auto bytes = std::vector<char>(begin, end);
|
auto bytes = std::vector<char>(begin, end);
|
||||||
return read<T, Ps...>(bytes.data(), bytes.size());
|
return read<T, Ps...>(bytes.data(), bytes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,10 @@ namespace rfl {
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class T>
|
template <internal::StringLiteral _name, class T>
|
||||||
struct remove_ptr<Field<_name, T>> {
|
struct remove_ptr<Field<_name, T>> {
|
||||||
using FieldType = Field<_name,
|
using FieldType = Field<
|
||||||
internal::wrap_in_rfl_array_t<
|
_name,
|
||||||
std::remove_cvref_t<std::remove_pointer_t<T>>>>;
|
internal::wrap_in_rfl_array_t<
|
||||||
|
std::remove_cvref_t<std::remove_pointer_t<T>>>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue