This commit is contained in:
Mars 2024-06-08 15:53:06 -04:00
parent bd402f57f5
commit 3ea546fe08
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
166 changed files with 18360 additions and 18199 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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()));
} }

View file

@ -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}};
} }

View file

@ -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);

View file

@ -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;

View file

@ -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;
} }

View file

@ -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>

View file

@ -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;

View file

@ -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;

View file

@ -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.

View file

@ -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));
} }

View file

@ -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)
);
} }
}; };

View file

@ -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() + "'."
);
} }
} }

View file

@ -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))
);
} }
}; };

View file

@ -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;
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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());
} }
}; };

View file

@ -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());
} }
}; };

View file

@ -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_);
} }

View file

@ -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() + "'."
);
} }
} }

View file

@ -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();
} }

View file

@ -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_; }

View file

@ -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)...)); )...));
} }
} }

View file

@ -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 {}};
} }
}; };

View file

@ -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()); }

View file

@ -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>()) {

View file

@ -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());
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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 {

View file

@ -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>()) {

View file

@ -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());
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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

View file

@ -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()); }

View file

@ -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};
} }

View file

@ -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());
} }

View file

@ -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();
} }

View file

@ -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);

View file

@ -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.

View file

@ -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);

View file

@ -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;

View file

@ -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);
} }

View file

@ -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

View file

@ -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)
);
} }
} }

View file

@ -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

View file

@ -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.

View file

@ -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...>>,

View file

@ -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.

View file

@ -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

View file

@ -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) {

View file

@ -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>();

View file

@ -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

View file

@ -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

View file

@ -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;
}; };

View file

@ -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>>());

View file

@ -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))
);
} }
} }

View file

@ -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()> {});

View file

@ -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;

View file

@ -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)))
);
} }
} }
} }

View file

@ -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))); ));
} }
} }

View file

@ -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))
);
} }
} }
} }

View file

@ -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()))
);
} }
} }

View file

@ -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>

View file

@ -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;
}; };

View file

@ -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;
}; };

View file

@ -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()> {});

View file

@ -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) {

View file

@ -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;

View file

@ -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));

View file

@ -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

View file

@ -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))
);
} }
} }
} }

View file

@ -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
);
} }
} }

View file

@ -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 {

View file

@ -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

View file

@ -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)
);
} }
} }
} }

View file

@ -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 {

View file

@ -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."
);
} }
} }

View file

@ -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);

View file

@ -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);

View file

@ -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()); }

View file

@ -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.");
} }

View file

@ -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);
} }

View file

@ -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);

View file

@ -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;
}; };

View file

@ -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; }

View file

@ -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);
} }

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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()); }

View file

@ -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_);

View file

@ -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());
} }

View file

@ -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