blwegh
This commit is contained in:
parent
f668a2eb4c
commit
50083503cf
|
@ -5,18 +5,20 @@ AlignConsecutiveDeclarations: true
|
||||||
AllowShortBlocksOnASingleLine: Always
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortCompoundRequirementOnASingleLine: true
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
AllowShortEnumsOnASingleLine: true
|
AllowShortEnumsOnASingleLine: true
|
||||||
AllowShortFunctionsOnASingleLine: true
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: true
|
||||||
BasedOnStyle: Chromium
|
BasedOnStyle: Chromium
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
FixNamespaceComments: false
|
FixNamespaceComments: false
|
||||||
IndentAccessModifiers: false
|
IndentAccessModifiers: false
|
||||||
IndentExternBlock: Indent
|
IndentExternBlock: Indent
|
||||||
IndentPPDirectives: BeforeHash
|
IndentWidth: 2
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: All
|
||||||
SkipMacroDefinitionBody: true
|
|
||||||
SpaceBeforeCpp11BracedList: true
|
SpaceBeforeCpp11BracedList: true
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# noinspection SpellCheckingInspection
|
||||||
Checks: >
|
Checks: >
|
||||||
*,
|
*,
|
||||||
-abseil-*,
|
-abseil-*,
|
||||||
|
|
6956
include/ctre.hpp
6956
include/ctre.hpp
File diff suppressed because it is too large
Load diff
|
@ -17,13 +17,11 @@ namespace rfl {
|
||||||
/// Adds the name of the struct as a new field.
|
/// Adds the name of the struct as a new field.
|
||||||
template <class StructType>
|
template <class StructType>
|
||||||
static auto process(auto&& _view) {
|
static auto process(auto&& _view) {
|
||||||
using LiteralType = Literal<
|
using LiteralType =
|
||||||
internal::remove_namespaces<internal::get_type_name<StructType>()>()>;
|
Literal<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(
|
return make_named_tuple(FieldType(LiteralType()), 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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,9 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
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 =
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
std::vector<ValidationType>({ C::template to_schema<T>(), Cs::template to_schema<T>()... });
|
||||||
);
|
return ValidationType { ValidationType::AllOf { .types_ = types } };
|
||||||
return ValidationType {ValidationType::AllOf {.types_ = types}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -21,18 +21,17 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
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 =
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
std::vector<ValidationType>({ C::template to_schema<T>(), Cs::template to_schema<T>()... });
|
||||||
);
|
return ValidationType { ValidationType::AnyOf { .types_ = types } };
|
||||||
return ValidationType {ValidationType::AnyOf {.types_ = types}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Error make_error_message(const std::vector<Error>& _errors) {
|
static Error make_error_message(const std::vector<Error>& _errors) {
|
||||||
std::string msg =
|
std::string msg =
|
||||||
"Expected at least one of the following validations to pass, but "
|
"Expected at least one of the following validations to pass, but "
|
||||||
"none "
|
"none "
|
||||||
"of them did:";
|
"of them did:";
|
||||||
for (size_t i = 0; i < _errors.size(); ++i) {
|
for (size_t i = 0; i < _errors.size(); ++i) {
|
||||||
msg += "\n" + std::to_string(i + 1) + ") " + _errors.at(i).what();
|
msg += "\n" + std::to_string(i + 1) + ") " + _errors.at(i).what();
|
||||||
}
|
}
|
||||||
|
@ -40,16 +39,13 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class Head, class... Tail>
|
template <class T, class Head, class... Tail>
|
||||||
static rfl::Result<T>
|
static rfl::Result<T> validate_impl(const T& _value, std::vector<Error> _errors) {
|
||||||
validate_impl(const T& _value, std::vector<Error> _errors) {
|
|
||||||
const auto handle_err = [&](Error&& _err) {
|
const auto handle_err = [&](Error&& _err) {
|
||||||
_errors.push_back(std::forward<Error>(_err));
|
_errors.push_back(std::forward<Error>(_err));
|
||||||
if constexpr (sizeof...(Tail) == 0) {
|
if constexpr (sizeof...(Tail) == 0) {
|
||||||
return make_error_message(_errors);
|
return make_error_message(_errors);
|
||||||
} else {
|
} else {
|
||||||
return validate_impl<T, Tail...>(
|
return validate_impl<T, Tail...>(_value, std::forward<std::vector<Error>>(_errors));
|
||||||
_value, std::forward<std::vector<Error>>(_errors)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Head::validate(_value).or_else(handle_err);
|
return Head::validate(_value).or_else(handle_err);
|
||||||
|
|
|
@ -33,29 +33,19 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {}
|
Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {}
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Attribute(const Default& _default) : value_(Type()) {}
|
Attribute(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Attribute() = default;
|
~Attribute() = default;
|
||||||
|
@ -82,10 +72,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -93,9 +80,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -38,8 +38,7 @@ namespace rfl {
|
||||||
Box(Box<T>&& _other) = default;
|
Box(Box<T>&& _other) = default;
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
Box(Box<U>&& _other) noexcept
|
Box(Box<U>&& _other) noexcept : ptr_(std::forward<std::unique_ptr<U>>(_other.ptr())) {}
|
||||||
: ptr_(std::forward<std::unique_ptr<U>>(_other.ptr())) {}
|
|
||||||
|
|
||||||
~Box() = default;
|
~Box() = default;
|
||||||
|
|
||||||
|
@ -110,9 +109,7 @@ namespace std {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct hash<rfl::Box<T>> {
|
struct hash<rfl::Box<T>> {
|
||||||
size_t operator()(const rfl::Box<T>& _b) const {
|
size_t operator()(const rfl::Box<T>& _b) const { return hash<unique_ptr<T>>()(_b.ptr()); }
|
||||||
return hash<unique_ptr<T>>()(_b.ptr());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -36,36 +36,24 @@ namespace rfl {
|
||||||
Description(const Description<_description, Type>& _field) = default;
|
Description(const Description<_description, Type>& _field) = default;
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
Description(const Description<_description, U>& _field)
|
Description(const Description<_description, U>& _field) : value_(_field.get()) {}
|
||||||
: value_(_field.get()) {}
|
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
Description(Description<_description, U>&& _field) : value_(_field.get()) {}
|
Description(Description<_description, U>&& _field) : value_(_field.get()) {}
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
Description(const Description<_description, U>& _field) : value_(_field.value()) {}
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
|
||||||
true>
|
|
||||||
Description(const Description<_description, U>& _field)
|
|
||||||
: value_(_field.value()) {}
|
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Description(const Default& _default) : value_(Type()) {}
|
Description(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Description() = default;
|
~Description() = default;
|
||||||
|
@ -95,10 +83,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -106,23 +91,18 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Description<_description, T>& operator=(
|
Description<_description, T>& operator=(const Description<_description, T>& _field) = default;
|
||||||
const Description<_description, T>& _field
|
|
||||||
) = default;
|
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
Description<_description, T>& operator=(
|
Description<_description, T>& operator=(Description<_description, T>&& _field) = default;
|
||||||
Description<_description, T>&& _field
|
|
||||||
) = default;
|
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <class U>
|
template <class U>
|
||||||
|
|
|
@ -39,29 +39,19 @@ 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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Field(const Default& _default) : value_(Type()) {}
|
Field(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Field() = default;
|
~Field() = default;
|
||||||
|
@ -94,10 +84,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -105,9 +92,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -29,16 +29,10 @@ namespace rfl {
|
||||||
template <class U>
|
template <class U>
|
||||||
Flatten(Flatten<U>&& _f) : value_(_f.get()) {}
|
Flatten(Flatten<U>&& _f) : value_(_f.get()) {}
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -68,10 +62,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
|
|
@ -26,9 +26,9 @@ namespace rfl {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ValueType = std::conditional_t<
|
using ValueType = std::conditional_t<
|
||||||
sizeof...(fields_) <= std::numeric_limits<std::uint8_t>::max(),
|
sizeof...(fields_) <= 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.
|
||||||
|
@ -46,9 +46,7 @@ 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 <
|
template <ValueType num_fields = num_fields_, 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,9 +67,7 @@ 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(
|
static_assert(_value < num_fields_, "Value cannot exceed number of fields.");
|
||||||
_value < num_fields_, "Value cannot exceed number of fields."
|
|
||||||
);
|
|
||||||
return Literal<fields_...>(_value);
|
return Literal<fields_...>(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +128,7 @@ namespace rfl {
|
||||||
/// Constructs a Literal from a string. Returns an error if the string
|
/// Constructs a Literal from a string. Returns an error if the string
|
||||||
/// cannot be found.
|
/// cannot be found.
|
||||||
static Result<Literal> from_string(const std::string& _str) {
|
static Result<Literal> from_string(const std::string& _str) {
|
||||||
const auto to_literal = [](const auto& _v) {
|
const auto to_literal = [](const auto& _v) { return Literal<fields_...>(_v); };
|
||||||
return Literal<fields_...>(_v);
|
|
||||||
};
|
|
||||||
return find_value(_str).transform(to_literal);
|
return find_value(_str).transform(to_literal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -156,8 +150,7 @@ 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
|
Literal<fields_...>& operator=(Literal<fields_...>&& _other) noexcept = 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) {
|
||||||
|
@ -166,9 +159,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <=> for other Literals with the same fields.
|
/// <=> for other Literals with the same fields.
|
||||||
auto operator<=>(const Literal<fields_...>& _other) const {
|
auto operator<=>(const Literal<fields_...>& _other) const { return value() <=> _other.value(); }
|
||||||
return value() <=> _other.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <=> for other Literals with different fields.
|
/// <=> for other Literals with different fields.
|
||||||
template <internal::StringLiteral... _fields>
|
template <internal::StringLiteral... _fields>
|
||||||
|
@ -177,9 +168,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <=> for strings.
|
/// <=> for strings.
|
||||||
inline auto operator<=>(const std::string& _str) const {
|
inline auto operator<=>(const std::string& _str) const { return name() <=> _str; }
|
||||||
return name() <=> _str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <=> for const char*.
|
/// <=> for const char*.
|
||||||
template <internal::StringLiteral... other_fields>
|
template <internal::StringLiteral... other_fields>
|
||||||
|
@ -233,9 +222,7 @@ 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);
|
||||||
|
@ -302,8 +289,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
if constexpr (_i + 1 == num_fields_) {
|
if constexpr (_i + 1 == num_fields_) {
|
||||||
return Error(
|
return Error(
|
||||||
"Literal does not support string '" + _str +
|
"Literal does not support string '" + _str +
|
||||||
"'. The following strings are supported: " + allowed_strings() + "."
|
"'. The following strings are supported: " + allowed_strings() + "."
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return find_value<_i + 1>(_str);
|
return find_value<_i + 1>(_str);
|
||||||
|
@ -341,14 +328,11 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(
|
static_assert(sizeof...(fields_) <= std::numeric_limits<ValueType>::max(), "Too many fields.");
|
||||||
sizeof...(fields_) <= std::numeric_limits<ValueType>::max(),
|
|
||||||
"Too many fields."
|
|
||||||
);
|
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof...(fields_) <= 1 || !has_duplicates(),
|
sizeof...(fields_) <= 1 || !has_duplicates(),
|
||||||
"Duplicate strings are not allowed in a Literal."
|
"Duplicate strings are not allowed in a Literal."
|
||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -8,8 +8,7 @@ namespace rfl {
|
||||||
/// Contains meta-information about a field in a struct.
|
/// Contains meta-information about a field in a struct.
|
||||||
class MetaField {
|
class MetaField {
|
||||||
public:
|
public:
|
||||||
MetaField(const std::string& _name, const std::string& _type)
|
MetaField(const std::string& _name, const std::string& _type) : name_(_name), type_(_type) {}
|
||||||
: name_(_name), type_(_type) {}
|
|
||||||
|
|
||||||
~MetaField() = default;
|
~MetaField() = default;
|
||||||
|
|
||||||
|
|
|
@ -31,64 +31,43 @@ namespace rfl {
|
||||||
public:
|
public:
|
||||||
using Fields = std::tuple<std::remove_cvref_t<FieldTypes>...>;
|
using Fields = std::tuple<std::remove_cvref_t<FieldTypes>...>;
|
||||||
using Names = Literal<std::remove_cvref_t<FieldTypes>::name_...>;
|
using Names = Literal<std::remove_cvref_t<FieldTypes>::name_...>;
|
||||||
using Values =
|
using Values = std::tuple<typename std::remove_cvref_t<FieldTypes>::Type...>;
|
||||||
std::tuple<typename std::remove_cvref_t<FieldTypes>::Type...>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Construct from the values.
|
/// Construct from the values.
|
||||||
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>(_values)...) {
|
||||||
std::forward<typename std::remove_cvref<FieldTypes>::type::Type>(
|
static_assert(no_duplicate_field_names(), "Duplicate field names are not allowed");
|
||||||
_values
|
|
||||||
)...
|
|
||||||
) {
|
|
||||||
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...)) {
|
||||||
)
|
static_assert(no_duplicate_field_names(), "Duplicate field names are not allowed");
|
||||||
: values_(std::make_tuple(_values...)) {
|
|
||||||
static_assert(
|
|
||||||
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(), "Duplicate field names are not allowed");
|
||||||
static_assert(
|
|
||||||
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(), "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(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(
|
static_assert(no_duplicate_field_names(), "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(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(
|
static_assert(no_duplicate_field_names(), "Duplicate field names are not allowed");
|
||||||
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
|
@ -100,19 +79,15 @@ namespace rfl {
|
||||||
/// Copy constructor.
|
/// Copy constructor.
|
||||||
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(
|
static_assert(no_duplicate_field_names(), "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(
|
static_assert(no_duplicate_field_names(), "Duplicate field names are not allowed");
|
||||||
no_duplicate_field_names(), "Duplicate field names are not allowed"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~NamedTuple() = default;
|
~NamedTuple() = default;
|
||||||
|
@ -123,12 +98,12 @@ 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))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,14 +113,10 @@ namespace rfl {
|
||||||
auto add(Field<_name, FType> _head, const Tail&... _tail) const {
|
auto add(Field<_name, FType> _head, const Tail&... _tail) const {
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +126,7 @@ namespace rfl {
|
||||||
auto add(std::tuple<TupContent...>&& _tuple, Tail&&... _tail) {
|
auto add(std::tuple<TupContent...>&& _tuple, Tail&&... _tail) {
|
||||||
if constexpr (sizeof...(Tail) > 0) {
|
if constexpr (sizeof...(Tail) > 0) {
|
||||||
return add_tuple(std::forward<std::tuple<TupContent...>>(_tuple))
|
return add_tuple(std::forward<std::tuple<TupContent...>>(_tuple))
|
||||||
.add(std::forward<Tail>(_tail)...);
|
.add(std::forward<Tail>(_tail)...);
|
||||||
} else {
|
} else {
|
||||||
return add_tuple(std::forward<std::tuple<TupContent...>>(_tuple));
|
return add_tuple(std::forward<std::tuple<TupContent...>>(_tuple));
|
||||||
}
|
}
|
||||||
|
@ -177,16 +148,14 @@ namespace rfl {
|
||||||
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(
|
return add(
|
||||||
std::forward<std::tuple<TupContent...>>(_named_tuple.fields()),
|
std::forward<std::tuple<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 add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail)
|
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
|
||||||
const {
|
|
||||||
return add(_named_tuple.fields(), _tail...);
|
return add(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +166,10 @@ 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 = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
const auto to_nt = []<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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,17 +180,17 @@ 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 = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
const auto to_nt = []<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 = [&_f]<typename... AFields>(AFields&&... fields
|
const auto apply_to_field = [&_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());
|
||||||
|
@ -229,9 +199,7 @@ namespace rfl {
|
||||||
/// 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) const {
|
void apply(F&& _f) const {
|
||||||
const auto apply_to_field = [&_f](const auto&... fields) {
|
const auto apply_to_field = [&_f](const auto&... fields) { ((_f(fields)), ...); };
|
||||||
((_f(fields)), ...);
|
|
||||||
};
|
|
||||||
std::apply(apply_to_field, fields());
|
std::apply(apply_to_field, fields());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,12 +252,10 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy assignment operator.
|
/// Copy assignment operator.
|
||||||
NamedTuple<FieldTypes...>& operator=(const NamedTuple<FieldTypes...>& _other
|
NamedTuple<FieldTypes...>& operator=(const NamedTuple<FieldTypes...>& _other) = default;
|
||||||
) = default;
|
|
||||||
|
|
||||||
/// Move assignment operator.
|
/// Move assignment operator.
|
||||||
NamedTuple<FieldTypes...>& operator=(NamedTuple<FieldTypes...>&& _other
|
NamedTuple<FieldTypes...>& operator=(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 {
|
||||||
|
@ -303,32 +269,27 @@ 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
|
auto replace(Field<_name, FType>&& _field, 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) {
|
||||||
return replace_value<RField>(_field.value_);
|
return replace_value<RField>(_field.value_);
|
||||||
} else {
|
} else {
|
||||||
return replace_value<RField>(_field.value_)
|
return replace_value<RField>(_field.value_)
|
||||||
.replace(std::forward<OtherRFields>(_other_fields)...);
|
.replace(std::forward<OtherRFields>(_other_fields)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(
|
auto replace(Field<_name, FType> _field, 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) {
|
||||||
return replace_value<RField>(std::move(_field.value_));
|
return replace_value<RField>(std::move(_field.value_));
|
||||||
} else {
|
} else {
|
||||||
return replace_value<RField>(std::move(_field.value_))
|
return replace_value<RField>(std::move(_field.value_)).replace(_other_fields...);
|
||||||
.replace(_other_fields...);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +299,7 @@ namespace rfl {
|
||||||
auto replace(std::tuple<TupContent...>&& _tuple, Tail&&... _tail) {
|
auto replace(std::tuple<TupContent...>&& _tuple, Tail&&... _tail) {
|
||||||
if constexpr (sizeof...(Tail) > 0) {
|
if constexpr (sizeof...(Tail) > 0) {
|
||||||
return replace_tuple(std::forward<std::tuple<TupContent...>>(_tuple))
|
return replace_tuple(std::forward<std::tuple<TupContent...>>(_tuple))
|
||||||
.replace(std::forward<Tail>(_tail)...);
|
.replace(std::forward<Tail>(_tail)...);
|
||||||
} else {
|
} else {
|
||||||
return replace_tuple(std::forward<std::tuple<TupContent...>>(_tuple));
|
return replace_tuple(std::forward<std::tuple<TupContent...>>(_tuple));
|
||||||
}
|
}
|
||||||
|
@ -360,16 +321,14 @@ namespace rfl {
|
||||||
template <class... TupContent, class... Tail>
|
template <class... TupContent, class... Tail>
|
||||||
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, const Tail&... _tail)
|
auto replace(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
|
||||||
const {
|
|
||||||
return replace(_named_tuple.fields(), _tail...);
|
return replace(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,9 +342,10 @@ 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 = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
const auto to_nt = []<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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,9 +356,10 @@ 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 = []<class... NewFields>(std::tuple<NewFields...>&& _tup
|
const auto to_nt = []<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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,8 +407,7 @@ 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 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)...
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,7 +428,7 @@ 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)...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,18 +447,18 @@ 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<V>(_values),
|
||||||
std::forward<T>(_val),
|
std::forward<T>(_val),
|
||||||
std::forward<Args>(_args)...,
|
std::forward<Args>(_args)...,
|
||||||
FieldType(std::forward<T>(_val))
|
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<V>(_values),
|
||||||
std::forward<T>(_val),
|
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)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,9 +474,7 @@ 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>(
|
return make_replaced<index, Values, T>(std::forward<Values>(values_), 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.
|
||||||
|
@ -525,9 +483,7 @@ namespace rfl {
|
||||||
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>(
|
return make_replaced<index, Values, T>(std::move(values), 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,
|
||||||
|
@ -552,10 +508,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Retrieves the fields from another tuple.
|
/// Retrieves the fields from another tuple.
|
||||||
template <class... OtherFieldTypes, class... Args>
|
template <class... OtherFieldTypes, class... Args>
|
||||||
constexpr static Fields retrieve_fields(
|
constexpr static Fields
|
||||||
std::tuple<OtherFieldTypes...>&& _other_fields,
|
retrieve_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>;
|
||||||
|
@ -563,20 +517,18 @@ namespace rfl {
|
||||||
if constexpr (retrieved_all_fields) {
|
if constexpr (retrieved_all_fields) {
|
||||||
return std::make_tuple(std::forward<Args>(_args)...);
|
return std::make_tuple(std::forward<Args>(_args)...);
|
||||||
} else {
|
} else {
|
||||||
constexpr auto field_name =
|
constexpr auto field_name = std::tuple_element<size, Fields>::type::name_;
|
||||||
std::tuple_element<size, Fields>::type::name_;
|
|
||||||
|
|
||||||
constexpr auto index =
|
constexpr auto index = internal::find_index<field_name, std::tuple<OtherFieldTypes...>>();
|
||||||
internal::find_index<field_name, std::tuple<OtherFieldTypes...>>();
|
|
||||||
|
|
||||||
using FieldType = typename std::tuple_element<size, Fields>::type;
|
using FieldType = typename std::tuple_element<size, Fields>::type;
|
||||||
|
|
||||||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||||
|
|
||||||
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_))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,8 +579,7 @@ 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, const Tail&... _tail)
|
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
|
||||||
const {
|
|
||||||
return add(_named_tuple.fields(), _tail...);
|
return add(_named_tuple.fields(), _tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,72 +612,55 @@ namespace rfl {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <
|
template <
|
||||||
internal::StringLiteral _name1,
|
internal::StringLiteral _name1,
|
||||||
class Type1,
|
class Type1,
|
||||||
internal::StringLiteral _name2,
|
internal::StringLiteral _name2,
|
||||||
class Type2>
|
class Type2>
|
||||||
inline auto operator*(
|
inline auto
|
||||||
const rfl::Field<_name1, Type1>& _f1,
|
operator*(const rfl::Field<_name1, Type1>& _f1, const rfl::Field<_name2, Type2>& _f2) {
|
||||||
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*(
|
inline auto operator*(const NamedTuple<FieldTypes...>& _tup, 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*(
|
inline auto operator*(const rfl::Field<_name, Type>& _f, 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*(
|
inline auto
|
||||||
const NamedTuple<FieldTypes1...>& _tup1,
|
operator*(const NamedTuple<FieldTypes1...>& _tup1, const NamedTuple<FieldTypes2...>& _tup2) {
|
||||||
const NamedTuple<FieldTypes2...>& _tup2
|
|
||||||
) {
|
|
||||||
return _tup1.add(_tup2);
|
return _tup1.add(_tup2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
internal::StringLiteral _name1,
|
internal::StringLiteral _name1,
|
||||||
class Type1,
|
class Type1,
|
||||||
internal::StringLiteral _name2,
|
internal::StringLiteral _name2,
|
||||||
class Type2>
|
class Type2>
|
||||||
inline auto
|
inline auto operator*(rfl::Field<_name1, Type1>&& _f1, rfl::Field<_name2, Type2>&& _f2) {
|
||||||
operator*(rfl::Field<_name1, Type1>&& _f1, rfl::Field<_name2, Type2>&& _f2) {
|
|
||||||
return NamedTuple(
|
return NamedTuple(
|
||||||
std::forward<Field<_name1, Type1>>(_f1),
|
std::forward<Field<_name1, Type1>>(_f1), std::forward<Field<_name2, Type2>>(_f2)
|
||||||
std::forward<Field<_name2, Type2>>(_f2)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
template <internal::StringLiteral _name, class Type, class... FieldTypes>
|
||||||
inline auto
|
inline auto operator*(NamedTuple<FieldTypes...>&& _tup, 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
|
inline auto operator*(rfl::Field<_name, Type>&& _f, 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*(
|
inline auto operator*(NamedTuple<FieldTypes1...>&& _tup1, 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,14 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
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 =
|
||||||
{C::template to_schema<T>(), Cs::template to_schema<T>()...}
|
std::vector<ValidationType>({ C::template to_schema<T>(), Cs::template to_schema<T>()... });
|
||||||
);
|
return ValidationType { ValidationType::OneOf { .types_ = types } };
|
||||||
return ValidationType {ValidationType::OneOf {.types_ = types}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Error make_error_message(const std::vector<Error>& _errors) {
|
static Error make_error_message(const std::vector<Error>& _errors) {
|
||||||
std::string msg = "Expected exactly 1 out of " +
|
std::string msg = "Expected exactly 1 out of " + std::to_string(sizeof...(Cs) + 1) +
|
||||||
std::to_string(sizeof...(Cs) + 1) +
|
|
||||||
" validations to pass, but " +
|
" validations to pass, but " +
|
||||||
std::to_string(sizeof...(Cs) + 1 - _errors.size()) +
|
std::to_string(sizeof...(Cs) + 1 - _errors.size()) +
|
||||||
" of them did. The following errors were generated: ";
|
" of them did. The following errors were generated: ";
|
||||||
|
@ -41,8 +39,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class Head, class... Tail>
|
template <class T, class Head, class... Tail>
|
||||||
static rfl::Result<T>
|
static rfl::Result<T> validate_impl(const T& _value, 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;
|
||||||
|
@ -57,15 +54,11 @@ 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)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Head::validate(_value)
|
return Head::validate(_value).and_then(next_validation).or_else(next_validation);
|
||||||
.and_then(next_validation)
|
|
||||||
.or_else(next_validation);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ namespace rfl {
|
||||||
return _str;
|
return _str;
|
||||||
} else {
|
} else {
|
||||||
return rfl::Error(
|
return rfl::Error(
|
||||||
"String '" + _str + "' did not match format '" + _name.str() +
|
"String '" + _str + "' did not match format '" + _name.str() + "': '" + _regex.str() +
|
||||||
"': '" + _regex.str() + "'."
|
"'."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
return ValidationType {ValidationType::Regex {.pattern_ = Regex().str()}};
|
return ValidationType { ValidationType::Regex { .pattern_ = Regex().str() } };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,13 @@ 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_ = std::disjunction_v<
|
static constexpr bool all_required_ =
|
||||||
internal::is_no_optionals<Head>,
|
std::disjunction_v<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))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,8 +50,7 @@ namespace rfl {
|
||||||
Ref(const Ref<U>& _other) : ptr_(_other.ptr()) {}
|
Ref(const Ref<U>& _other) : ptr_(_other.ptr()) {}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
Ref(Ref<U>&& _other) noexcept
|
Ref(Ref<U>&& _other) noexcept : ptr_(std::forward<std::shared_ptr<U>>(_other.ptr())) {}
|
||||||
: ptr_(std::forward<std::shared_ptr<U>>(_other.ptr())) {}
|
|
||||||
|
|
||||||
~Ref() = default;
|
~Ref() = default;
|
||||||
|
|
||||||
|
@ -132,9 +131,7 @@ namespace std {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct hash<rfl::Ref<T>> {
|
struct hash<rfl::Ref<T>> {
|
||||||
size_t operator()(const rfl::Ref<T>& _r) const {
|
size_t operator()(const rfl::Ref<T>& _r) const { return hash<shared_ptr<T>>()(_r.ptr()); }
|
||||||
return hash<shared_ptr<T>>()(_r.ptr());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -39,29 +39,19 @@ 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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Rename(const Default& _default) : value_(Type()) {}
|
Rename(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Rename() = default;
|
~Rename() = default;
|
||||||
|
@ -91,10 +81,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -102,9 +89,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -40,52 +40,33 @@ 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(
|
static_assert(!std::is_same<T, Error>(), "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))>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Type = T;
|
using Type = T;
|
||||||
|
|
||||||
Result(const T& _val) : success_(true) { new (&get_t()) T(_val); }
|
Result(const T& _val) : success_(true) { new (&get_t()) T(_val); }
|
||||||
|
|
||||||
Result(T&& _val) noexcept : success_(true) {
|
Result(T&& _val) noexcept : success_(true) { new (&get_t()) T(std::move(_val)); }
|
||||||
new (&get_t()) T(std::move(_val));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result(const Error& _err) : success_(false) {
|
Result(const Error& _err) : success_(false) { new (&get_err()) Error(_err); }
|
||||||
new (&get_err()) Error(_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result(Error&& _err) noexcept : success_(false) {
|
Result(Error&& _err) noexcept : success_(false) { new (&get_err()) Error(std::move(_err)); }
|
||||||
new (&get_err()) Error(std::move(_err));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result(Result<T>&& _other) noexcept : success_(_other.success_) {
|
Result(Result<T>&& _other) noexcept : success_(_other.success_) { move_from_other(_other); }
|
||||||
move_from_other(_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result(const Result<T>& _other) : success_(_other.success_) {
|
Result(const Result<T>& _other) : success_(_other.success_) { copy_from_other(_other); }
|
||||||
copy_from_other(_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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([](U&& _u) {
|
auto temp =
|
||||||
return T(std::forward<U>(_u));
|
std::forward<Result<U>>(_other).transform([](U&& _u) { return T(std::forward<U>(_u)); });
|
||||||
});
|
|
||||||
move_from_other(temp);
|
move_from_other(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
Result(const Result<U>& _other) : success_(_other && true) {
|
Result(const Result<U>& _other) : success_(_other && true) {
|
||||||
auto temp = _other.transform([](const U& _u) { return T(_u); });
|
auto temp = _other.transform([](const U& _u) { return T(_u); });
|
||||||
move_from_other(temp);
|
move_from_other(temp);
|
||||||
|
@ -209,9 +190,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
auto& operator=(const Result<U>& _other) {
|
auto& operator=(const Result<U>& _other) {
|
||||||
const auto to_t = [](const U& _u) -> T { return _u; };
|
const auto to_t = [](const U& _u) -> T { return _u; };
|
||||||
t_or_err_ = _other.transform(to_t).t_or_err_;
|
t_or_err_ = _other.transform(to_t).t_or_err_;
|
||||||
|
@ -320,8 +299,7 @@ namespace rfl {
|
||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
if (success_) {
|
if (success_) {
|
||||||
if constexpr (std::is_destructible_v<
|
if constexpr (std::is_destructible_v<T> /*&& !internal::is_array_v<T>*/) {
|
||||||
T> /*&& !internal::is_array_v<T>*/) {
|
|
||||||
get_t().~T();
|
get_t().~T();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -331,13 +309,9 @@ namespace rfl {
|
||||||
|
|
||||||
T& get_t() noexcept { return *(reinterpret_cast<T*>(t_or_err_.data())); }
|
T& get_t() noexcept { return *(reinterpret_cast<T*>(t_or_err_.data())); }
|
||||||
|
|
||||||
const T& get_t() const noexcept {
|
const T& get_t() const noexcept { return *(reinterpret_cast<const T*>(t_or_err_.data())); }
|
||||||
return *(reinterpret_cast<const T*>(t_or_err_.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Error& get_err() noexcept {
|
Error& get_err() noexcept { return *(reinterpret_cast<Error*>(t_or_err_.data())); }
|
||||||
return *(reinterpret_cast<Error*>(t_or_err_.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Error& get_err() const noexcept {
|
const Error& get_err() const noexcept {
|
||||||
return *(reinterpret_cast<const Error*>(t_or_err_.data()));
|
return *(reinterpret_cast<const Error*>(t_or_err_.data()));
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace rfl {
|
||||||
template <class FieldType>
|
template <class FieldType>
|
||||||
static auto handle_one_field(FieldType&& _f) {
|
static auto handle_one_field(FieldType&& _f) {
|
||||||
using NewFieldType = Field<
|
using NewFieldType = Field<
|
||||||
internal::transform_snake_case<
|
internal::transform_snake_case<
|
||||||
FieldType::name_,
|
FieldType::name_,
|
||||||
/*capitalize=*/false>(),
|
/*capitalize=*/false>(),
|
||||||
typename FieldType::Type>;
|
typename FieldType::Type>;
|
||||||
return NewFieldType(_f.value());
|
return NewFieldType(_f.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace rfl {
|
||||||
template <class FieldType>
|
template <class FieldType>
|
||||||
static auto handle_one_field(FieldType&& _f) {
|
static auto handle_one_field(FieldType&& _f) {
|
||||||
using NewFieldType = Field<
|
using NewFieldType = Field<
|
||||||
internal::transform_snake_case<
|
internal::transform_snake_case<
|
||||||
FieldType::name_,
|
FieldType::name_,
|
||||||
/*capitalize=*/true>(),
|
/*capitalize=*/true>(),
|
||||||
typename FieldType::Type>;
|
typename FieldType::Type>;
|
||||||
return NewFieldType(_f.value());
|
return NewFieldType(_f.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,30 +19,24 @@ namespace rfl {
|
||||||
using VariantType = std::variant<Ts...>;
|
using VariantType = std::variant<Ts...>;
|
||||||
|
|
||||||
/// A literal containing all the tags that are possible
|
/// A literal containing all the tags that are possible
|
||||||
using PossibleTags =
|
using PossibleTags = define_literal_t<internal::tag_t<_discriminator, Ts>...>;
|
||||||
define_literal_t<internal::tag_t<_discriminator, Ts>...>;
|
|
||||||
|
|
||||||
TaggedUnion(const VariantType& _variant) : variant_(_variant) {}
|
TaggedUnion(const VariantType& _variant) : variant_(_variant) {}
|
||||||
|
|
||||||
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
|
TaggedUnion(TaggedUnion<_discriminator, Ts...>&& _tagged_union) noexcept = default;
|
||||||
) noexcept = default;
|
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
TaggedUnion(const T& _t) : variant_(_t) {}
|
TaggedUnion(const T& _t) : variant_(_t) {}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
TaggedUnion(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
TaggedUnion(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
||||||
|
|
||||||
~TaggedUnion() = default;
|
~TaggedUnion() = default;
|
||||||
|
@ -61,9 +55,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
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;
|
||||||
|
@ -71,22 +64,19 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(const T& _variant) {
|
TaggedUnion<_discriminator, Ts...>& operator=(const T& _variant) {
|
||||||
variant_ = _variant;
|
variant_ = _variant;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(
|
TaggedUnion<_discriminator, Ts...>& operator=(const TaggedUnion<_discriminator, Ts...>& _other
|
||||||
const TaggedUnion<_discriminator, Ts...>& _other
|
|
||||||
) = default;
|
) = default;
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
TaggedUnion<_discriminator, Ts...>& operator=(
|
TaggedUnion<_discriminator, Ts...>& operator=(TaggedUnion<_discriminator, Ts...>&& _other
|
||||||
TaggedUnion<_discriminator, Ts...>&& _other
|
|
||||||
) = default;
|
) = default;
|
||||||
|
|
||||||
/// Returns the underlying variant.
|
/// Returns the underlying variant.
|
||||||
|
@ -96,8 +86,8 @@ namespace rfl {
|
||||||
const VariantType& variant() const { return variant_; }
|
const VariantType& variant() const { return variant_; }
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
!PossibleTags::has_duplicates(),
|
!PossibleTags::has_duplicates(),
|
||||||
"Duplicate tags are not allowed inside tagged unions."
|
"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
|
||||||
|
@ -112,58 +102,43 @@ namespace rfl {
|
||||||
public:
|
public:
|
||||||
/// 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>(_tu.variant_);
|
||||||
) {
|
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<_index>(
|
|
||||||
_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<_field_name>(_tu.variant_);
|
||||||
) {
|
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<
|
|
||||||
_field_name>(_tu.variant_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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>(_tu.variant_);
|
||||||
) {
|
|
||||||
return Getter<std::variant<NamedTupleTypes...>>::template get<Field>(
|
|
||||||
_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_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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>(
|
||||||
_field_name>(_tu.variant_);
|
_tu.variant_
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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_);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,7 @@ namespace rfl {
|
||||||
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(
|
throw std::runtime_error(
|
||||||
"String '" + std::string(_str) + "' did not match format '" +
|
"String '" + std::string(_str) + "' did not match format '" + Format().str() + "'."
|
||||||
Format().str() + "'."
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ namespace rfl {
|
||||||
struct Validator {
|
struct Validator {
|
||||||
public:
|
public:
|
||||||
using ReflectionType = T;
|
using ReflectionType = T;
|
||||||
using ValidationType =
|
using ValidationType = std::conditional_t<sizeof...(Vs) == 0, V, AllOf<V, Vs...>>;
|
||||||
std::conditional_t<sizeof...(Vs) == 0, V, AllOf<V, Vs...>>;
|
|
||||||
|
|
||||||
/// Exception-free validation.
|
/// Exception-free validation.
|
||||||
static Result<Validator<T, V, Vs...>> from_value(const T& _value) noexcept {
|
static Result<Validator<T, V, Vs...>> from_value(const T& _value) noexcept {
|
||||||
|
@ -39,21 +38,13 @@ namespace rfl {
|
||||||
|
|
||||||
Validator(T&& _value) : value_(ValidationType::validate(_value).value()) {}
|
Validator(T&& _value) : value_(ValidationType::validate(_value).value()) {}
|
||||||
|
|
||||||
Validator(const T& _value)
|
Validator(const T& _value) : value_(ValidationType::validate(_value).value()) {}
|
||||||
: value_(ValidationType::validate(_value).value()) {}
|
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
Validator(U&& _value) : value_(ValidationType::validate(T(std::forward<U>(_value))).value()) {}
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
Validator(U&& _value)
|
|
||||||
: value_(ValidationType::validate(T(std::forward<U>(_value))).value()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
Validator(const U& _value) : value_(ValidationType::validate(T(_value)).value()) {}
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
Validator(const U& _value)
|
|
||||||
: value_(ValidationType::validate(T(_value)).value()) {}
|
|
||||||
|
|
||||||
~Validator() = default;
|
~Validator() = default;
|
||||||
|
|
||||||
|
@ -70,26 +61,20 @@ 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...>&& _other
|
Validator<T, V, Vs...>& operator=(Validator<T, V, Vs...>&& _other) noexcept = default;
|
||||||
) noexcept = default;
|
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
auto& operator=(U&& _value) noexcept {
|
auto& operator=(U&& _value) noexcept {
|
||||||
value_ = ValidationType::validate(T(std::forward<U>(_value))).value();
|
value_ = ValidationType::validate(T(std::forward<U>(_value))).value();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
||||||
class U,
|
|
||||||
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
|
|
||||||
auto& operator=(const U& _value) {
|
auto& operator=(const U& _value) {
|
||||||
value_ = ValidationType::validate(T(_value)).value();
|
value_ = ValidationType::validate(T(_value)).value();
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -115,10 +100,7 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class V, class... Vs>
|
template <class T, class V, class... Vs>
|
||||||
inline auto operator<=>(
|
inline auto operator<=>(const Validator<T, V, Vs...>& _v1, 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,9 +115,7 @@ namespace std {
|
||||||
|
|
||||||
template <class T, class V, class... Vs>
|
template <class T, class V, class... Vs>
|
||||||
struct hash<rfl::Validator<T, V, Vs...>> {
|
struct hash<rfl::Validator<T, V, Vs...>> {
|
||||||
size_t operator()(const rfl::Validator<T, V, Vs...>& _v) const {
|
size_t operator()(const rfl::Validator<T, V, Vs...>& _v) const { return hash<T>()(_v.value()); }
|
||||||
return hash<T>()(_v.value());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
|
@ -19,15 +19,13 @@ namespace rfl {
|
||||||
Variant(Variant<AlternativeTypes...>&& _variant) noexcept = default;
|
Variant(Variant<AlternativeTypes...>&& _variant) noexcept = default;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Variant(const T& _t) : variant_(_t) {}
|
Variant(const T& _t) : variant_(_t) {}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Variant(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
Variant(T&& _t) noexcept : variant_(std::forward<T>(_t)) {}
|
||||||
|
|
||||||
~Variant() = default;
|
~Variant() = default;
|
||||||
|
@ -46,9 +44,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
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;
|
||||||
|
@ -56,23 +53,18 @@ namespace rfl {
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <
|
||||||
class T,
|
class T,
|
||||||
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::
|
typename std::enable_if<std::is_convertible_v<T, VariantType>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Variant<AlternativeTypes...>& operator=(const T& _variant) {
|
Variant<AlternativeTypes...>& operator=(const T& _variant) {
|
||||||
variant_ = _variant;
|
variant_ = _variant;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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_; }
|
||||||
|
|
|
@ -14,8 +14,7 @@ namespace rfl {
|
||||||
return from_named_tuple<T>(to_named_tuple(std::forward<Head>(_head)));
|
return from_named_tuple<T>(to_named_tuple(std::forward<Head>(_head)));
|
||||||
} 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))...)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +25,7 @@ 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>(to_named_tuple(_head).add(to_named_tuple(_tail
|
return from_named_tuple<T>(to_named_tuple(_head).add(to_named_tuple(_tail)...));
|
||||||
)...));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,25 +19,18 @@ namespace rfl::parsing {
|
||||||
|
|
||||||
using ParentType = Parent<W>;
|
using ParentType = Parent<W>;
|
||||||
|
|
||||||
static Result<bson_oid_t>
|
static Result<bson_oid_t> read(const R& _r, 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
|
static void write(const W& _w, const bson_oid_t& _oid, const P& _parent) noexcept {
|
||||||
write(const W& _w, const bson_oid_t& _oid, 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.");
|
||||||
) {
|
return schema::Type { schema::Type::String {} };
|
||||||
static_assert(
|
|
||||||
rfl::always_false_v<R>,
|
|
||||||
"bson_oid_t cannot be expressed inside a JSON schema."
|
|
||||||
);
|
|
||||||
return schema::Type {schema::Type::String {}};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,12 +47,10 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static constexpr bool has_custom_constructor =
|
static constexpr bool has_custom_constructor =
|
||||||
(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 InputObjectType& _obj)
|
||||||
const std::string& _name,
|
const noexcept {
|
||||||
const InputObjectType& _obj
|
|
||||||
) const noexcept {
|
|
||||||
bson_t b;
|
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;
|
||||||
|
@ -86,9 +84,7 @@ namespace rfl {
|
||||||
return std::string(value.v_symbol.symbol, value.v_symbol.len);
|
return std::string(value.v_symbol.symbol, value.v_symbol.len);
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -112,12 +108,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>, bson_oid_t>(
|
} else if constexpr (std::is_same<std::remove_cvref_t<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.");
|
||||||
}
|
}
|
||||||
|
@ -127,20 +122,17 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
rfl::Result<InputArrayType> to_array(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.");
|
||||||
}
|
}
|
||||||
return InputArrayType {_var.val_};
|
return InputArrayType { _var.val_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(const ArrayReader& _array_reader, const InputArrayType& _arr)
|
||||||
const ArrayReader& _array_reader,
|
const noexcept {
|
||||||
const InputArrayType& _arr
|
|
||||||
) const noexcept {
|
|
||||||
bson_t b;
|
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;
|
||||||
|
@ -158,10 +150,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error>
|
||||||
const ObjectReader& _object_reader,
|
read_object(const ObjectReader& _object_reader, const InputObjectType& _obj) const noexcept {
|
||||||
const InputObjectType& _obj
|
|
||||||
) const noexcept {
|
|
||||||
bson_t b;
|
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;
|
||||||
|
@ -176,18 +166,16 @@ namespace rfl {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputObjectType> to_object(const InputVarType& _var
|
rfl::Result<InputObjectType> to_object(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.");
|
||||||
}
|
}
|
||||||
return InputObjectType {_var.val_};
|
return InputObjectType { _var.val_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
rfl::Result<T> use_custom_constructor(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()); }
|
||||||
|
@ -206,7 +194,7 @@ namespace rfl {
|
||||||
values_->vec_.emplace_back(rfl::Box<BSONValue>::make());
|
values_->vec_.emplace_back(rfl::Box<BSONValue>::make());
|
||||||
auto* last_value = values_->vec_.back().get();
|
auto* last_value = values_->vec_.back().get();
|
||||||
bson_value_copy(bson_iter_value(_iter), &last_value->val_);
|
bson_value_copy(bson_iter_value(_iter), &last_value->val_);
|
||||||
return InputVarType {last_value};
|
return InputVarType { last_value };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -41,14 +41,13 @@ namespace rfl {
|
||||||
public:
|
public:
|
||||||
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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BSONOutputObject {
|
struct BSONOutputObject {
|
||||||
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_;
|
||||||
};
|
};
|
||||||
|
@ -79,83 +78,61 @@ 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(
|
static_assert(rfl::always_false_v<T>, "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, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
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_ });
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) const noexcept {
|
||||||
bson_array_builder_t* val;
|
bson_array_builder_t* val;
|
||||||
bson_append_array_builder_begin(
|
bson_append_array_builder_begin(
|
||||||
_parent->val_, _name.data(), 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, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
const noexcept {
|
||||||
OutputArrayType* _parent
|
|
||||||
) const noexcept {
|
|
||||||
subdocs_->emplace_back(rfl::Box<BSONType>());
|
subdocs_->emplace_back(rfl::Box<BSONType>());
|
||||||
bson_array_builder_append_document_begin(
|
bson_array_builder_append_document_begin(_parent->val_, &(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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) const noexcept {
|
||||||
subdocs_->emplace_back(rfl::Box<BSONType>());
|
subdocs_->emplace_back(rfl::Box<BSONType>());
|
||||||
bson_append_document_begin(
|
bson_append_document_begin(
|
||||||
_parent->val_,
|
_parent->val_, _name.data(), static_cast<int>(_name.size()), &(subdocs_->back()->val_)
|
||||||
_name.data(),
|
|
||||||
static_cast<int>(_name.size()),
|
|
||||||
&(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(
|
bson_array_builder_append_utf8(
|
||||||
_parent->val_, _var.c_str(), 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(
|
bson_array_builder_append_double(_parent->val_, 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(
|
bson_array_builder_append_int64(_parent->val_, 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.");
|
||||||
|
@ -165,41 +142,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
|
OutputObjectType* _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_append_utf8(
|
bson_append_utf8(
|
||||||
_parent->val_,
|
_parent->val_,
|
||||||
_name.data(),
|
_name.data(),
|
||||||
static_cast<int>(_name.size()),
|
static_cast<int>(_name.size()),
|
||||||
_var.c_str(),
|
_var.c_str(),
|
||||||
static_cast<int>(_var.size())
|
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(
|
bson_append_bool(_parent->val_, _name.data(), 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(
|
bson_append_double(
|
||||||
_parent->val_,
|
_parent->val_, _name.data(), static_cast<int>(_name.size()), static_cast<double>(_var)
|
||||||
_name.data(),
|
|
||||||
static_cast<int>(_name.size()),
|
|
||||||
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(
|
bson_append_int64(
|
||||||
_parent->val_,
|
_parent->val_,
|
||||||
_name.data(),
|
_name.data(),
|
||||||
static_cast<int>(_name.size()),
|
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>(
|
|
||||||
)) {
|
|
||||||
bson_append_oid(
|
|
||||||
_parent->val_, _name.data(), static_cast<int>(_name.size()), &_var
|
|
||||||
);
|
);
|
||||||
|
} 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);
|
||||||
} else {
|
} else {
|
||||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||||
}
|
}
|
||||||
|
@ -211,13 +180,9 @@ namespace rfl {
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(const std::string_view& _name, OutputObjectType* _parent)
|
||||||
const std::string_view& _name,
|
const noexcept {
|
||||||
OutputObjectType* _parent
|
bson_append_null(_parent->val_, _name.data(), static_cast<int>(_name.size()));
|
||||||
) const noexcept {
|
|
||||||
bson_append_null(
|
|
||||||
_parent->val_, _name.data(), static_cast<int>(_name.size())
|
|
||||||
);
|
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,9 +190,7 @@ 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(
|
bson_array_builder_append_array_builder_end(_parent.ptr_, _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>()) {
|
||||||
|
|
|
@ -10,9 +10,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<T> load(const std::string& _fname) {
|
Result<T> load(const std::string& _fname) {
|
||||||
const auto read_bytes = [](const auto& _bytes) {
|
const auto read_bytes = [](const auto& _bytes) { return read<T, Ps...>(_bytes); };
|
||||||
return read<T, Ps...>(_bytes);
|
|
||||||
};
|
|
||||||
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace rfl {
|
||||||
value.val_.value.v_doc.data_len = static_cast<uint32_t>(_size);
|
value.val_.value.v_doc.data_len = static_cast<uint32_t>(_size);
|
||||||
value.val_.value.v_doc.data = const_cast<uint8_t*>(_bytes);
|
value.val_.value.v_doc.data = const_cast<uint8_t*>(_bytes);
|
||||||
value.val_.value_type = BSON_TYPE_DOCUMENT;
|
value.val_.value_type = BSON_TYPE_DOCUMENT;
|
||||||
auto doc = InputVarType {&value};
|
auto doc = InputVarType { &value };
|
||||||
return read<T, Ps...>(doc);
|
return read<T, Ps...>(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,18 +18,15 @@ 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(
|
Parser<T, Processors<Ps...>>::write(rfl_writer, _obj, 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,10 +36,9 @@ namespace rfl {
|
||||||
/// Returns BSON bytes.
|
/// Returns BSON bytes.
|
||||||
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>(
|
const auto result =
|
||||||
reinterpret_cast<char*>(buf), reinterpret_cast<char*>(buf) + len
|
std::vector<char>(reinterpret_cast<char*>(buf), reinterpret_cast<char*>(buf) + len);
|
||||||
);
|
|
||||||
bson_free(buf);
|
bson_free(buf);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,33 +12,26 @@ 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<
|
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, NamedTuple<FieldTypes...>>
|
||||||
|
struct Parser<cbor::Reader, cbor::Writer, NamedTuple<FieldTypes...>, ProcessorsType>
|
||||||
|
: public NamedTupleParser<
|
||||||
cbor::Reader,
|
cbor::Reader,
|
||||||
cbor::Writer,
|
cbor::Writer,
|
||||||
NamedTuple<FieldTypes...>>
|
/*_ignore_empty_containers=*/false,
|
||||||
struct Parser<
|
/*_all_required=*/true,
|
||||||
cbor::Reader,
|
ProcessorsType,
|
||||||
cbor::Writer,
|
FieldTypes...> {};
|
||||||
NamedTuple<FieldTypes...>,
|
|
||||||
ProcessorsType>
|
|
||||||
: public NamedTupleParser<
|
|
||||||
cbor::Reader,
|
|
||||||
cbor::Writer,
|
|
||||||
/*_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<
|
: public TupleParser<
|
||||||
cbor::Reader,
|
cbor::Reader,
|
||||||
cbor::Writer,
|
cbor::Writer,
|
||||||
/*_ignore_empty_containers=*/false,
|
/*_ignore_empty_containers=*/false,
|
||||||
/*_all_required=*/true,
|
/*_all_required=*/true,
|
||||||
ProcessorsType,
|
ProcessorsType,
|
||||||
Ts...> {};
|
Ts...> {};
|
||||||
|
|
||||||
} // namespace parsing
|
} // namespace parsing
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -43,12 +43,10 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static constexpr bool has_custom_constructor =
|
static constexpr bool has_custom_constructor =
|
||||||
(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 InputObjectType& _obj)
|
||||||
const std::string& _name,
|
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);
|
||||||
|
@ -134,9 +132,9 @@ namespace rfl {
|
||||||
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 {
|
||||||
|
@ -144,27 +142,23 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
rfl::Result<InputArrayType> to_array(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(const InputVarType& _var
|
rfl::Result<InputObjectType> to_object(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.");
|
||||||
}
|
}
|
||||||
return InputObjectType {_var.val_};
|
return InputObjectType { _var.val_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(const ArrayReader& _array_reader, const InputArrayType& _arr)
|
||||||
const ArrayReader& _array_reader,
|
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);
|
||||||
|
@ -190,10 +184,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error>
|
||||||
const ObjectReader& _object_reader,
|
read_object(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) {
|
if (err != CborNoError) {
|
||||||
|
@ -218,7 +210,7 @@ namespace rfl {
|
||||||
return Error(cbor_error_string(err));
|
return Error(cbor_error_string(err));
|
||||||
}
|
}
|
||||||
const auto name = std::string_view(buffer.data(), buffer.size() - 1);
|
const auto name = std::string_view(buffer.data(), buffer.size() - 1);
|
||||||
_object_reader.read(name, InputVarType {&val});
|
_object_reader.read(name, InputVarType { &val });
|
||||||
cbor_value_advance(&val);
|
cbor_value_advance(&val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,16 +218,14 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
rfl::Result<T> use_custom_constructor(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, std::vector<char>* _buffer)
|
CborError get_string(const CborValue* _ptr, 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) {
|
if (err != CborNoError && err != CborErrorOutOfMemory) {
|
||||||
|
@ -243,15 +233,13 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
_buffer->resize(length + 1);
|
_buffer->resize(length + 1);
|
||||||
(*_buffer)[length] = '\0';
|
(*_buffer)[length] = '\0';
|
||||||
return cbor_value_copy_text_string(
|
return cbor_value_copy_text_string(_ptr, _buffer->data(), &length, NULL);
|
||||||
_ptr, _buffer->data(), &length, NULL
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputVarType to_input_var(CborValue* _ptr) const noexcept {
|
InputVarType to_input_var(CborValue* _ptr) const noexcept {
|
||||||
values_->emplace_back(rfl::Box<CborValue>::make(*_ptr));
|
values_->emplace_back(rfl::Box<CborValue>::make(*_ptr));
|
||||||
auto* last_value = values_->back().get();
|
auto* last_value = values_->back().get();
|
||||||
return InputVarType {last_value};
|
return InputVarType { last_value };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -60,49 +60,44 @@ namespace rfl {
|
||||||
return new_value(_var, encoder_);
|
return new_value(_var, encoder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(const size_t _size, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) 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, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) 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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|
||||||
return new_value(_var, _parent->encoder_);
|
return new_value(_var, _parent->encoder_);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) 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_);
|
||||||
|
@ -113,10 +108,8 @@ namespace rfl {
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(const std::string_view& _name, OutputObjectType* _parent)
|
||||||
const std::string_view& _name,
|
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 {};
|
||||||
|
@ -131,23 +124,20 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutputArrayType new_array(const size_t _size, CborEncoder* _parent)
|
OutputArrayType new_array(const size_t _size, 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, CborEncoder* _parent)
|
OutputObjectType new_object(const size_t _size, 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, CborEncoder* _parent)
|
OutputVarType new_value(const T& _var, 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>()) {
|
||||||
|
|
|
@ -11,9 +11,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<T> load(const std::string& _fname) {
|
Result<T> load(const std::string& _fname) {
|
||||||
const auto read_bytes = [](const auto& _bytes) {
|
const auto read_bytes = [](const auto& _bytes) { return read<T, Ps...>(_bytes); };
|
||||||
return read<T, Ps...>(_bytes);
|
|
||||||
};
|
|
||||||
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,11 @@ 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>>
|
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes, const size_t _size) {
|
||||||
read(const char* _bytes, const size_t _size) {
|
|
||||||
CborParser parser;
|
CborParser parser;
|
||||||
CborValue value;
|
CborValue value;
|
||||||
cbor_parser_init(
|
cbor_parser_init(reinterpret_cast<const uint8_t*>(_bytes), _size, 0, &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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,22 +16,15 @@ namespace rfl {
|
||||||
|
|
||||||
template <class... Ps>
|
template <class... Ps>
|
||||||
void write_into_buffer(
|
void write_into_buffer(
|
||||||
const auto& _obj,
|
const auto& _obj,
|
||||||
CborEncoder* _encoder,
|
CborEncoder* _encoder,
|
||||||
std::vector<char>* _buffer
|
std::vector<char>* _buffer
|
||||||
) noexcept {
|
) 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(
|
cbor_encoder_init(_encoder, reinterpret_cast<uint8_t*>(_buffer->data()), _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(
|
Parser<T, Processors<Ps...>>::write(writer, _obj, typename ParentType::Root {});
|
||||||
writer, _obj, typename ParentType::Root {}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns CBOR bytes.
|
/// Returns CBOR bytes.
|
||||||
|
@ -40,15 +33,13 @@ namespace rfl {
|
||||||
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);
|
|
||||||
if (total_bytes_needed != buffer.size()) {
|
if (total_bytes_needed != buffer.size()) {
|
||||||
buffer.resize(total_bytes_needed);
|
buffer.resize(total_bytes_needed);
|
||||||
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 =
|
||||||
&encoder, reinterpret_cast<uint8_t*>(buffer.data())
|
cbor_encoder_get_buffer_size(&encoder, reinterpret_cast<uint8_t*>(buffer.data()));
|
||||||
);
|
|
||||||
buffer.resize(length);
|
buffer.resize(length);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value != threshold) {
|
if (_value != threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to be equal to " + std::to_string(threshold) +
|
"Value expected to be equal to " + std::to_string(threshold) + ", but got " +
|
||||||
", but got " + std::to_string(_value) + "."
|
std::to_string(_value) + "."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -25,11 +25,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::EqualTo { .value_ = value } };
|
||||||
return ValidationType {ValidationType::EqualTo {.value_ = value}};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,9 +39,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value < threshold) {
|
if (_value < threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to be greater than or equal to " +
|
"Value expected to be greater than or equal to " + std::to_string(threshold) +
|
||||||
std::to_string(threshold) + ", but got " + std::to_string(_value) +
|
", but got " + std::to_string(_value) + "."
|
||||||
"."
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -51,11 +49,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::Minimum { .value_ = value } };
|
||||||
return ValidationType {ValidationType::Minimum {.value_ = value}};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,8 +63,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value <= threshold) {
|
if (_value <= threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to be greater than " + std::to_string(threshold) +
|
"Value expected to be greater than " + std::to_string(threshold) + ", but got " +
|
||||||
", but got " + std::to_string(_value) + "."
|
std::to_string(_value) + "."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -76,12 +73,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::ExclusiveMinimum { .value_ = value } };
|
||||||
return ValidationType {ValidationType::ExclusiveMinimum {.value_ = value}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,9 +87,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value > threshold) {
|
if (_value > threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to be less than or equal to " +
|
"Value expected to be less than or equal to " + std::to_string(threshold) + ", but got " +
|
||||||
std::to_string(threshold) + ", but got " + std::to_string(_value) +
|
std::to_string(_value) + "."
|
||||||
"."
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -103,11 +97,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::Maximum { .value_ = value } };
|
||||||
return ValidationType {ValidationType::Maximum {.value_ = value}};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,8 +111,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value >= threshold) {
|
if (_value >= threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to be less than " + std::to_string(threshold) +
|
"Value expected to be less than " + std::to_string(threshold) + ", but got " +
|
||||||
", but got " + std::to_string(_value) + "."
|
std::to_string(_value) + "."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -128,12 +121,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::ExclusiveMaximum { .value_ = value } };
|
||||||
return ValidationType {ValidationType::ExclusiveMaximum {.value_ = value}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,8 +135,8 @@ namespace rfl {
|
||||||
constexpr auto threshold = static_cast<T>(_threshold);
|
constexpr auto threshold = static_cast<T>(_threshold);
|
||||||
if (_value == threshold) {
|
if (_value == threshold) {
|
||||||
return Error(
|
return Error(
|
||||||
"Value expected to not be equal to " + std::to_string(threshold) +
|
"Value expected to not be equal to " + std::to_string(threshold) + ", but got " +
|
||||||
", but got " + std::to_string(_value) + "."
|
std::to_string(_value) + "."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -154,11 +145,10 @@ namespace rfl {
|
||||||
template <class T>
|
template <class T>
|
||||||
static parsing::schema::ValidationType to_schema() {
|
static parsing::schema::ValidationType to_schema() {
|
||||||
using ValidationType = parsing::schema::ValidationType;
|
using ValidationType = parsing::schema::ValidationType;
|
||||||
const auto value =
|
const auto value = 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 { ValidationType::NotEqualTo { .value_ = value } };
|
||||||
return ValidationType {ValidationType::NotEqualTo {.value_ = value}};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ namespace rfl {
|
||||||
|
|
||||||
/// Allows you to combine several literal types.
|
/// Allows you to combine several literal types.
|
||||||
template <class... LiteralTypes>
|
template <class... LiteralTypes>
|
||||||
using define_literal_t =
|
using define_literal_t = typename internal::define_literal<LiteralTypes...>::type;
|
||||||
typename internal::define_literal<LiteralTypes...>::type;
|
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
namespace rfl {
|
namespace rfl {
|
||||||
|
|
||||||
template <class... FieldTypes>
|
template <class... FieldTypes>
|
||||||
using define_named_tuple_t =
|
using define_named_tuple_t = typename internal::define_named_tuple<FieldTypes...>::type;
|
||||||
typename internal::define_named_tuple<FieldTypes...>::type;
|
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
namespace rfl {
|
namespace rfl {
|
||||||
|
|
||||||
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
|
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
|
||||||
using define_tagged_union_t = typename internal::
|
using define_tagged_union_t =
|
||||||
define_tagged_union<_discriminator, TaggedUnionTypes...>::type;
|
typename internal::define_tagged_union<_discriminator, TaggedUnionTypes...>::type;
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -14,23 +14,21 @@ 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(_enum
|
return rfl::internal::enums::StringConverter<EnumType>::enum_to_string(_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(_str
|
return rfl::internal::enums::StringConverter<EnumType>::string_to_enum(_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
|
||||||
// to their values.
|
// to their values.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
auto get_enumerators() {
|
auto get_enumerators() {
|
||||||
constexpr auto names = internal::enums::
|
constexpr auto names =
|
||||||
get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
internal::enums::get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
||||||
return internal::enums::names_to_enumerator_named_tuple(names);
|
return internal::enums::names_to_enumerator_named_tuple(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +36,8 @@ namespace rfl {
|
||||||
// to their underlying values.
|
// to their underlying values.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
auto get_underlying_enumerators() {
|
auto get_underlying_enumerators() {
|
||||||
constexpr auto names = internal::enums::
|
constexpr auto names =
|
||||||
get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
internal::enums::get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
||||||
return internal::enums::names_to_underlying_enumerator_named_tuple(names);
|
return internal::enums::names_to_underlying_enumerator_named_tuple(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +45,8 @@ namespace rfl {
|
||||||
// std::string_view) and values.
|
// std::string_view) and values.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
constexpr auto get_enumerator_array() {
|
constexpr auto get_enumerator_array() {
|
||||||
constexpr auto names = internal::enums::
|
constexpr auto names =
|
||||||
get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
internal::enums::get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
||||||
return internal::enums::names_to_enumerator_array(names);
|
return internal::enums::names_to_enumerator_array(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +54,8 @@ namespace rfl {
|
||||||
// std::string_view) and underlying values.
|
// std::string_view) and underlying values.
|
||||||
template <internal::enums::is_scoped_enum EnumType>
|
template <internal::enums::is_scoped_enum EnumType>
|
||||||
constexpr auto get_underlying_enumerator_array() {
|
constexpr auto get_underlying_enumerator_array() {
|
||||||
constexpr auto names = internal::enums::
|
constexpr auto names =
|
||||||
get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
internal::enums::get_enum_names<EnumType, internal::enums::is_flag_enum<EnumType>>();
|
||||||
return internal::enums::names_to_underlying_enumerator_array(names);
|
return internal::enums::names_to_underlying_enumerator_array(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ namespace rfl {
|
||||||
/// Extracts a Literal containing all of the discriminators from a
|
/// Extracts a Literal containing all of the discriminators from a
|
||||||
/// TaggedUnion.
|
/// TaggedUnion.
|
||||||
template <class TaggedUnionType>
|
template <class TaggedUnionType>
|
||||||
using extract_discriminators_t =
|
using extract_discriminators_t = typename internal::extract_discriminators<TaggedUnionType>::type;
|
||||||
typename internal::extract_discriminators<TaggedUnionType>::type;
|
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace rfl {
|
||||||
|
|
||||||
/// Returns a rfl::Literal containing the field names of struct T.
|
/// Returns a rfl::Literal containing the field names of struct T.
|
||||||
template <class T>
|
template <class T>
|
||||||
using field_names_t = typename std::invoke_result<
|
using field_names_t =
|
||||||
decltype(internal::get_field_names<std::remove_cvref_t<T>>)>::type;
|
typename std::invoke_result<decltype(internal::get_field_names<std::remove_cvref_t<T>>)>::type;
|
||||||
|
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
||||||
|
|
|
@ -27,40 +27,32 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct has_from_flexbuf<
|
struct has_from_flexbuf<
|
||||||
T,
|
T,
|
||||||
std::enable_if_t<
|
std::enable_if_t<std::is_invocable_r<T, decltype(T::from_flexbuf), InputVarType>::value>>
|
||||||
std::is_invocable_r<T, decltype(T::from_flexbuf), InputVarType>::
|
: std::true_type {};
|
||||||
value>> : 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<
|
std::enable_if_t<
|
||||||
rfl::Result<T>,
|
std::is_invocable_r<rfl::Result<T>, decltype(T::from_flexbuf), 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 InputObjectType& _obj)
|
||||||
const std::string& _name,
|
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()) {
|
if (_name == keys[i].AsString().c_str()) {
|
||||||
return _obj.Values()[i];
|
return _obj.Values()[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rfl::Error(
|
return rfl::Error("Map does not contain any element called '" + _name + "'.");
|
||||||
"Map does not contain any element called '" + _name + "'."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_empty(const InputVarType& _var) const noexcept {
|
bool is_empty(const InputVarType& _var) const noexcept { return _var.IsNull(); }
|
||||||
return _var.IsNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> to_basic_type(const InputVarType& _var) const noexcept {
|
rfl::Result<T> to_basic_type(const InputVarType& _var) const noexcept {
|
||||||
|
@ -90,10 +82,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ArrayReader>
|
template <class ArrayReader>
|
||||||
std::optional<Error> read_array(
|
std::optional<Error> read_array(const ArrayReader& _array_reader, const InputArrayType& _arr)
|
||||||
const ArrayReader& _array_reader,
|
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]));
|
||||||
|
@ -105,33 +95,27 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ObjectReader>
|
template <class ObjectReader>
|
||||||
std::optional<Error> read_object(
|
std::optional<Error>
|
||||||
const ObjectReader& _object_reader,
|
read_object(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(
|
_object_reader.read(std::string_view(keys[i].AsString().c_str()), values[i]);
|
||||||
std::string_view(keys[i].AsString().c_str()), values[i]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfl::Result<InputArrayType> to_array(const InputVarType& _var
|
rfl::Result<InputArrayType> to_array(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(const InputVarType& _var
|
rfl::Result<InputObjectType> to_object(const InputVarType& _var) const noexcept {
|
||||||
) const noexcept {
|
|
||||||
if (!_var.IsMap()) {
|
if (!_var.IsMap()) {
|
||||||
return rfl::Error("Could not cast to Map!");
|
return rfl::Error("Could not cast to Map!");
|
||||||
}
|
}
|
||||||
|
@ -139,8 +123,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
rfl::Result<T> use_custom_constructor(const InputVarType& _var
|
rfl::Result<T> use_custom_constructor(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()); }
|
||||||
|
|
|
@ -39,13 +39,9 @@ namespace rfl {
|
||||||
|
|
||||||
~Writer() = default;
|
~Writer() = default;
|
||||||
|
|
||||||
OutputArrayType array_as_root(const size_t _size) const noexcept {
|
OutputArrayType array_as_root(const size_t _size) const noexcept { return new_array(); }
|
||||||
return new_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputObjectType object_as_root(const size_t _size) const noexcept {
|
OutputObjectType object_as_root(const size_t _size) const noexcept { return new_object(); }
|
||||||
return new_object();
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputVarType null_as_root() const noexcept {
|
OutputVarType null_as_root() const noexcept {
|
||||||
fbb_->Null();
|
fbb_->Null();
|
||||||
|
@ -57,47 +53,42 @@ namespace rfl {
|
||||||
return insert_value(_var);
|
return insert_value(_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType add_array_to_array(
|
OutputArrayType add_array_to_array(const size_t _size, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) const noexcept {
|
||||||
return new_array(_name);
|
return new_array(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType add_object_to_array(
|
OutputObjectType add_object_to_array(const size_t _size, OutputArrayType* _parent)
|
||||||
const size_t _size,
|
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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) const noexcept {
|
||||||
return new_object(_name);
|
return new_object(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|
||||||
return insert_value(_var);
|
return insert_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
|
OutputObjectType* _parent
|
||||||
) const noexcept {
|
) const noexcept {
|
||||||
return insert_value(_name, _var);
|
return insert_value(_name, _var);
|
||||||
}
|
}
|
||||||
|
@ -107,10 +98,8 @@ namespace rfl {
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputVarType add_null_to_object(
|
OutputVarType add_null_to_object(const std::string_view& _name, OutputObjectType* _parent)
|
||||||
const std::string_view& _name,
|
const noexcept {
|
||||||
OutputObjectType* _parent
|
|
||||||
) const noexcept {
|
|
||||||
fbb_->Null(_name.data());
|
fbb_->Null(_name.data());
|
||||||
return OutputVarType {};
|
return OutputVarType {};
|
||||||
}
|
}
|
||||||
|
@ -119,14 +108,11 @@ namespace rfl {
|
||||||
fbb_->EndVector(_arr->start_, false, false);
|
fbb_->EndVector(_arr->start_, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_object(OutputObjectType* _obj) const noexcept {
|
void end_object(OutputObjectType* _obj) const noexcept { fbb_->EndMap(_obj->start_); }
|
||||||
fbb_->EndMap(_obj->start_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T>
|
template <class T>
|
||||||
OutputVarType insert_value(const std::string_view& _name, const T& _var)
|
OutputVarType insert_value(const std::string_view& _name, 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>()) {
|
||||||
|
@ -159,23 +145,22 @@ namespace rfl {
|
||||||
|
|
||||||
OutputArrayType new_array(const std::string_view& _name) const noexcept {
|
OutputArrayType new_array(const std::string_view& _name) const noexcept {
|
||||||
const auto start = fbb_->StartVector(_name.data());
|
const auto start = fbb_->StartVector(_name.data());
|
||||||
return OutputArrayType {start};
|
return OutputArrayType { start };
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputArrayType new_array() const noexcept {
|
OutputArrayType new_array() const noexcept {
|
||||||
const auto start = fbb_->StartVector();
|
const auto start = fbb_->StartVector();
|
||||||
return OutputArrayType {start};
|
return OutputArrayType { start };
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType new_object(const std::string_view& _name
|
OutputObjectType new_object(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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputObjectType new_object() const noexcept {
|
OutputObjectType new_object() const noexcept {
|
||||||
const auto start = fbb_->StartMap();
|
const auto start = fbb_->StartMap();
|
||||||
return OutputObjectType {start};
|
return OutputObjectType { start };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -10,9 +10,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
Result<T> load(const std::string& _fname) {
|
Result<T> load(const std::string& _fname) {
|
||||||
const auto read_bytes = [](const auto& _bytes) {
|
const auto read_bytes = [](const auto& _bytes) { return read<T, Ps...>(_bytes); };
|
||||||
return read<T, Ps...>(_bytes);
|
|
||||||
};
|
|
||||||
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
return rfl::io::load_bytes(_fname).and_then(read_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace rfl {
|
||||||
template <class T, class... Ps>
|
template <class T, class... Ps>
|
||||||
auto read(const char* _bytes, const size_t _size) {
|
auto read(const char* _bytes, const size_t _size) {
|
||||||
const InputVarType root =
|
const InputVarType root =
|
||||||
flexbuffers::GetRoot(reinterpret_cast<const uint8_t*>(_bytes), _size);
|
flexbuffers::GetRoot(reinterpret_cast<const uint8_t*>(_bytes), _size);
|
||||||
return read<T, Ps...>(root);
|
return read<T, Ps...>(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,7 @@ namespace rfl {
|
||||||
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(
|
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root {});
|
||||||
w, _obj, typename ParentType::Root {}
|
|
||||||
);
|
|
||||||
fbb->Finish();
|
fbb->Finish();
|
||||||
return fbb->GetBuffer();
|
return fbb->GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,8 @@ 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<
|
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>, RequiredType>()) {
|
||||||
std::remove_cvref_t<NamedTupleType>,
|
return from_named_tuple<T>(RequiredType(std::forward<NamedTupleType>(_n)));
|
||||||
RequiredType>()) {
|
|
||||||
return from_named_tuple<T>(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);
|
||||||
|
@ -40,9 +37,7 @@ 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<
|
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>, 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);
|
||||||
|
|
|
@ -33,9 +33,7 @@ namespace rfl {
|
||||||
/// Gets a field by name.
|
/// Gets a field by name.
|
||||||
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.
|
||||||
|
|
|
@ -11,8 +11,7 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using field_tuple_t =
|
using field_tuple_t = typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
|
||||||
typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -29,25 +29,21 @@ namespace rfl::internal {
|
||||||
/// Gets a field by name.
|
/// Gets a field by name.
|
||||||
template <StringLiteral _field_name>
|
template <StringLiteral _field_name>
|
||||||
static inline auto& get(NamedTupleType& _tup) {
|
static inline auto& get(NamedTupleType& _tup) {
|
||||||
constexpr auto index =
|
constexpr auto index = find_index<_field_name, typename NamedTupleType::Fields>();
|
||||||
find_index<_field_name, typename NamedTupleType::Fields>();
|
|
||||||
return Getter<NamedTupleType>::template get<index>(_tup);
|
return Getter<NamedTupleType>::template get<index>(_tup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a field by the field type.
|
/// Gets a field by the field type.
|
||||||
template <class Field>
|
template <class Field>
|
||||||
static inline auto& get(NamedTupleType& _tup) {
|
static inline auto& get(NamedTupleType& _tup) {
|
||||||
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<
|
std::is_same<
|
||||||
typename std::tuple_element<
|
typename std::tuple_element<index, typename NamedTupleType::Fields>::type::Type,
|
||||||
index,
|
typename Field::Type>(),
|
||||||
typename NamedTupleType::Fields>::type::Type,
|
"If two fields have the same name, "
|
||||||
typename Field::Type>(),
|
"their type must be the same as "
|
||||||
"If two fields have the same name, "
|
"well."
|
||||||
"their type must be the same as "
|
|
||||||
"well."
|
|
||||||
);
|
);
|
||||||
return Getter<NamedTupleType>::template get<index>(_tup);
|
return Getter<NamedTupleType>::template get<index>(_tup);
|
||||||
}
|
}
|
||||||
|
@ -61,25 +57,21 @@ 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(const NamedTupleType& _tup) {
|
static inline const auto& get_const(const NamedTupleType& _tup) {
|
||||||
constexpr auto index =
|
constexpr auto index = find_index<_field_name, typename NamedTupleType::Fields>();
|
||||||
find_index<_field_name, typename NamedTupleType::Fields>();
|
|
||||||
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(const NamedTupleType& _tup) {
|
static inline const auto& get_const(const NamedTupleType& _tup) {
|
||||||
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<
|
std::is_same<
|
||||||
typename std::tuple_element<
|
typename std::tuple_element<index, typename NamedTupleType::Fields>::type::Type,
|
||||||
index,
|
typename Field::Type>(),
|
||||||
typename NamedTupleType::Fields>::type::Type,
|
"If two fields have the same name, "
|
||||||
typename Field::Type>(),
|
"their type must be the same as "
|
||||||
"If two fields have the same name, "
|
"well."
|
||||||
"their type must be the same as "
|
|
||||||
"well."
|
|
||||||
);
|
);
|
||||||
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
||||||
}
|
}
|
||||||
|
@ -123,9 +115,7 @@ 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);
|
||||||
|
@ -135,9 +125,7 @@ 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);
|
||||||
|
@ -147,9 +135,7 @@ 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);
|
||||||
|
|
|
@ -19,11 +19,15 @@ namespace rfl {
|
||||||
/// Returns the underlying value.
|
/// Returns the underlying value.
|
||||||
template <class F>
|
template <class F>
|
||||||
const T& value(const F& _f) {
|
const T& value(const F& _f) {
|
||||||
if (flag_.test()) { return value_; }
|
if (flag_.test()) {
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(mtx_);
|
std::lock_guard<std::mutex> guard(mtx_);
|
||||||
|
|
||||||
if (flag_.test()) { return value_; }
|
if (flag_.test()) {
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
_f(&value_);
|
_f(&value_);
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ namespace rfl::internal {
|
||||||
|
|
||||||
Skip(const Type& _value) : value_(_value) {}
|
Skip(const Type& _value) : value_(_value) {}
|
||||||
|
|
||||||
Skip(ReflectionType&& _value) noexcept
|
Skip(ReflectionType&& _value) noexcept : value_(_value ? std::move(*_value) : Type()) {}
|
||||||
: value_(_value ? std::move(*_value) : Type()) {}
|
|
||||||
|
|
||||||
Skip(const ReflectionType& _value) : value_(_value ? *_value : Type()) {}
|
Skip(const ReflectionType& _value) : value_(_value ? *_value : Type()) {}
|
||||||
|
|
||||||
|
@ -39,31 +38,23 @@ 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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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 <
|
template <
|
||||||
class U,
|
class U,
|
||||||
bool _skip_s,
|
bool _skip_s,
|
||||||
bool _skip_d,
|
bool _skip_d,
|
||||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
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 <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
Skip(const Default& _default) : value_(Type()) {}
|
Skip(const Default& _default) : value_(Type()) {}
|
||||||
|
|
||||||
~Skip() = default;
|
~Skip() = default;
|
||||||
|
@ -93,10 +84,7 @@ namespace rfl::internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the underlying object.
|
/// Assigns the underlying object.
|
||||||
template <
|
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type = true>
|
||||||
class U,
|
|
||||||
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;
|
||||||
|
@ -104,9 +92,8 @@ namespace rfl::internal {
|
||||||
|
|
||||||
/// Assigns the underlying object to its default value.
|
/// Assigns the underlying object to its default value.
|
||||||
template <
|
template <
|
||||||
class U = Type,
|
class U = Type,
|
||||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
typename std::enable_if<std::is_default_constructible_v<U>, bool>::type = true>
|
||||||
type = true>
|
|
||||||
auto& operator=(const Default& _default) {
|
auto& operator=(const Default& _default) {
|
||||||
value_ = Type();
|
value_ = Type();
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -14,13 +14,11 @@ namespace rfl {
|
||||||
/// for the parameters names in the NamedTuples.
|
/// for the parameters names in the NamedTuples.
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct StringLiteral {
|
struct StringLiteral {
|
||||||
constexpr StringLiteral(const auto... _chars) : arr_ {_chars..., '\0'} {}
|
constexpr StringLiteral(const auto... _chars) : arr_ { _chars..., '\0' } {}
|
||||||
|
|
||||||
constexpr StringLiteral(const std::array<char, N> _arr) : arr_(_arr) {}
|
constexpr StringLiteral(const std::array<char, N> _arr) : arr_(_arr) {}
|
||||||
|
|
||||||
constexpr StringLiteral(const char (&_str)[N]) {
|
constexpr StringLiteral(const char (&_str)[N]) { std::copy_n(_str, N, std::data(arr_)); }
|
||||||
std::copy_n(_str, N, std::data(arr_));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the value as a string.
|
/// Returns the value as a string.
|
||||||
std::string str() const { return std::string(std::data(arr_), N - 1); }
|
std::string str() const { return std::string(std::data(arr_), N - 1); }
|
||||||
|
@ -34,10 +32,8 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t N1, size_t N2>
|
template <size_t N1, size_t N2>
|
||||||
constexpr inline bool operator==(
|
constexpr inline bool
|
||||||
const StringLiteral<N1>& _first,
|
operator==(const StringLiteral<N1>& _first, const StringLiteral<N2>& _second) {
|
||||||
const StringLiteral<N2>& _second
|
|
||||||
) {
|
|
||||||
if constexpr (N1 != N2) {
|
if constexpr (N1 != N2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -45,10 +41,8 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N1, size_t N2>
|
template <size_t N1, size_t N2>
|
||||||
constexpr inline bool operator!=(
|
constexpr inline bool
|
||||||
const StringLiteral<N1>& _first,
|
operator!=(const StringLiteral<N1>& _first, const StringLiteral<N2>& _second) {
|
||||||
const StringLiteral<N2>& _second
|
|
||||||
) {
|
|
||||||
return !(_first == _second);
|
return !(_first == _second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ 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
|
static inline auto visit(const auto& _v, const int _i, const Args&... _args) {
|
||||||
visit(const auto& _v, const int _i, const Args&... _args) {
|
|
||||||
static_assert(_end > _begin, "_end needs to be greater than _begin.");
|
static_assert(_end > _begin, "_end needs to be greater than _begin.");
|
||||||
if constexpr (_end - _begin == 1) {
|
if constexpr (_end - _begin == 1) {
|
||||||
return _v.template visit<_begin>(_args...);
|
return _v.template visit<_begin>(_args...);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -13,23 +13,18 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class FieldNames, class... Fields>
|
template <class FieldNames, class... Fields>
|
||||||
auto copy_flattened_tuple_to_named_tuple(
|
auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple, Fields&&... _fields) {
|
||||||
const auto& _flattened_tuple,
|
constexpr auto size = std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
|
||||||
Fields&&... _fields
|
constexpr auto i = sizeof...(_fields);
|
||||||
) {
|
|
||||||
constexpr auto size =
|
|
||||||
std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
|
|
||||||
constexpr auto i = sizeof...(_fields);
|
|
||||||
if constexpr (i == size) {
|
if constexpr (i == size) {
|
||||||
return make_named_tuple(std::move(_fields)...);
|
return make_named_tuple(std::move(_fields)...);
|
||||||
} else {
|
} else {
|
||||||
const auto name_literal = FieldNames::template name_of<i>();
|
const auto name_literal = FieldNames::template name_of<i>();
|
||||||
auto new_field = rfl::make_field<
|
auto new_field = rfl::make_field<lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
||||||
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
std::get<i>(_flattened_tuple)
|
||||||
std::get<i>(_flattened_tuple)
|
|
||||||
);
|
);
|
||||||
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
||||||
_flattened_tuple, std::move(_fields)..., std::move(new_field)
|
_flattened_tuple, std::move(_fields)..., std::move(new_field)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,9 @@ namespace rfl {
|
||||||
struct define_literal;
|
struct define_literal;
|
||||||
|
|
||||||
/// General case
|
/// General case
|
||||||
template <
|
template <StringLiteral... _content1, StringLiteral... _content2, class... Tail>
|
||||||
StringLiteral... _content1,
|
struct define_literal<Literal<_content1...>, Literal<_content2...>, Tail...> {
|
||||||
StringLiteral... _content2,
|
using type = typename define_literal<Literal<_content1..., _content2...>, Tail...>::type;
|
||||||
class... Tail>
|
|
||||||
struct define_literal<
|
|
||||||
Literal<_content1...>,
|
|
||||||
Literal<_content2...>,
|
|
||||||
Tail...> {
|
|
||||||
using type = typename define_literal<
|
|
||||||
Literal<_content1..., _content2...>,
|
|
||||||
Tail...>::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Special case - only a single literal is left
|
/// Special case - only a single literal is left
|
||||||
|
|
|
@ -20,22 +20,16 @@ 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<
|
using type = typename define_named_tuple<NamedTuple<TupContent..., Head>, 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<
|
struct define_named_tuple<NamedTuple<TupContent...>, NamedTuple<TupContent2...>, Tail...> {
|
||||||
NamedTuple<TupContent...>,
|
using type =
|
||||||
NamedTuple<TupContent2...>,
|
typename define_named_tuple<NamedTuple<TupContent..., TupContent2...>, Tail...>::type;
|
||||||
Tail...> {
|
|
||||||
using type = typename define_named_tuple<
|
|
||||||
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.
|
||||||
|
|
|
@ -13,58 +13,50 @@ namespace rfl {
|
||||||
|
|
||||||
/// Recursive case - both tagged union.
|
/// Recursive case - both tagged union.
|
||||||
template <
|
template <
|
||||||
StringLiteral _discriminator,
|
StringLiteral _discriminator,
|
||||||
class... NamedTupleTypes1,
|
class... NamedTupleTypes1,
|
||||||
class... NamedTupleTypes2,
|
class... NamedTupleTypes2,
|
||||||
class... Tail>
|
class... Tail>
|
||||||
struct define_tagged_union<
|
struct define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
||||||
Tail...> {
|
Tail...> {
|
||||||
using type = typename define_tagged_union<
|
using type = typename define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
|
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
|
||||||
Tail...>::type;
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - tagged union plus named tuple.
|
/// Recursive case - tagged union plus named tuple.
|
||||||
template <
|
template <
|
||||||
StringLiteral _discriminator,
|
StringLiteral _discriminator,
|
||||||
class... NamedTupleTypes,
|
class... NamedTupleTypes,
|
||||||
class... FieldTypes,
|
class... FieldTypes,
|
||||||
class... Tail>
|
class... Tail>
|
||||||
struct define_tagged_union<
|
struct define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
||||||
NamedTuple<FieldTypes...>,
|
NamedTuple<FieldTypes...>,
|
||||||
Tail...> {
|
Tail...> {
|
||||||
using type = typename define_tagged_union<
|
using type = typename define_tagged_union<
|
||||||
_discriminator,
|
_discriminator,
|
||||||
TaggedUnion<
|
TaggedUnion<_discriminator, NamedTupleTypes..., NamedTuple<FieldTypes...>>,
|
||||||
_discriminator,
|
Tail...>::type;
|
||||||
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<
|
struct define_tagged_union<_discriminator, NamedTuple<FieldTypes...>, Tail...> {
|
||||||
_discriminator,
|
|
||||||
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...>>,
|
||||||
Tail...>::type;
|
Tail...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Special case - only a single TaggedUnion is left.
|
/// Special case - only a single TaggedUnion is left.
|
||||||
template <StringLiteral _discriminator, class... NamedTupleTypes>
|
template <StringLiteral _discriminator, class... NamedTupleTypes>
|
||||||
struct define_tagged_union<
|
struct define_tagged_union<_discriminator, TaggedUnion<_discriminator, NamedTupleTypes...>> {
|
||||||
_discriminator,
|
|
||||||
TaggedUnion<_discriminator, NamedTupleTypes...>> {
|
|
||||||
using type = TaggedUnion<_discriminator, NamedTupleTypes...>;
|
using type = TaggedUnion<_discriminator, NamedTupleTypes...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,20 +12,14 @@ 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<
|
struct define_variant<std::variant<Vars1...>, std::variant<Vars2...>, Tail...> {
|
||||||
std::variant<Vars1...>,
|
using type = typename define_variant<std::variant<Vars1..., Vars2...>, Tail...>::type;
|
||||||
std::variant<Vars2...>,
|
|
||||||
Tail...> {
|
|
||||||
using type =
|
|
||||||
typename define_variant<std::variant<Vars1..., Vars2...>, Tail...>::
|
|
||||||
type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - variant plus other type.
|
/// Recursive case - variant plus other type.
|
||||||
template <class... Vars, class Head, class... Tail>
|
template <class... Vars, class Head, class... Tail>
|
||||||
struct define_variant<std::variant<Vars...>, Head, Tail...> {
|
struct define_variant<std::variant<Vars...>, Head, Tail...> {
|
||||||
using type =
|
using type = typename define_variant<std::variant<Vars..., Head>, Tail...>::type;
|
||||||
typename define_variant<std::variant<Vars..., Head>, Tail...>::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Recursive case - other type.
|
/// Recursive case - other type.
|
||||||
|
|
|
@ -26,89 +26,45 @@ namespace rfl {
|
||||||
constexpr static size_t size = N;
|
constexpr static size_t size = N;
|
||||||
|
|
||||||
/// A list of all the possible enums
|
/// A list of all the possible enums
|
||||||
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(
|
static_assert(N == 0 || LiteralType::size() == N, "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 = std::conditional_t<
|
using AddOneType = std::conditional_t<
|
||||||
N == 0,
|
N == 0,
|
||||||
Names<EnumType, NewLiteral, 1, _new_enum>,
|
Names<EnumType, NewLiteral, 1, _new_enum>,
|
||||||
Names<
|
Names<EnumType, define_literal_t<LiteralType, NewLiteral>, N + 1, _enums..., _new_enum>>;
|
||||||
EnumType,
|
|
||||||
define_literal_t<LiteralType, NewLiteral>,
|
|
||||||
N + 1,
|
|
||||||
_enums...,
|
|
||||||
_new_enum>>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <
|
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
|
||||||
class EnumType,
|
auto names_to_enumerator_named_tuple(Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||||
size_t N,
|
return make_named_tuple(Field<_names, EnumType> { _enums }...);
|
||||||
StringLiteral... _names,
|
|
||||||
auto... _enums>
|
|
||||||
auto names_to_enumerator_named_tuple(Names<
|
|
||||||
EnumType,
|
|
||||||
Literal<_names...>,
|
|
||||||
N,
|
|
||||||
_enums...>) {
|
|
||||||
return make_named_tuple(Field<_names, EnumType> {_enums}...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
|
||||||
class EnumType,
|
|
||||||
size_t N,
|
|
||||||
StringLiteral... _names,
|
|
||||||
auto... _enums>
|
|
||||||
auto names_to_underlying_enumerator_named_tuple(Names<
|
auto names_to_underlying_enumerator_named_tuple(Names<
|
||||||
EnumType,
|
EnumType,
|
||||||
Literal<_names...>,
|
Literal<_names...>,
|
||||||
N,
|
N,
|
||||||
_enums...>) {
|
_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 <
|
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
|
||||||
class EnumType,
|
|
||||||
size_t N,
|
|
||||||
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<
|
names_to_enumerator_array(Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||||
EnumType,
|
return { std::make_pair(LiteralHelper<_names>::field_.string_view(), _enums)... };
|
||||||
Literal<_names...>,
|
|
||||||
N,
|
|
||||||
_enums...>) {
|
|
||||||
return {std::make_pair(
|
|
||||||
LiteralHelper<_names>::field_.string_view(), _enums
|
|
||||||
)...};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
|
||||||
class EnumType,
|
constexpr std::array<std::pair<std::string_view, std::underlying_type_t<EnumType>>, N>
|
||||||
size_t N,
|
names_to_underlying_enumerator_array(Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||||
StringLiteral... _names,
|
return { std::make_pair(
|
||||||
auto... _enums>
|
LiteralHelper<_names>::field_.string_view(),
|
||||||
constexpr std::array<
|
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
||||||
std::pair<std::string_view, std::underlying_type_t<EnumType>>,
|
)... };
|
||||||
N>
|
|
||||||
names_to_underlying_enumerator_array(Names<
|
|
||||||
EnumType,
|
|
||||||
Literal<_names...>,
|
|
||||||
N,
|
|
||||||
_enums...>) {
|
|
||||||
return {std::make_pair(
|
|
||||||
LiteralHelper<_names>::field_.string_view(),
|
|
||||||
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
|
||||||
)...};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
|
|
|
@ -23,8 +23,7 @@ namespace rfl {
|
||||||
public:
|
public:
|
||||||
static constexpr bool is_flag_enum_ = is_flag_enum<EnumType>;
|
static constexpr bool is_flag_enum_ = is_flag_enum<EnumType>;
|
||||||
|
|
||||||
static constexpr auto names_ =
|
static constexpr auto names_ = get_enum_names<EnumType, is_flag_enum_>();
|
||||||
get_enum_names<EnumType, is_flag_enum_>();
|
|
||||||
|
|
||||||
using NamesLiteral = typename decltype(names_)::Literal;
|
using NamesLiteral = typename decltype(names_)::Literal;
|
||||||
|
|
||||||
|
@ -41,9 +40,9 @@ namespace rfl {
|
||||||
/// Transforms a string to the matching enum.
|
/// Transforms a string to the matching enum.
|
||||||
static Result<EnumType> string_to_enum(const std::string& _str) {
|
static Result<EnumType> string_to_enum(const std::string& _str) {
|
||||||
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);
|
||||||
|
@ -63,9 +62,7 @@ namespace rfl {
|
||||||
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;
|
||||||
|
@ -81,17 +78,13 @@ 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)
|
||||||
)
|
.value();
|
||||||
.transform(to_str)
|
|
||||||
.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.
|
||||||
|
@ -102,8 +95,7 @@ namespace rfl {
|
||||||
/// This assumes that _enum can be exactly matched to one of the names
|
/// This assumes that _enum can be exactly matched to one of the names
|
||||||
/// and does not have to be combined using |.
|
/// and does not have to be combined using |.
|
||||||
static Result<EnumType> single_string_to_enum(const std::string& _str) {
|
static Result<EnumType> single_string_to_enum(const std::string& _str) {
|
||||||
const auto r =
|
const auto r = NamesLiteral::from_string(_str).transform(literal_to_enum);
|
||||||
NamesLiteral::from_string(_str).transform(literal_to_enum);
|
|
||||||
if (r) {
|
if (r) {
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,8 +107,7 @@ 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(const std::string& _str
|
static Result<EnumType> string_to_flag_enum(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);
|
||||||
|
|
|
@ -45,10 +45,9 @@ namespace rfl {
|
||||||
// for Clang on Windows. For all other compilers, function_name works as
|
// for Clang on Windows. For all other compilers, function_name works as
|
||||||
// intended.
|
// intended.
|
||||||
#if defined(__clang__) && defined(_MSC_VER)
|
#if defined(__clang__) && defined(_MSC_VER)
|
||||||
const auto func_name = std::string_view {__PRETTY_FUNCTION__};
|
const auto func_name = std::string_view { __PRETTY_FUNCTION__ };
|
||||||
#else
|
#else
|
||||||
const auto func_name =
|
const auto func_name = std::string_view { std::source_location::current().function_name() };
|
||||||
std::string_view {std::source_location::current().function_name()};
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto split = func_name.substr(0, func_name.size() - 1);
|
const auto split = func_name.substr(0, func_name.size() - 1);
|
||||||
|
@ -61,18 +60,18 @@ namespace rfl {
|
||||||
return split.substr(split.find("get_enum_name_str_view<") + 23);
|
return split.substr(split.find("get_enum_name_str_view<") + 23);
|
||||||
#else
|
#else
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto e>
|
template <auto e>
|
||||||
consteval auto get_enum_name() {
|
consteval auto get_enum_name() {
|
||||||
constexpr auto name = get_enum_name_str_view<e>();
|
constexpr auto name = get_enum_name_str_view<e>();
|
||||||
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()> {});
|
||||||
}
|
}
|
||||||
|
@ -91,9 +90,8 @@ namespace rfl {
|
||||||
if constexpr (_is_flag) {
|
if constexpr (_is_flag) {
|
||||||
return calc_greatest_power_of_two<T>();
|
return calc_greatest_power_of_two<T>();
|
||||||
} else {
|
} else {
|
||||||
return std::numeric_limits<T>::max() > 127
|
return std::numeric_limits<T>::max() > 127 ? static_cast<T>(127)
|
||||||
? static_cast<T>(127)
|
: std::numeric_limits<T>::max();
|
||||||
: std::numeric_limits<T>::max();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,12 +104,7 @@ namespace rfl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <class EnumType, class NamesType, auto _max, bool _is_flag, int _i>
|
||||||
class EnumType,
|
|
||||||
class NamesType,
|
|
||||||
auto _max,
|
|
||||||
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>;
|
||||||
|
|
||||||
|
@ -123,27 +116,16 @@ namespace rfl {
|
||||||
if constexpr (j == _max) {
|
if constexpr (j == _max) {
|
||||||
return NamesType {};
|
return NamesType {};
|
||||||
} else {
|
} else {
|
||||||
return get_enum_names_impl<
|
return get_enum_names_impl<EnumType, NamesType, _max, _is_flag, _i + 1>();
|
||||||
EnumType,
|
|
||||||
NamesType,
|
|
||||||
_max,
|
|
||||||
_is_flag,
|
|
||||||
_i + 1>();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
using NewNames = typename NamesType::template AddOneType<
|
using NewNames = typename NamesType::
|
||||||
Literal<remove_namespaces<name>()>,
|
template AddOneType<Literal<remove_namespaces<name>()>, static_cast<EnumType>(j)>;
|
||||||
static_cast<EnumType>(j)>;
|
|
||||||
|
|
||||||
if constexpr (j == _max) {
|
if constexpr (j == _max) {
|
||||||
return NewNames {};
|
return NewNames {};
|
||||||
} else {
|
} else {
|
||||||
return get_enum_names_impl<
|
return get_enum_names_impl<EnumType, NewNames, _max, _is_flag, _i + 1>();
|
||||||
EnumType,
|
|
||||||
NewNames,
|
|
||||||
_max,
|
|
||||||
_is_flag,
|
|
||||||
_i + 1>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,18 +133,17 @@ namespace rfl {
|
||||||
template <class EnumType, bool _is_flag>
|
template <class EnumType, bool _is_flag>
|
||||||
consteval auto get_enum_names() {
|
consteval auto get_enum_names() {
|
||||||
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(
|
static_assert(
|
||||||
std::is_integral_v<std::underlying_type_t<EnumType>>,
|
std::is_integral_v<std::underlying_type_t<EnumType>>,
|
||||||
"The underlying type of any Enum must be integral!"
|
"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>();
|
|
||||||
|
|
||||||
using EmptyNames = Names<EnumType, rfl::Literal<"">, 0>;
|
using EmptyNames = Names<EnumType, rfl::Literal<"">, 0>;
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,9 @@ namespace rfl {
|
||||||
namespace enums {
|
namespace enums {
|
||||||
|
|
||||||
template <class EnumType>
|
template <class EnumType>
|
||||||
concept is_flag_enum =
|
concept is_flag_enum = is_scoped_enum<EnumType> && requires(EnumType e1, EnumType e2) {
|
||||||
is_scoped_enum<EnumType> && requires(EnumType e1, EnumType e2) {
|
{ e1 | e2 } -> std::same_as<EnumType>;
|
||||||
{ e1 | e2 } -> std::same_as<EnumType>;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -9,9 +9,8 @@ namespace rfl {
|
||||||
namespace enums {
|
namespace enums {
|
||||||
|
|
||||||
template <class EnumType>
|
template <class EnumType>
|
||||||
concept is_scoped_enum =
|
concept is_scoped_enum = std::is_enum_v<EnumType> &&
|
||||||
std::is_enum_v<EnumType> &&
|
!std::is_convertible_v<EnumType, std::underlying_type_t<EnumType>>;
|
||||||
!std::is_convertible_v<EnumType, std::underlying_type_t<EnumType>>;
|
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -14,10 +14,9 @@ namespace rfl {
|
||||||
struct extract_discriminators;
|
struct extract_discriminators;
|
||||||
|
|
||||||
template <StringLiteral _discriminator, class... NamedTupleType>
|
template <StringLiteral _discriminator, class... NamedTupleType>
|
||||||
struct extract_discriminators<
|
struct extract_discriminators<TaggedUnion<_discriminator, NamedTupleType...>> {
|
||||||
TaggedUnion<_discriminator, NamedTupleType...>> {
|
using type =
|
||||||
using type = define_literal_t<
|
define_literal_t<std::remove_cvref_t<field_type_t<_discriminator, NamedTupleType>>...>;
|
||||||
std::remove_cvref_t<field_type_t<_discriminator, NamedTupleType>>...>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -11,8 +11,7 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using field_tuple_t =
|
using field_tuple_t = typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
|
||||||
typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -27,24 +27,19 @@ namespace rfl {
|
||||||
using NamedTupleType = named_tuple_t<T>;
|
using NamedTupleType = named_tuple_t<T>;
|
||||||
|
|
||||||
static constexpr int field_ix_ =
|
static constexpr int field_ix_ =
|
||||||
internal::find_index<_field_name, typename NamedTupleType::Fields>();
|
internal::find_index<_field_name, typename NamedTupleType::Fields>();
|
||||||
|
|
||||||
using Type = typename std::
|
using Type =
|
||||||
tuple_element<field_ix_, typename NamedTupleType::Fields>::type::Type;
|
typename std::tuple_element<field_ix_, typename NamedTupleType::Fields>::type::Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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 <
|
template <StringLiteral _field_name, class FirstAlternativeType, class... OtherAlternativeTypes>
|
||||||
StringLiteral _field_name,
|
struct FieldType<_field_name, std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
|
||||||
class FirstAlternativeType,
|
|
||||||
class... OtherAlternativeTypes>
|
|
||||||
struct FieldType<
|
|
||||||
_field_name,
|
|
||||||
std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
|
|
||||||
constexpr static bool all_types_match = std::conjunction_v<std::is_same<
|
constexpr static bool all_types_match = std::conjunction_v<std::is_same<
|
||||||
typename FieldType<_field_name, FirstAlternativeType>::Type,
|
typename FieldType<_field_name, FirstAlternativeType>::Type,
|
||||||
typename FieldType<_field_name, OtherAlternativeTypes>::Type>...>;
|
typename FieldType<_field_name, OtherAlternativeTypes>::Type>...>;
|
||||||
|
|
||||||
static_assert(all_types_match, "All field types must be the same.");
|
static_assert(all_types_match, "All field types must be the same.");
|
||||||
|
|
||||||
|
@ -52,17 +47,11 @@ namespace rfl {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// For tagged union - just defers to the variant.
|
/// For tagged union - just defers to the variant.
|
||||||
template <
|
template <StringLiteral _field_name, StringLiteral _discriminator_name, class... VarTypes>
|
||||||
StringLiteral _field_name,
|
struct FieldType<_field_name, TaggedUnion<_discriminator_name, VarTypes...>> {
|
||||||
StringLiteral _discriminator_name,
|
|
||||||
class... 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, VarTypes...>::VariantType>::
|
typename TaggedUnion<_discriminator_name, VarTypes...>::VariantType>::Type;
|
||||||
Type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -12,8 +12,7 @@ namespace rfl {
|
||||||
/// Finds the index of the field signified by _field_name
|
/// Finds the index of the field signified by _field_name
|
||||||
template <StringLiteral _field_name, class Fields, int I = 0>
|
template <StringLiteral _field_name, class Fields, int I = 0>
|
||||||
constexpr static int find_index() {
|
constexpr static int find_index() {
|
||||||
using FieldType =
|
using FieldType = std::remove_cvref_t<typename std::tuple_element<I, Fields>::type>;
|
||||||
std::remove_cvref_t<typename std::tuple_element<I, Fields>::type>;
|
|
||||||
|
|
||||||
constexpr bool name_i_matches = (FieldType::name_ == _field_name);
|
constexpr bool name_i_matches = (FieldType::name_ == _field_name);
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using flattened_ptr_tuple_t = typename std::
|
using flattened_ptr_tuple_t =
|
||||||
invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
|
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -13,8 +13,7 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using flattened_tuple_t =
|
using flattened_tuple_t = typename remove_ptrs_tup<flattened_ptr_tuple_t<T>>::TupleType;
|
||||||
typename remove_ptrs_tup<flattened_ptr_tuple_t<T>>::TupleType;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace rfl::internal {
|
||||||
// This workaround is necessary for clang.
|
// This workaround is necessary for clang.
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr auto wrap(const T& arg) noexcept {
|
constexpr auto wrap(const T& arg) noexcept {
|
||||||
return Wrapper {arg};
|
return Wrapper { arg };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, auto ptr>
|
template <class T, auto ptr>
|
||||||
|
@ -46,10 +46,9 @@ namespace rfl::internal {
|
||||||
// Clang on Windows. For all other compilers, function_name works as
|
// Clang on Windows. For all other compilers, function_name works as
|
||||||
// intended.
|
// intended.
|
||||||
#if defined(__clang__) && defined(_MSC_VER)
|
#if defined(__clang__) && defined(_MSC_VER)
|
||||||
const auto func_name = std::string_view {__PRETTY_FUNCTION__};
|
const auto func_name = std::string_view { __PRETTY_FUNCTION__ };
|
||||||
#else
|
#else
|
||||||
const auto func_name =
|
const auto func_name = std::string_view { std::source_location::current().function_name() };
|
||||||
std::string_view {std::source_location::current().function_name()};
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto split = func_name.substr(0, func_name.size() - 2);
|
const auto split = func_name.substr(0, func_name.size() - 2);
|
||||||
|
@ -62,9 +61,9 @@ namespace rfl::internal {
|
||||||
return split.substr(split.rfind("->") + 2);
|
return split.substr(split.rfind("->") + 2);
|
||||||
#else
|
#else
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,7 @@ namespace rfl::internal {
|
||||||
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()> {});
|
||||||
}
|
}
|
||||||
|
@ -84,8 +83,8 @@ namespace rfl::internal {
|
||||||
template <class T, auto ptr>
|
template <class T, auto ptr>
|
||||||
auto get_field_name() {
|
auto get_field_name() {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
using Type = std::remove_cvref_t<std::remove_pointer_t<
|
using Type = std::remove_cvref_t<
|
||||||
typename std::remove_pointer_t<decltype(ptr)>::Type>>;
|
std::remove_pointer_t<typename std::remove_pointer_t<decltype(ptr)>::Type>>;
|
||||||
#else
|
#else
|
||||||
using Type = std::remove_cvref_t<std::remove_pointer_t<decltype(ptr)>>;
|
using Type = std::remove_cvref_t<std::remove_pointer_t<decltype(ptr)>>;
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,8 +100,8 @@ namespace rfl::internal {
|
||||||
|
|
||||||
template <StringLiteral... _names1, StringLiteral... _names2>
|
template <StringLiteral... _names1, StringLiteral... _names2>
|
||||||
auto concat_two_literals(
|
auto concat_two_literals(
|
||||||
const rfl::Literal<_names1...>& _lit1,
|
const rfl::Literal<_names1...>& _lit1,
|
||||||
const rfl::Literal<_names2...>& _lit2
|
const rfl::Literal<_names2...>& _lit2
|
||||||
) {
|
) {
|
||||||
return rfl::Literal<_names1..., _names2...>::template from_value<0>();
|
return rfl::Literal<_names1..., _names2...>::template from_value<0>();
|
||||||
}
|
}
|
||||||
|
@ -138,17 +137,13 @@ 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<
|
get_field_name<Type, wrap(std::get<Is>(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, std::get<Is>(bind_fake_object_to_tuple<T>())>(
|
||||||
get_field_name<Type, 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>>());
|
||||||
|
|
|
@ -15,15 +15,13 @@ namespace rfl {
|
||||||
auto get_meta_fields(AlreadyExtracted&&... _already_extracted) {
|
auto get_meta_fields(AlreadyExtracted&&... _already_extracted) {
|
||||||
constexpr size_t i = sizeof...(_already_extracted);
|
constexpr size_t i = sizeof...(_already_extracted);
|
||||||
if constexpr (NamedTupleType::size() == i) {
|
if constexpr (NamedTupleType::size() == i) {
|
||||||
return std::array<MetaField, i> {std::move(_already_extracted)...};
|
return std::array<MetaField, i> { std::move(_already_extracted)... };
|
||||||
} else {
|
} else {
|
||||||
using FieldType =
|
using FieldType = std::tuple_element_t<i, typename NamedTupleType::Fields>;
|
||||||
std::tuple_element_t<i, typename NamedTupleType::Fields>;
|
auto name = typename FieldType::Name().str();
|
||||||
auto name = typename FieldType::Name().str();
|
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))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,9 @@ namespace rfl {
|
||||||
// Clang on Windows. For all other compilers, function_name works as
|
// Clang on Windows. For all other compilers, function_name works as
|
||||||
// intended.
|
// intended.
|
||||||
#if defined(__clang__) && defined(_MSC_VER)
|
#if defined(__clang__) && defined(_MSC_VER)
|
||||||
const auto func_name = std::string_view {__PRETTY_FUNCTION__};
|
const auto func_name = std::string_view { __PRETTY_FUNCTION__ };
|
||||||
#else
|
#else
|
||||||
const auto func_name =
|
const auto func_name = std::string_view { std::source_location::current().function_name() };
|
||||||
std::string_view {std::source_location::current().function_name()};
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto split = func_name.substr(0, func_name.size() - 1);
|
const auto split = func_name.substr(0, func_name.size() - 1);
|
||||||
|
@ -35,22 +34,19 @@ namespace rfl {
|
||||||
return split;
|
return split;
|
||||||
#else
|
#else
|
||||||
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(
|
static_assert(get_type_name_str_view<int>() == "int", "Expected 'int', got something else.");
|
||||||
get_type_name_str_view<int>() == "int",
|
|
||||||
"Expected 'int', got something else."
|
|
||||||
);
|
|
||||||
constexpr auto name = get_type_name_str_view<T>();
|
constexpr auto name = get_type_name_str_view<T>();
|
||||||
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()> {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,7 @@ namespace rfl {
|
||||||
} else {
|
} else {
|
||||||
using T = std::remove_cvref_t<std::tuple_element_t<_i, TupleType>>;
|
using T = std::remove_cvref_t<std::tuple_element_t<_i, TupleType>>;
|
||||||
if constexpr (is_flatten_field_v<T>) {
|
if constexpr (is_flatten_field_v<T>) {
|
||||||
return all_fields_or_flatten<
|
return all_fields_or_flatten<ptr_tuple_t<typename std::remove_pointer_t<T>::Type>>() &&
|
||||||
ptr_tuple_t<typename std::remove_pointer_t<T>::Type>>() &&
|
|
||||||
all_fields_or_flatten<TupleType, _i + 1>();
|
all_fields_or_flatten<TupleType, _i + 1>();
|
||||||
} else {
|
} else {
|
||||||
return is_field_v<T> && all_fields_or_flatten<TupleType, _i + 1>();
|
return is_field_v<T> && all_fields_or_flatten<TupleType, _i + 1>();
|
||||||
|
@ -36,8 +35,7 @@ namespace rfl {
|
||||||
} else {
|
} else {
|
||||||
using T = std::remove_cvref_t<std::tuple_element_t<_i, TupleType>>;
|
using T = std::remove_cvref_t<std::tuple_element_t<_i, TupleType>>;
|
||||||
if constexpr (is_flatten_field_v<T>) {
|
if constexpr (is_flatten_field_v<T>) {
|
||||||
return some_fields_or_flatten<
|
return some_fields_or_flatten<ptr_tuple_t<typename std::remove_pointer_t<T>::Type>>() ||
|
||||||
ptr_tuple_t<typename std::remove_pointer_t<T>::Type>>() ||
|
|
||||||
some_fields_or_flatten<TupleType, _i + 1>();
|
some_fields_or_flatten<TupleType, _i + 1>();
|
||||||
} else {
|
} else {
|
||||||
return is_field_v<T> || some_fields_or_flatten<TupleType, _i + 1>();
|
return is_field_v<T> || some_fields_or_flatten<TupleType, _i + 1>();
|
||||||
|
@ -53,11 +51,11 @@ namespace rfl {
|
||||||
using TupleType = ptr_tuple_t<T>;
|
using TupleType = ptr_tuple_t<T>;
|
||||||
if constexpr (some_fields_or_flatten<TupleType>()) {
|
if constexpr (some_fields_or_flatten<TupleType>()) {
|
||||||
static_assert(
|
static_assert(
|
||||||
all_fields_or_flatten<TupleType>(),
|
all_fields_or_flatten<TupleType>(),
|
||||||
"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 {
|
||||||
|
|
|
@ -7,15 +7,13 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename Wrapper>
|
template <typename Wrapper>
|
||||||
using reflection_method_t =
|
using reflection_method_t = decltype(std::declval<const Wrapper>().reflection());
|
||||||
decltype(std::declval<const Wrapper>().reflection());
|
|
||||||
|
|
||||||
template <typename Wrapper, typename = std::void_t<>>
|
template <typename Wrapper, typename = std::void_t<>>
|
||||||
struct has_refl_m : std::false_type {};
|
struct has_refl_m : std::false_type {};
|
||||||
|
|
||||||
template <typename Wrapper>
|
template <typename Wrapper>
|
||||||
struct has_refl_m<Wrapper, std::void_t<reflection_method_t<Wrapper>>>
|
struct has_refl_m<Wrapper, std::void_t<reflection_method_t<Wrapper>>> : std::true_type {};
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
/// Utility parameter for named tuple parsing, can be used by the
|
/// Utility parameter for named tuple parsing, can be used by the
|
||||||
/// parsers to determine whether a class or struct has a method
|
/// parsers to determine whether a class or struct has a method
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace rfl {
|
||||||
static std::int32_t foo(typename U::ReflectionType*);
|
static std::int32_t foo(typename U::ReflectionType*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool value =
|
static constexpr bool value = sizeof(foo<Wrapper>(nullptr)) == sizeof(std::int32_t);
|
||||||
sizeof(foo<Wrapper>(nullptr)) == sizeof(std::int32_t);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Utility parameter for named tuple parsing, can be used by the
|
/// Utility parameter for named tuple parsing, can be used by the
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace rfl {
|
||||||
static std::int32_t foo(typename U::Tag*);
|
static std::int32_t foo(typename U::Tag*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool value =
|
static constexpr bool value = sizeof(foo<Wrapper>(nullptr)) == sizeof(std::int32_t);
|
||||||
sizeof(foo<Wrapper>(nullptr)) == sizeof(std::int32_t);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Used for tagged unions - determines whether a struct as a Tag.
|
/// Used for tagged unions - determines whether a struct as a Tag.
|
||||||
|
|
|
@ -7,15 +7,13 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename Wrapper>
|
template <typename Wrapper>
|
||||||
using to_class_method_t =
|
using to_class_method_t = decltype(std::declval<const Wrapper>().to_class());
|
||||||
decltype(std::declval<const Wrapper>().to_class());
|
|
||||||
|
|
||||||
template <typename Wrapper, typename = std::void_t<>>
|
template <typename Wrapper, typename = std::void_t<>>
|
||||||
struct has_to_class_m : std::false_type {};
|
struct has_to_class_m : std::false_type {};
|
||||||
|
|
||||||
template <typename Wrapper>
|
template <typename Wrapper>
|
||||||
struct has_to_class_m<Wrapper, std::void_t<to_class_method_t<Wrapper>>>
|
struct has_to_class_m<Wrapper, std::void_t<to_class_method_t<Wrapper>>> : std::true_type {};
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
/// Utility parameter for named tuple parsing, can be used by the
|
/// Utility parameter for named tuple parsing, can be used by the
|
||||||
/// parsers to determine whether a class or struct has a method
|
/// parsers to determine whether a class or struct has a method
|
||||||
|
|
|
@ -19,8 +19,7 @@ namespace rfl::internal {
|
||||||
class is_array<Array<Type>> : public std::true_type {};
|
class is_array<Array<Type>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_array_v =
|
constexpr bool is_array_v = is_array<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_array<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace rfl::internal
|
} // namespace rfl::internal
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_attribute_v =
|
constexpr bool is_attribute_v =
|
||||||
is_attribute<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_attribute<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -8,11 +8,10 @@ namespace rfl {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_basic_type_v =
|
constexpr bool is_basic_type_v = std::is_floating_point_v<std::remove_cvref_t<T>> ||
|
||||||
std::is_floating_point_v<std::remove_cvref_t<T>> ||
|
std::is_integral_v<std::remove_cvref_t<T>> ||
|
||||||
std::is_integral_v<std::remove_cvref_t<T>> ||
|
std::is_same<std::remove_cvref_t<T>, std::string>() ||
|
||||||
std::is_same<std::remove_cvref_t<T>, std::string>() ||
|
std::is_same<std::remove_cvref_t<T>, bool>();
|
||||||
std::is_same<std::remove_cvref_t<T>, bool>();
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_description_v =
|
constexpr bool is_description_v =
|
||||||
is_description<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_description<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -21,8 +21,7 @@ namespace rfl {
|
||||||
class is_field<Field<_name, Type>> : public std::true_type {};
|
class is_field<Field<_name, Type>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_field_v =
|
constexpr bool is_field_v = is_field<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_field<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_flatten_field_v =
|
constexpr bool is_flatten_field_v =
|
||||||
is_flatten_field<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_flatten_field<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -19,8 +19,7 @@ namespace rfl {
|
||||||
class is_literal<Literal<_s...>> : public std::true_type {};
|
class is_literal<Literal<_s...>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_literal_v =
|
constexpr bool is_literal_v = is_literal<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_literal<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_named_tuple_v =
|
constexpr bool is_named_tuple_v =
|
||||||
is_named_tuple<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_named_tuple<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_no_optionals_v =
|
constexpr bool is_no_optionals_v =
|
||||||
is_no_optionals<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_no_optionals<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -19,8 +19,7 @@ namespace rfl {
|
||||||
class is_pattern<Pattern<_regex, _name>> : public std::true_type {};
|
class is_pattern<Pattern<_regex, _name>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_pattern_v =
|
constexpr bool is_pattern_v = is_pattern<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_pattern<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -21,8 +21,7 @@ namespace rfl {
|
||||||
class is_rename<Rename<_name, Type>> : public std::true_type {};
|
class is_rename<Rename<_name, Type>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_rename_v =
|
constexpr bool is_rename_v = is_rename<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_rename<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -14,12 +14,10 @@ namespace rfl::internal {
|
||||||
class is_skip : public std::false_type {};
|
class is_skip : public std::false_type {};
|
||||||
|
|
||||||
template <class T, bool _skip_serialization, bool _skip_deserialization>
|
template <class T, bool _skip_serialization, bool _skip_deserialization>
|
||||||
class is_skip<Skip<T, _skip_serialization, _skip_deserialization>>
|
class is_skip<Skip<T, _skip_serialization, _skip_deserialization>> : public std::true_type {};
|
||||||
: public std::true_type {};
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_skip_v =
|
constexpr bool is_skip_v = is_skip<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_skip<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace rfl::internal
|
} // namespace rfl::internal
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace rfl {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_validator_v =
|
constexpr bool is_validator_v =
|
||||||
is_validator<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
is_validator<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace rfl {
|
||||||
class is_variant<std::variant<T...>> : public std::true_type {};
|
class is_variant<std::variant<T...>> : public std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool is_variant_v =
|
constexpr bool is_variant_v = is_variant<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
||||||
is_variant<std::remove_cvref_t<std::remove_pointer_t<T>>>::value;
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rfl
|
} // namespace rfl
|
||||||
|
|
|
@ -17,15 +17,13 @@ namespace rfl::internal {
|
||||||
static inline auto make_tag(const T& _t) noexcept {
|
static inline auto make_tag(const T& _t) noexcept {
|
||||||
if constexpr (internal::has_reflection_type_v<T>) {
|
if constexpr (internal::has_reflection_type_v<T>) {
|
||||||
return make_tag<typename T::ReflectionType>();
|
return make_tag<typename T::ReflectionType>();
|
||||||
} else if constexpr (named_tuple_t<T>::Names::template contains<
|
} else if constexpr (named_tuple_t<T>::Names::template contains<_discriminator>()) {
|
||||||
_discriminator>()) {
|
|
||||||
return *to_view(_t).template get<_discriminator>();
|
return *to_view(_t).template get<_discriminator>();
|
||||||
} else if constexpr (internal::has_tag_v<T>) {
|
} else if constexpr (internal::has_tag_v<T>) {
|
||||||
using LiteralType = typename T::Tag;
|
using LiteralType = typename T::Tag;
|
||||||
return LiteralType::template name_of<0>();
|
return LiteralType::template name_of<0>();
|
||||||
} else {
|
} else {
|
||||||
return rfl::Literal<
|
return rfl::Literal<internal::remove_namespaces<internal::get_type_name<T>()>()>();
|
||||||
internal::remove_namespaces<internal::get_type_name<T>()>()>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue