This commit is contained in:
Mars 2024-06-08 14:10:59 -04:00
parent a743cdabe5
commit bd402f57f5
Signed by: pupbrained
GPG key ID: 874E22DF2F9DFCB5
276 changed files with 37936 additions and 22932 deletions

View file

@ -2,6 +2,8 @@
AlignConsecutiveAssignments: true
AllowShortBlocksOnASingleLine: Always
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
BasedOnStyle: Chromium

View file

@ -16,9 +16,26 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1708475490,
"narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0e74ca98a74bc7270d28838369593635a5db3260",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"treefmt-nix": "treefmt-nix",
"utils": "utils"
}
},
@ -37,6 +54,24 @@
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1717850719,
"narHash": "sha256-npYqVg+Wk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "4fc1c45a5f50169f9f29f6a98a438fb910b834ed",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"

View file

@ -3,12 +3,14 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
treefmt-nix.url = "github:numtide/treefmt-nix";
utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
treefmt-nix,
utils,
...
}:
@ -18,7 +20,7 @@
inherit system;
overlays = [
(self: super: {
(_self: super: {
ccacheWrapper = super.ccacheWrapper.override {
extraConfig = ''
export CCACHE_COMPRESS=1
@ -54,9 +56,8 @@
deps = with (
if !stdenv.isDarwin
then pkgs.pkgsStatic
else pkgs
); # TODO: Remove when fixed on darwin
else pkgs # TODO: Remove when fixed on darwin
);
[
curl
fmt
@ -110,7 +111,18 @@
default = draconisplusplus;
};
formatter = alejandra;
formatter = treefmt-nix.lib.mkWrapper pkgs {
projectRootFile = "flake.nix";
programs = {
alejandra.enable = true;
deadnix.enable = true;
clang-format = {
enable = true;
package = pkgs.clang-tools_18;
};
};
};
devShell = mkShell.override {inherit stdenv;} {
packages =

File diff suppressed because it is too large Load diff

View file

@ -12,8 +12,8 @@
namespace rfl {
template <internal::StringLiteral field_name_>
struct AddStructName {
template <internal::StringLiteral field_name_>
struct AddStructName {
/// Adds the name of the struct as a new field.
template <class StructType>
static auto process(auto&& _view) {
@ -21,11 +21,12 @@ struct AddStructName {
internal::remove_namespaces<internal::get_type_name<StructType>()>()>;
using FieldType = Field<field_name_, LiteralType>;
const auto add_new_field = [](auto&&... _fields) {
return make_named_tuple(FieldType(LiteralType()), std::move(_fields)...);
return make_named_tuple(FieldType(LiteralType()),
std::move(_fields)...);
};
return std::apply(add_new_field, std::move(_view.fields()));
}
};
};
} // namespace rfl

View file

@ -8,9 +8,9 @@
namespace rfl {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct AllOf {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct AllOf {
template <class T>
static rfl::Result<T> validate(T _value) noexcept {
return validate_impl<T, C, Cs...>(_value);
@ -21,7 +21,7 @@ struct AllOf {
using ValidationType = parsing::schema::ValidationType;
const auto types = 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:
@ -33,7 +33,7 @@ struct AllOf {
return Head::validate(_value).and_then(validate_impl<T, Tail...>);
}
}
};
};
} // namespace rfl

View file

@ -10,9 +10,9 @@
namespace rfl {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct AnyOf {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct AnyOf {
template <class T>
static rfl::Result<T> validate(const T& _value) noexcept {
return validate_impl<T, C, Cs...>(_value, {});
@ -23,13 +23,14 @@ struct AnyOf {
using ValidationType = parsing::schema::ValidationType;
const auto types = 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:
static Error make_error_message(const std::vector<Error>& _errors) {
std::string msg =
"Expected at least one of the following validations to pass, but none "
"Expected at least one of the following validations to pass, but "
"none "
"of them did:";
for (size_t i = 0; i < _errors.size(); ++i) {
msg += "\n" + std::to_string(i + 1) + ") " + _errors.at(i).what();
@ -51,7 +52,7 @@ struct AnyOf {
};
return Head::validate(_value).or_else(handle_err);
}
};
};
} // namespace rfl

View file

@ -12,8 +12,8 @@
namespace rfl {
template <class T>
struct Attribute {
template <class T>
struct Attribute {
using Type = T;
using ReflectionType = T;
@ -33,15 +33,18 @@ struct Attribute {
template <class U>
Attribute(Attribute<U>&& _attr) : value_(_attr.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Attribute(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Attribute(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Attribute(const Attribute<U>& _attr) : value_(_attr.value()) {}
@ -75,7 +78,8 @@ struct Attribute {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
auto& operator=(const U& _value) {
value_ = _value;
@ -129,7 +133,7 @@ struct Attribute {
/// The underlying value.
Type value_;
};
};
} // namespace rfl

View file

@ -8,12 +8,12 @@
namespace rfl {
/// The Box class behaves very similarly to the unique_ptr, but unlike the
/// unique_ptr, it is 100% guaranteed to be filled at all times (unless the user
/// tries to access it after calling std::move does something else that is
/// clearly bad practice).
template <class T>
class Box {
/// The Box class behaves very similarly to the unique_ptr, but unlike the
/// unique_ptr, it is 100% guaranteed to be filled at all times (unless the
/// user tries to access it after calling std::move does something else that
/// is clearly bad practice).
template <class T>
class Box {
public:
/// The only way of creating new boxes is
/// Box<T>::make(...).
@ -25,9 +25,7 @@ class Box {
/// You can generate them from unique_ptrs as well, in which case it will
/// return an Error, if the unique_ptr is not set.
static Result<Box<T>> make(std::unique_ptr<T>&& _ptr) {
if (!_ptr) {
return Error("std::unique_ptr was a nullptr.");
}
if (!_ptr) { return Error("std::unique_ptr was a nullptr."); }
return Box<T>(std::move(_ptr));
}
@ -84,41 +82,42 @@ class Box {
private:
/// The underlying unique_ptr_
std::unique_ptr<T> ptr_;
};
};
/// Generates a new Ref<T>.
template <class T, class... Args>
auto make_box(Args&&... _args) {
/// Generates a new Ref<T>.
template <class T, class... Args>
auto make_box(Args&&... _args) {
return Box<T>::make(std::forward<Args>(_args)...);
}
}
template <class T1, class T2>
inline auto operator<=>(const Box<T1>& _b1, const Box<T2>& _b2) {
template <class T1, class T2>
inline auto operator<=>(const Box<T1>& _b1, const Box<T2>& _b2) {
return _b1.ptr() <=> _b2.ptr();
}
}
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os, const Box<T>& _b) {
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os,
const Box<T>& _b) {
_os << _b.get();
return _os;
}
}
} // namespace rfl
namespace std {
template <class T>
struct hash<rfl::Box<T>> {
template <class T>
struct hash<rfl::Box<T>> {
size_t operator()(const rfl::Box<T>& _b) const {
return hash<unique_ptr<T>>()(_b.ptr());
}
};
};
template <class T>
inline void swap(rfl::Box<T>& _b1, rfl::Box<T>& _b2) {
template <class T>
inline void swap(rfl::Box<T>& _b1, rfl::Box<T>& _b2) {
return swap(_b1.ptr(), _b2.ptr());
}
}
} // namespace std

View file

@ -13,10 +13,10 @@
namespace rfl {
/// Used to add a description to the field - this is only relevant for the JSON
/// schema and will be ignored by the normal serialization routines.
template <internal::StringLiteral _description, class T>
struct Description {
/// Used to add a description to the field - this is only relevant for the
/// JSON schema and will be ignored by the normal serialization routines.
template <internal::StringLiteral _description, class T>
struct Description {
/// The underlying type.
using Type = T;
@ -42,15 +42,18 @@ struct Description {
template <class U>
Description(Description<_description, U>&& _field) : value_(_field.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Description(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Description(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Description(const Description<_description, U>& _field)
: value_(_field.value()) {}
@ -88,7 +91,8 @@ struct Description {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
auto& operator=(const U& _value) {
value_ = _value;
@ -143,7 +147,7 @@ struct Description {
/// The underlying value.
Type value_;
};
};
} // namespace rfl

View file

@ -16,9 +16,9 @@
namespace rfl {
/// Used to define a field in the NamedTuple.
template <internal::StringLiteral _name, class T>
struct Field {
/// Used to define a field in the NamedTuple.
template <internal::StringLiteral _name, class T>
struct Field {
/// The underlying type.
using Type = internal::wrap_in_rfl_array_t<T>;
@ -39,15 +39,18 @@ struct Field {
template <class U>
Field(Field<_name, U>&& _field) : value_(_field.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Field(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Field(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Field(const Field<_name, U>& _field) : value_(_field.value()) {}
@ -87,7 +90,8 @@ struct Field {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
auto& operator=(const U& _value) {
value_ = _value;
@ -137,17 +141,17 @@ struct Field {
/// The underlying value.
Type value_;
};
};
template <internal::StringLiteral _name, class T>
inline auto make_field(T&& _value) {
template <internal::StringLiteral _name, class T>
inline auto make_field(T&& _value) {
using T0 = std::remove_cvref_t<T>;
if constexpr (std::is_array_v<T0>) {
return Field<_name, T0>(internal::Array<T0>(std::forward<T>(_value)));
} else {
return Field<_name, T0>(std::forward<T>(_value));
}
}
}
} // namespace rfl

View file

@ -9,9 +9,9 @@
namespace rfl {
/// Used to embed another struct into the generated output.
template <class T>
struct Flatten {
/// Used to embed another struct into the generated output.
template <class T>
struct Flatten {
/// The underlying type.
using Type = std::remove_cvref_t<T>;
@ -29,11 +29,13 @@ struct Flatten {
template <class U>
Flatten(Flatten<U>&& _f) : value_(_f.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Flatten(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Flatten(U&& _value) : value_(_value) {}
@ -64,7 +66,8 @@ struct Flatten {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Flatten<T>& operator=(const U& _value) {
value_ = _value;
@ -99,7 +102,7 @@ struct Flatten {
/// The underlying value.
Type value_;
};
};
} // namespace rfl

View file

@ -15,20 +15,21 @@
namespace rfl {
template <internal::StringLiteral _field>
struct LiteralHelper {
template <internal::StringLiteral _field>
struct LiteralHelper {
constexpr static internal::StringLiteral field_ = _field;
};
};
template <internal::StringLiteral... fields_>
class Literal {
template <internal::StringLiteral... fields_>
class Literal {
using FieldsType = std::tuple<LiteralHelper<fields_>...>;
public:
using ValueType =
std::conditional_t<sizeof...(fields_) <=
std::numeric_limits<std::uint8_t>::max(),
std::uint8_t, std::uint16_t>;
std::uint8_t,
std::uint16_t>;
/// The number of different fields or different options that the literal
/// can assume.
@ -58,7 +59,8 @@ class Literal {
return Literal(Literal<fields_...>::template value_of<_name>());
}
/// Constructs a new Literal, equivalent to make, for reasons of consistency.
/// Constructs a new Literal, equivalent to make, for reasons of
/// consistency.
template <internal::StringLiteral _name>
static Literal<fields_...> from_name() {
return Literal<fields_...>::template make<_name>();
@ -138,7 +140,8 @@ class Literal {
/// The name defined by the Literal.
std::string name() const { return find_name(); }
/// Returns all possible values of the literal as a std::vector<std::string>.
/// Returns all possible values of the literal as a
/// std::vector<std::string>.
static std::vector<std::string> names() { return allowed_strings_vec(); }
/// Helper function to retrieve a name at compile time.
@ -292,13 +295,11 @@ class Literal {
template <int _i = 0>
static Result<int> find_value(const std::string& _str) {
using FieldType = typename std::tuple_element<_i, FieldsType>::type;
if (FieldType::field_.str() == _str) {
return _i;
}
if (FieldType::field_.str() == _str) { return _i; }
if constexpr (_i + 1 == num_fields_) {
return Error(
"Literal does not support string '" + _str +
"'. The following strings are supported: " + allowed_strings() + ".");
return Error("Literal does not support string '" + _str +
"'. The following strings are supported: " +
allowed_strings() + ".");
} else {
return find_value<_i + 1>(_str);
}
@ -344,30 +345,30 @@ class Literal {
private:
/// The underlying value.
ValueType value_;
};
};
/// Helper function to retrieve a name at compile time.
template <class LiteralType, int _value>
inline constexpr auto name_of() {
/// Helper function to retrieve a name at compile time.
template <class LiteralType, int _value>
inline constexpr auto name_of() {
return LiteralType::template name_of<_value>();
}
}
/// Helper function to retrieve a value at compile time.
template <class LiteralType, internal::StringLiteral _name>
inline constexpr auto value_of() {
/// Helper function to retrieve a value at compile time.
template <class LiteralType, internal::StringLiteral _name>
inline constexpr auto value_of() {
return LiteralType::template value_of<_name>();
}
}
} // namespace rfl
namespace std {
template <rfl::internal::StringLiteral... fields>
struct hash<rfl::Literal<fields...>> {
template <rfl::internal::StringLiteral... fields>
struct hash<rfl::Literal<fields...>> {
size_t operator()(const rfl::Literal<fields...>& _l) const {
return hash<int>()(static_cast<int>(_l.value()));
}
};
};
} // namespace std

View file

@ -5,8 +5,8 @@
namespace rfl {
/// Contains meta-information about a field in a struct.
class MetaField {
/// Contains meta-information about a field in a struct.
class MetaField {
public:
MetaField(const std::string& _name, const std::string& _type)
: name_(_name), type_(_type) {}
@ -25,7 +25,7 @@ class MetaField {
/// The type of the field we describe.
std::string type_;
};
};
} // namespace rfl

View file

@ -16,22 +16,23 @@
namespace rfl {
/// A named tuple behaves like std::tuple,
/// but the fields have explicit names, which
/// allows for reflection.
/// IMPORTANT: We have two template specializations. One with fields, one
/// without fields.
template <class... FieldTypes>
class NamedTuple;
/// A named tuple behaves like std::tuple,
/// but the fields have explicit names, which
/// allows for reflection.
/// IMPORTANT: We have two template specializations. One with fields, one
/// without fields.
template <class... FieldTypes>
class NamedTuple;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
template <class... FieldTypes>
class NamedTuple {
template <class... FieldTypes>
class NamedTuple {
public:
using Fields = std::tuple<std::remove_cvref_t<FieldTypes>...>;
using Names = Literal<std::remove_cvref_t<FieldTypes>::name_...>;
using Values = std::tuple<typename std::remove_cvref_t<FieldTypes>::Type...>;
using Values =
std::tuple<typename std::remove_cvref_t<FieldTypes>::Type...>;
public:
/// Construct from the values.
@ -166,7 +167,8 @@ class NamedTuple {
/// Template specialization for NamedTuple, so we can pass fields from other
/// named tuples.
template <class... TupContent, class... Tail>
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
auto add(NamedTuple<TupContent...> _named_tuple,
const Tail&... _tail) const {
return add(_named_tuple.fields(), _tail...);
}
@ -177,7 +179,8 @@ class NamedTuple {
const auto transform_field = [&_f](auto... _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);
};
auto new_fields = std::apply(transform_field, std::move(fields()));
@ -191,7 +194,8 @@ class NamedTuple {
const auto transform_field = [&_f](auto... _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);
};
auto new_fields = std::apply(transform_field, std::move(fields()));
@ -285,7 +289,8 @@ class NamedTuple {
/// Replaces one or several fields, returning a new version
/// with the non-replaced fields left unchanged.
template <internal::StringLiteral _name, class FType, class... OtherRFields>
auto replace(Field<_name, FType>&& _field, OtherRFields&&... _other_fields) {
auto replace(Field<_name, FType>&& _field,
OtherRFields&&... _other_fields) {
using RField = Field<_name, FType>;
constexpr auto num_other_fields = sizeof...(OtherRFields);
if constexpr (num_other_fields == 0) {
@ -361,7 +366,8 @@ class NamedTuple {
const auto transform_field = [&_f](auto... 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);
};
auto new_fields = std::apply(transform_field, std::move(fields()));
@ -375,7 +381,8 @@ class NamedTuple {
const auto transform_field = [&_f](auto... 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);
};
auto new_fields = std::apply(transform_field, std::move(fields()));
@ -446,8 +453,8 @@ class NamedTuple {
// When we add additional fields, it is more intuitive to add
// them to the end, that is why we do it like this.
using FieldType = typename std::tuple_element<i, Fields>::type;
return make_fields<num_additional_fields>(FieldType(std::get<i>(values_)),
std::move(_args)...);
return make_fields<num_additional_fields>(
FieldType(std::get<i>(values_)), std::move(_args)...);
}
}
@ -524,7 +531,8 @@ class NamedTuple {
/// Retrieves the fields from another tuple.
template <class... OtherFieldTypes, class... Args>
constexpr static Fields retrieve_fields(
std::tuple<OtherFieldTypes...>&& _other_fields, Args&&... _args) {
std::tuple<OtherFieldTypes...>&& _other_fields,
Args&&... _args) {
constexpr auto size = sizeof...(Args);
constexpr bool retrieved_all_fields = size == std::tuple_size_v<Fields>;
@ -532,7 +540,8 @@ class NamedTuple {
if constexpr (retrieved_all_fields) {
return std::make_tuple(std::forward<Args>(_args)...);
} else {
constexpr auto field_name = std::tuple_element<size, Fields>::type::name_;
constexpr auto field_name =
std::tuple_element<size, Fields>::type::name_;
constexpr auto index =
internal::find_index<field_name, std::tuple<OtherFieldTypes...>>();
@ -554,19 +563,19 @@ class NamedTuple {
/// everything else is resolved at compile time. It should have no
/// runtime overhead over a normal std::tuple.
Values values_;
};
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// We need a special template instantiation for empty named tuples.
template <>
class NamedTuple<> {
/// We need a special template instantiation for empty named tuples.
template <>
class NamedTuple<> {
public:
using Fields = std::tuple<>;
using Names = Literal<>;
using Values = std::tuple<>;
NamedTuple(){};
NamedTuple() {};
~NamedTuple() = default;
@ -594,7 +603,8 @@ class NamedTuple<> {
/// Template specialization for NamedTuple, so we can pass fields from other
/// named tuples.
template <class... TupContent, class... Tail>
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
auto add(NamedTuple<TupContent...> _named_tuple,
const Tail&... _tail) const {
return add(_named_tuple.fields(), _tail...);
}
@ -622,61 +632,65 @@ class NamedTuple<> {
/// Returns an empty tuple.
auto values() const { return std::tuple(); }
};
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
template <internal::StringLiteral _name1, class Type1,
internal::StringLiteral _name2, class Type2>
inline auto operator*(const rfl::Field<_name1, Type1>& _f1,
template <internal::StringLiteral _name1,
class Type1,
internal::StringLiteral _name2,
class Type2>
inline auto operator*(const rfl::Field<_name1, Type1>& _f1,
const rfl::Field<_name2, Type2>& _f2) {
return NamedTuple(_f1, _f2);
}
}
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(const NamedTuple<FieldTypes...>& _tup,
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(const NamedTuple<FieldTypes...>& _tup,
const rfl::Field<_name, Type>& _f) {
return _tup.add(_f);
}
}
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(const rfl::Field<_name, Type>& _f,
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(const rfl::Field<_name, Type>& _f,
const NamedTuple<FieldTypes...>& _tup) {
return NamedTuple(_f).add(_tup);
}
}
template <class... FieldTypes1, class... FieldTypes2>
inline auto operator*(const NamedTuple<FieldTypes1...>& _tup1,
template <class... FieldTypes1, class... FieldTypes2>
inline auto operator*(const NamedTuple<FieldTypes1...>& _tup1,
const NamedTuple<FieldTypes2...>& _tup2) {
return _tup1.add(_tup2);
}
}
template <internal::StringLiteral _name1, class Type1,
internal::StringLiteral _name2, class Type2>
inline auto operator*(rfl::Field<_name1, Type1>&& _f1,
template <internal::StringLiteral _name1,
class Type1,
internal::StringLiteral _name2,
class Type2>
inline auto operator*(rfl::Field<_name1, Type1>&& _f1,
rfl::Field<_name2, Type2>&& _f2) {
return NamedTuple(std::forward<Field<_name1, Type1>>(_f1),
std::forward<Field<_name2, Type2>>(_f2));
}
}
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(NamedTuple<FieldTypes...>&& _tup,
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(NamedTuple<FieldTypes...>&& _tup,
rfl::Field<_name, Type>&& _f) {
return _tup.add(std::forward<Field<_name, Type>>(_f));
}
}
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(rfl::Field<_name, Type>&& _f,
template <internal::StringLiteral _name, class Type, class... FieldTypes>
inline auto operator*(rfl::Field<_name, Type>&& _f,
NamedTuple<FieldTypes...>&& _tup) {
return NamedTuple(std::forward<Field<_name, Type>>(_f))
.add(std::forward<NamedTuple<FieldTypes...>>(_tup));
}
}
template <class... FieldTypes1, class... FieldTypes2>
inline auto operator*(NamedTuple<FieldTypes1...>&& _tup1,
template <class... FieldTypes1, class... FieldTypes2>
inline auto operator*(NamedTuple<FieldTypes1...>&& _tup1,
NamedTuple<FieldTypes2...>&& _tup2) {
return _tup1.add(std::forward<NamedTuple<FieldTypes2...>>(_tup2));
}
}
} // namespace rfl

View file

@ -3,15 +3,15 @@
namespace rfl {
/// This is a "fake" processor - it doesn't do much in itself, but its
/// inclusion instructs the parsers to require the inclusion of all fields.
struct NoOptionals {
/// This is a "fake" processor - it doesn't do much in itself, but its
/// inclusion instructs the parsers to require the inclusion of all fields.
struct NoOptionals {
public:
template <class StructType>
static auto process(auto&& _named_tuple) {
return _named_tuple;
}
};
};
} // namespace rfl

View file

@ -10,9 +10,9 @@
namespace rfl {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct OneOf {
/// Requires that all of the contraints C and Cs be true.
template <class C, class... Cs>
struct OneOf {
template <class T>
static rfl::Result<T> validate(const T& _value) noexcept {
return validate_impl<T, C, Cs...>(_value, {});
@ -23,7 +23,7 @@ struct OneOf {
using ValidationType = parsing::schema::ValidationType;
const auto types = 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:
@ -51,9 +51,7 @@ struct OneOf {
_r.or_else(push_back);
if constexpr (sizeof...(Tail) == 0) {
if (_errors.size() == sizeof...(Cs)) {
return _value;
}
if (_errors.size() == sizeof...(Cs)) { return _value; }
return make_error_message(_errors);
} else {
return validate_impl<T, Tail...>(
@ -65,7 +63,7 @@ struct OneOf {
.and_then(next_validation)
.or_else(next_validation);
}
};
};
} // namespace rfl

View file

@ -6,8 +6,8 @@
namespace rfl {
template <internal::StringLiteral _regex, internal::StringLiteral _name>
using Pattern = Validator<std::string, PatternValidator<_regex, _name>>;
template <internal::StringLiteral _regex, internal::StringLiteral _name>
using Pattern = Validator<std::string, PatternValidator<_regex, _name>>;
} // namespace rfl

View file

@ -11,8 +11,8 @@
namespace rfl {
template <internal::StringLiteral _regex, internal::StringLiteral _name>
struct PatternValidator {
template <internal::StringLiteral _regex, internal::StringLiteral _name>
struct PatternValidator {
using Name = Literal<_name>;
using Regex = Literal<_regex>;
@ -28,9 +28,9 @@ struct PatternValidator {
template <class T>
static parsing::schema::ValidationType to_schema() {
using ValidationType = parsing::schema::ValidationType;
return ValidationType{ValidationType::Regex{.pattern_ = Regex().str()}};
return ValidationType {ValidationType::Regex {.pattern_ = Regex().str()}};
}
};
};
} // namespace rfl

View file

@ -7,21 +7,21 @@
namespace rfl {
template <class... Ps>
struct Processors;
template <class... Ps>
struct Processors;
template <>
struct Processors<> {
template <>
struct Processors<> {
static constexpr bool all_required_ = false;
template <class T, class NamedTupleType>
static auto process(NamedTupleType&& _named_tuple) {
return _named_tuple;
}
};
};
template <class Head, class... Tail>
struct Processors<Head, Tail...> {
template <class Head, class... Tail>
struct Processors<Head, Tail...> {
static constexpr bool all_required_ =
std::disjunction_v<internal::is_no_optionals<Head>,
internal::is_no_optionals<Tail>...>;
@ -31,7 +31,7 @@ struct Processors<Head, Tail...> {
return Processors<Tail...>::template process<T>(
Head::template process<T>(std::move(_named_tuple)));
}
};
};
} // namespace rfl

View file

@ -8,12 +8,12 @@
namespace rfl {
/// The Ref class behaves very similarly to the shared_ptr, but unlike the
/// unique_ptr, it is 100% guaranteed to be filled at all times (unless the user
/// tries to access it after calling std::move does something else that is
/// clearly bad practice).
template <class T>
class Ref {
/// The Ref class behaves very similarly to the shared_ptr, but unlike the
/// unique_ptr, it is 100% guaranteed to be filled at all times (unless the
/// user tries to access it after calling std::move does something else that
/// is clearly bad practice).
template <class T>
class Ref {
public:
/// The default way of creating new references is
/// Ref<T>::make(...) or make_ref<T>(...).
@ -25,18 +25,14 @@ class Ref {
/// You can generate them from shared_ptrs as well, in which case it will
/// return an Error, if the shared_ptr is not set.
static Result<Ref<T>> make(std::shared_ptr<T>&& _ptr) {
if (!_ptr) {
return Error("std::shared_ptr was a nullptr.");
}
if (!_ptr) { return Error("std::shared_ptr was a nullptr."); }
return Ref<T>(std::move(_ptr));
}
/// You can generate them from shared_ptrs as well, in which case it will
/// return an Error, if the shared_ptr is not set.
static Result<Ref<T>> make(const std::shared_ptr<T>& _ptr) {
if (!_ptr) {
return Error("std::shared_ptr was a nullptr.");
}
if (!_ptr) { return Error("std::shared_ptr was a nullptr."); }
return Ref<T>(_ptr);
}
@ -106,43 +102,43 @@ class Ref {
private:
/// The underlying shared_ptr_
std::shared_ptr<T> ptr_;
};
};
/// Generates a new Ref<T>.
template <class T, class... Args>
auto make_ref(Args&&... _args) {
/// Generates a new Ref<T>.
template <class T, class... Args>
auto make_ref(Args&&... _args) {
return Ref<T>::make(std::forward<Args>(_args)...);
}
}
template <class T1, class T2>
inline auto operator<=>(const Ref<T1>& _t1, const Ref<T2>& _t2) {
template <class T1, class T2>
inline auto operator<=>(const Ref<T1>& _t1, const Ref<T2>& _t2) {
return _t1.ptr() <=> _t2.ptr();
}
}
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os, const Ref<T>& _b) {
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os,
const Ref<T>& _b) {
_os << _b.get();
return _os;
}
}
} // namespace rfl
namespace std {
template <class T>
struct hash<rfl::Ref<T>> {
template <class T>
struct hash<rfl::Ref<T>> {
size_t operator()(const rfl::Ref<T>& _r) const {
return hash<shared_ptr<T>>()(_r.ptr());
}
};
};
template <class T>
inline void swap(rfl::Ref<T>& _r1, rfl::Ref<T>& _r2) {
template <class T>
inline void swap(rfl::Ref<T>& _r1, rfl::Ref<T>& _r2) {
return swap(_r1.ptr(), _r2.ptr());
}
}
} // namespace std
#endif // RFL_REF_HPP_

View file

@ -13,10 +13,10 @@
namespace rfl {
/// Used to assign a new name to a field, which is different from the name
/// inside the struct.
template <internal::StringLiteral _name, class T>
struct Rename {
/// Used to assign a new name to a field, which is different from the name
/// inside the struct.
template <internal::StringLiteral _name, class T>
struct Rename {
/// The underlying type.
using Type = T;
@ -39,15 +39,18 @@ struct Rename {
template <class U>
Rename(Rename<_name, U>&& _field) : value_(_field.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Rename(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Rename(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Rename(const Rename<_name, U>& _field) : value_(_field.value()) {}
@ -84,7 +87,8 @@ struct Rename {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
auto& operator=(const U& _value) {
value_ = _value;
@ -134,7 +138,7 @@ struct Rename {
/// The underlying value.
Type value_;
};
};
} // namespace rfl

View file

@ -18,8 +18,8 @@
namespace rfl {
/// To be returned
class Error {
/// To be returned
class Error {
public:
Error(const std::string& _what) : what_(_what) {}
@ -31,18 +31,20 @@ class Error {
private:
/// Documents what went wrong
std::string what_;
};
};
/// Can be used when we are simply interested in whether an operation was
/// successful.
struct Nothing {};
/// Can be used when we are simply interested in whether an operation was
/// successful.
struct Nothing {};
/// The Result class is used for monadic error handling.
template <class T>
class Result {
static_assert(!std::is_same<T, Error>(), "The result type cannot be Error.");
/// The Result class is used for monadic error handling.
template <class T>
class Result {
static_assert(!std::is_same<T, Error>(),
"The result type cannot be Error.");
using TOrErr = std::array<unsigned char, std::max(sizeof(T), sizeof(Error))>;
using TOrErr =
std::array<unsigned char, std::max(sizeof(T), sizeof(Error))>;
public:
using Type = T;
@ -53,7 +55,9 @@ class Result {
new (&get_t()) T(std::move(_val));
}
Result(const Error& _err) : success_(false) { new (&get_err()) Error(_err); }
Result(const Error& _err) : success_(false) {
new (&get_err()) Error(_err);
}
Result(Error&& _err) noexcept : success_(false) {
new (&get_err()) Error(std::move(_err));
@ -67,16 +71,18 @@ class Result {
copy_from_other(_other);
}
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
Result(Result<U>&& _other) : success_(_other && true) {
auto temp = std::forward<Result<U>>(_other).transform(
[](U&& _u) { return T(std::forward<U>(_u)); });
move_from_other(temp);
}
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
Result(const Result<U>& _other) : success_(_other && true) {
auto temp = _other.transform([](const U& _u) { return T(_u); });
move_from_other(temp);
@ -179,9 +185,7 @@ class Result {
/// Assigns the underlying object.
Result<T>& operator=(const Result<T>& _other) {
if (this == &_other) {
return *this;
}
if (this == &_other) { return *this; }
destroy();
success_ = _other.success_;
copy_from_other(_other);
@ -190,9 +194,7 @@ class Result {
/// Assigns the underlying object.
Result<T>& operator=(Result<T>&& _other) noexcept {
if (this == &_other) {
return *this;
}
if (this == &_other) { return *this; }
destroy();
success_ = _other.success_;
move_from_other(_other);
@ -200,8 +202,9 @@ class Result {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
auto& operator=(const Result<U>& _other) {
const auto to_t = [](const U& _u) -> T { return _u; };
t_or_err_ = _other.transform(to_t).t_or_err_;
@ -310,7 +313,8 @@ class Result {
void destroy() {
if (success_) {
if constexpr (std::is_destructible_v<T> /*&& !internal::is_array_v<T>*/) {
if constexpr (std::is_destructible_v<
T> /*&& !internal::is_array_v<T>*/) {
get_t().~T();
}
} else {
@ -346,7 +350,7 @@ class Result {
/// The underlying data, can either be T or Error.
alignas(std::max(alignof(T), alignof(Error))) TOrErr t_or_err_;
};
};
} // namespace rfl

View file

@ -10,8 +10,8 @@
namespace rfl {
template <class V>
struct Size {
template <class V>
struct Size {
template <class T>
static rfl::Result<T> validate(const T& _t) {
const auto to_t = [&](const auto& _v) { return _t; };
@ -25,7 +25,7 @@ struct Size {
static parsing::schema::ValidationType to_schema() {
return V::template to_schema<size_t>();
}
};
};
} // namespace rfl

View file

@ -5,16 +5,15 @@
namespace rfl {
template <class T>
using Skip = internal::Skip<T, true, true>;
template <class T>
using Skip = internal::Skip<T, true, true>;
template <class T>
using SkipSerialization = internal::Skip<T, true, false>;
template <class T>
using SkipSerialization = internal::Skip<T, true, false>;
template <class T>
using SkipDeserialization = internal::Skip<T, false, true>;
template <class T>
using SkipDeserialization = internal::Skip<T, false, true>;
} // namespace rfl
#endif

View file

@ -6,7 +6,7 @@
namespace rfl {
struct SnakeCaseToCamelCase {
struct SnakeCaseToCamelCase {
public:
/// Replaces all instances of snake_case field names with camelCase.
template <class StructType>
@ -31,7 +31,7 @@ struct SnakeCaseToCamelCase {
typename FieldType::Type>;
return NewFieldType(_f.value());
}
};
};
} // namespace rfl

View file

@ -6,7 +6,7 @@
namespace rfl {
struct SnakeCaseToPascalCase {
struct SnakeCaseToPascalCase {
public:
/// Replaces all instances of snake_case field names with PascalCase.
template <class StructType>
@ -31,7 +31,7 @@ struct SnakeCaseToPascalCase {
typename FieldType::Type>;
return NewFieldType(_f.value());
}
};
};
} // namespace rfl

View file

@ -10,16 +10,17 @@
namespace rfl {
// https://serde.rs/enum-representations.html
template <internal::StringLiteral _discriminator, class... Ts>
struct TaggedUnion {
// https://serde.rs/enum-representations.html
template <internal::StringLiteral _discriminator, class... Ts>
struct TaggedUnion {
static constexpr internal::StringLiteral discrimininator_ = _discriminator;
/// The type of the underlying variant.
using VariantType = std::variant<Ts...>;
/// A literal containing all the tags that are possible
using PossibleTags = define_literal_t<internal::tag_t<_discriminator, Ts>...>;
using PossibleTags =
define_literal_t<internal::tag_t<_discriminator, Ts>...>;
TaggedUnion(const VariantType& _variant) : variant_(_variant) {}
@ -94,12 +95,12 @@ struct TaggedUnion {
/// The underlying variant - a TaggedUnion is a thin wrapper
/// around a variant that is mainly used for parsing.
VariantType variant_;
};
};
namespace internal {
namespace internal {
template <StringLiteral _discriminator, class... NamedTupleTypes>
struct Getter<TaggedUnion<_discriminator, NamedTupleTypes...>> {
template <StringLiteral _discriminator, class... NamedTupleTypes>
struct Getter<TaggedUnion<_discriminator, NamedTupleTypes...>> {
public:
/// Retrieves the indicated value from the tuple.
template <int _index>
@ -113,8 +114,8 @@ struct Getter<TaggedUnion<_discriminator, NamedTupleTypes...>> {
template <StringLiteral _field_name>
static inline auto& get(
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.
@ -129,8 +130,8 @@ struct Getter<TaggedUnion<_discriminator, NamedTupleTypes...>> {
template <int _index>
static inline const auto& get_const(
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
return Getter<std::variant<NamedTupleTypes...>>::template get_const<_index>(
_tu.variant_);
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
_index>(_tu.variant_);
}
/// Gets a field by name.
@ -145,12 +146,12 @@ struct Getter<TaggedUnion<_discriminator, NamedTupleTypes...>> {
template <class Field>
static inline const auto& get_const(
const TaggedUnion<_discriminator, NamedTupleTypes...>& _tu) {
return Getter<std::variant<NamedTupleTypes...>>::template get_const<Field>(
_tu.variant_);
return Getter<std::variant<NamedTupleTypes...>>::template get_const<
Field>(_tu.variant_);
}
};
};
} // namespace internal
} // namespace internal
} // namespace rfl

View file

@ -15,9 +15,9 @@
namespace rfl {
/// For serializing and deserializing time stamps.
template <internal::StringLiteral _format>
class Timestamp {
/// For serializing and deserializing time stamps.
template <internal::StringLiteral _format>
class Timestamp {
constexpr static const internal::StringLiteral format_ = _format;
public:
@ -25,7 +25,7 @@ class Timestamp {
using ReflectionType = std::string;
Timestamp(const char* _str) : tm_(std::tm{}) {
Timestamp(const char* _str) : tm_(std::tm {}) {
const auto r = strptime(_str, _format.str().c_str(), &tm_);
if (r == NULL) {
throw std::runtime_error("String '" + std::string(_str) +
@ -45,9 +45,7 @@ class Timestamp {
static Result<Timestamp> from_string(const char* _str) noexcept {
try {
return Timestamp(_str);
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
}
/// Returns a result containing the timestamp when successful or an Error
@ -79,9 +77,7 @@ class Timestamp {
std::istringstream input(_s);
input.imbue(std::locale(setlocale(LC_ALL, nullptr)));
input >> std::get_time(_tm, _f);
if (input.fail()) {
return NULL;
}
if (input.fail()) { return NULL; }
return (char*)(_s + input.tellg());
}
#endif
@ -89,7 +85,7 @@ class Timestamp {
private:
/// The underlying time stamp.
std::tm tm_;
};
};
} // namespace rfl

View file

@ -16,9 +16,9 @@
namespace rfl {
template <class T, class V, class... Vs>
requires internal::HasValidation<AllOf<V, Vs...>, T>
struct Validator {
template <class T, class V, class... Vs>
requires internal::HasValidation<AllOf<V, Vs...>, T>
struct Validator {
public:
using ReflectionType = T;
using ValidationType =
@ -28,9 +28,7 @@ struct Validator {
static Result<Validator<T, V, Vs...>> from_value(const T& _value) noexcept {
try {
return Validator<T, V, Vs...>(_value);
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
}
Validator() : value_(ValidationType::validate(T()).value()) {}
@ -44,13 +42,16 @@ struct Validator {
Validator(const T& _value)
: value_(ValidationType::validate(_value).value()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
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()) {}
: value_(ValidationType::validate(T(std::forward<U>(_value))).value()) {
}
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
Validator(const U& _value)
: value_(ValidationType::validate(T(_value)).value()) {}
@ -73,20 +74,22 @@ struct Validator {
default;
/// Assigns the underlying object.
Validator<T, V, Vs...>& operator=(Validator<T, V, Vs...>&& _other) noexcept =
default;
Validator<T, V, Vs...>& operator=(
Validator<T, V, Vs...>&& _other) noexcept = default;
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
auto& operator=(U&& _value) noexcept {
value_ = ValidationType::validate(T(std::forward<U>(_value))).value();
return *this;
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, T>,
bool>::type = true>
template <
class U,
typename std::enable_if<std::is_convertible_v<U, T>, bool>::type = true>
auto& operator=(const U& _value) {
value_ = ValidationType::validate(T(_value)).value();
return *this;
@ -109,29 +112,29 @@ struct Validator {
private:
/// The underlying value.
T value_;
};
};
template <class T, class V, class... Vs>
inline auto operator<=>(const Validator<T, V, Vs...>& _v1,
template <class T, class V, class... Vs>
inline auto operator<=>(const Validator<T, V, Vs...>& _v1,
const Validator<T, V, Vs...>& _v2) {
return _v1.value() <=> _v2.value();
}
}
template <class T, class V, class... Vs>
inline auto operator<=>(const Validator<T, V, Vs...>& _v, const T& _t) {
template <class T, class V, class... Vs>
inline auto operator<=>(const Validator<T, V, Vs...>& _v, const T& _t) {
return _v.value() <=> _t;
}
}
} // namespace rfl
namespace std {
template <class T, class V, class... Vs>
struct hash<rfl::Validator<T, V, Vs...>> {
template <class T, class V, class... Vs>
struct hash<rfl::Validator<T, V, Vs...>> {
size_t operator()(const rfl::Validator<T, V, Vs...>& _v) const {
return hash<T>()(_v.value());
}
};
};
} // namespace std

View file

@ -5,8 +5,8 @@
namespace rfl {
template <class... AlternativeTypes>
struct Variant {
template <class... AlternativeTypes>
struct Variant {
/// The type of the underlying variant.
using VariantType = std::variant<AlternativeTypes...>;
@ -77,7 +77,7 @@ struct Variant {
/// The underlying variant - a Variant is a thin wrapper
/// around a variant that is mainly used for parsing.
VariantType variant_;
};
};
} // namespace rfl

View file

@ -3,9 +3,9 @@
namespace rfl {
/// To be used inside visitor patterns
template <class>
inline constexpr bool always_false_v = false;
/// To be used inside visitor patterns
template <class>
inline constexpr bool always_false_v = false;
} // namespace rfl

View file

@ -7,9 +7,9 @@
namespace rfl {
/// Generates a type T from the input values.
template <class T, class Head, class... Tail>
T as(Head&& _head, Tail&&... _tail) {
/// Generates a type T from the input values.
template <class T, class Head, class... Tail>
T as(Head&& _head, Tail&&... _tail) {
if constexpr (sizeof...(_tail) == 0) {
return from_named_tuple<T>(to_named_tuple(std::forward<Head>(_head)));
} else {
@ -17,18 +17,18 @@ T as(Head&& _head, Tail&&... _tail) {
to_named_tuple(std::forward<Head>(_head))
.add(to_named_tuple(std::forward<Tail>(_tail))...));
}
}
}
/// Generates a type T from the input values.
template <class T, class Head, class... Tail>
T as(const Head& _head, const Tail&... _tail) {
/// Generates a type T from the input values.
template <class T, class Head, class... Tail>
T as(const Head& _head, const Tail&... _tail) {
if constexpr (sizeof...(_tail) == 0) {
return from_named_tuple<T>(to_named_tuple(_head));
} else {
return from_named_tuple<T>(
to_named_tuple(_head).add(to_named_tuple(_tail)...));
}
}
}
} // namespace rfl

View file

@ -9,11 +9,11 @@
namespace rfl::parsing {
/// bson_oid_t needs to be treated as a special case, otherwise it will be read
/// as a struct.
template <class R, class W, class ProcessorsType>
requires AreReaderAndWriter<R, W, bson_oid_t>
struct Parser<R, W, ProcessorsType, bson_oid_t> {
/// bson_oid_t needs to be treated as a special case, otherwise it will be
/// read as a struct.
template <class R, class W, class ProcessorsType>
requires AreReaderAndWriter<R, W, bson_oid_t>
struct Parser<R, W, ProcessorsType, bson_oid_t> {
using InputVarType = typename R::InputVarType;
using OutputVarType = typename W::OutputVarType;
@ -25,7 +25,8 @@ struct Parser<R, W, ProcessorsType, bson_oid_t> {
}
template <class P>
static void write(const W& _w, const bson_oid_t& _oid,
static void write(const W& _w,
const bson_oid_t& _oid,
const P& _parent) noexcept {
ParentType::add_value(_w, _oid, _parent);
}
@ -34,16 +35,16 @@ struct Parser<R, W, ProcessorsType, bson_oid_t> {
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{}};
return schema::Type {schema::Type::String {}};
}
};
};
} // namespace rfl::parsing
namespace rfl::bson {
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
} // namespace rfl::bson

View file

@ -1,9 +1,8 @@
#ifndef RFL_BSON_READER_HPP_
#define RFL_BSON_READER_HPP_
#include <bson/bson.h>
#include <array>
#include <bson/bson.h>
#include <concepts>
#include <exception>
#include <map>
@ -22,10 +21,10 @@
#include "../always_false.hpp"
namespace rfl {
namespace bson {
namespace bson {
/// Please refer to https://mongoc.org/libbson/current/api.html
struct Reader {
/// Please refer to https://mongoc.org/libbson/current/api.html
struct Reader {
struct BSONValue {
bson_value_t val_;
};
@ -47,12 +46,12 @@ struct Reader {
using InputVarType = BSONInputVar;
template <class T>
static constexpr bool has_custom_constructor = (requires(InputVarType var) {
T::from_bson_obj(var);
});
static constexpr bool has_custom_constructor =
(requires(InputVarType var) { T::from_bson_obj(var); });
rfl::Result<InputVarType> get_field(
const std::string& _name, const InputObjectType& _obj) const noexcept {
const std::string& _name,
const InputObjectType& _obj) const noexcept {
bson_t b;
bson_iter_t iter;
const auto doc = _obj.val_->val_.value.v_doc;
@ -60,9 +59,7 @@ struct Reader {
if (bson_iter_init(&iter, &b)) {
while (bson_iter_next(&iter)) {
auto key = std::string(bson_iter_key(&iter));
if (key == _name) {
return to_input_var(&iter);
}
if (key == _name) { return to_input_var(&iter); }
}
}
}
@ -114,7 +111,8 @@ struct Reader {
"Could not cast to numeric value. The type must be double, "
"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) {
return rfl::Error("Could not cast to OID.");
}
@ -130,11 +128,12 @@ struct Reader {
if (btype != BSON_TYPE_ARRAY && btype != BSON_TYPE_DOCUMENT) {
return Error("Could not cast to an array.");
}
return InputArrayType{_var.val_};
return InputArrayType {_var.val_};
}
template <class ArrayReader>
std::optional<Error> read_array(const ArrayReader& _array_reader,
std::optional<Error> read_array(
const ArrayReader& _array_reader,
const InputArrayType& _arr) const noexcept {
bson_t b;
bson_iter_t iter;
@ -143,9 +142,7 @@ struct Reader {
if (bson_iter_init(&iter, &b)) {
while (bson_iter_next(&iter)) {
const auto err = _array_reader.read(to_input_var(&iter));
if (err) {
return err;
}
if (err) { return err; }
}
}
}
@ -153,7 +150,8 @@ struct Reader {
}
template <class ObjectReader>
std::optional<Error> read_object(const ObjectReader& _object_reader,
std::optional<Error> read_object(
const ObjectReader& _object_reader,
const InputObjectType& _obj) const noexcept {
bson_t b;
bson_iter_t iter;
@ -175,7 +173,7 @@ struct Reader {
if (btype != BSON_TYPE_DOCUMENT) {
return Error("Could not cast to a document.");
}
return InputObjectType{_var.val_};
return InputObjectType {_var.val_};
}
template <class T>
@ -183,18 +181,14 @@ struct Reader {
const InputVarType& _var) const noexcept {
try {
return T::from_bson_obj(_var);
} catch (std::exception& e) {
return rfl::Error(e.what());
}
} catch (std::exception& e) { return rfl::Error(e.what()); }
}
private:
struct BSONValues {
std::vector<rfl::Box<BSONValue>> vec_;
~BSONValues() {
for (auto& v : vec_) {
bson_value_destroy(&(v->val_));
}
for (auto& v : vec_) { bson_value_destroy(&(v->val_)); }
}
};
@ -203,15 +197,15 @@ struct Reader {
values_->vec_.emplace_back(rfl::Box<BSONValue>::make());
auto* last_value = values_->vec_.back().get();
bson_value_copy(bson_iter_value(_iter), &last_value->val_);
return InputVarType{last_value};
return InputVarType {last_value};
}
private:
/// Contains the values inside the object.
rfl::Ref<BSONValues> values_;
};
};
} // namespace bson
} // namespace bson
} // namespace rfl
#endif // JSON_PARSER_HPP_

View file

@ -2,7 +2,6 @@
#define RFL_BSON_WRITER_HPP_
#include <bson/bson.h>
#include <exception>
#include <map>
#include <sstream>
@ -19,10 +18,10 @@
#include "../always_false.hpp"
namespace rfl {
namespace bson {
namespace bson {
/// Please refer to https://mongoc.org/libbson/current/api.html
class Writer {
/// Please refer to https://mongoc.org/libbson/current/api.html
class Writer {
struct BSONType {
bson_t val_;
};
@ -66,62 +65,68 @@ class Writer {
OutputArrayType array_as_root(const size_t _size) const noexcept {
bson_array_builder_t* val = bson_array_builder_new();
return OutputArrayType(val, IsRoot{});
return OutputArrayType(val, IsRoot {});
}
OutputObjectType object_as_root(const size_t _size) const noexcept {
return OutputObjectType(doc_, IsRoot{});
return OutputObjectType(doc_, IsRoot {});
}
OutputVarType null_as_root() const noexcept {
// Appears to be unsupported by the BSON C API.
return OutputVarType{};
return OutputVarType {};
}
template <class T>
OutputVarType value_as_root(const T& _var) const noexcept {
static_assert(rfl::always_false_v<T>,
"BSON only allows arrays or objects as its root.");
return OutputVarType{};
return OutputVarType {};
}
OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType add_array_to_array(
const size_t _size,
OutputArrayType* _parent) const noexcept {
bson_array_builder_t* 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(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
bson_array_builder_t* val;
bson_append_array_builder_begin(_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(
const size_t _size, OutputArrayType* _parent) const noexcept {
const size_t _size,
OutputArrayType* _parent) const noexcept {
subdocs_->emplace_back(rfl::Box<BSONType>());
bson_array_builder_append_document_begin(_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(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
subdocs_->emplace_back(rfl::Box<BSONType>());
bson_append_document_begin(_parent->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>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_array_builder_append_utf8(_parent->val_, _var.c_str(),
static_cast<int>(_var.size()));
@ -133,16 +138,18 @@ class Writer {
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
bson_array_builder_append_int64(_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);
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
return OutputVarType {};
}
template <class T>
OutputVarType add_value_to_object(const std::string_view& _name,
OutputVarType add_value_to_object(
const std::string_view& _name,
const T& _var,
OutputObjectType* _parent) const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
@ -160,32 +167,35 @@ class Writer {
bson_append_int64(_parent->val_, _name.data(),
static_cast<int>(_name.size()),
static_cast<std::int64_t>(_var));
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
bson_oid_t>()) {
bson_append_oid(_parent->val_, _name.data(),
static_cast<int>(_name.size()), &_var);
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
return OutputVarType {};
}
OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept {
bson_array_builder_append_null(_parent->val_);
return OutputVarType{};
return OutputVarType {};
}
OutputVarType add_null_to_object(const std::string_view& _name,
OutputVarType add_null_to_object(
const std::string_view& _name,
OutputObjectType* _parent) const noexcept {
bson_append_null(_parent->val_, _name.data(),
static_cast<int>(_name.size()));
return OutputVarType{};
return OutputVarType {};
}
void end_array(OutputArrayType* _arr) const noexcept {
const auto handle = [&](const auto _parent) {
using Type = std::remove_cvref_t<decltype(_parent)>;
if constexpr (std::is_same<Type, IsArray>()) {
bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_);
bson_array_builder_append_array_builder_end(_parent.ptr_,
_arr->val_);
} else if constexpr (std::is_same<Type, IsObject>()) {
bson_append_array_builder_end(_parent.ptr_, _arr->val_);
} else if constexpr (std::is_same<Type, IsRoot>()) {
@ -219,9 +229,9 @@ class Writer {
/// Contain all of the subdocuments.
const rfl::Ref<std::vector<rfl::Box<BSONType>>> subdocs_;
};
};
} // namespace bson
} // namespace bson
} // namespace rfl
#endif // BSON_PARSER_HPP_

View file

@ -6,17 +6,17 @@
#include "read.hpp"
namespace rfl {
namespace bson {
namespace bson {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
const auto read_bytes = [](const auto& _bytes) {
return read<T, Ps...>(_bytes);
};
return rfl::io::load_bytes(_fname).and_then(read_bytes);
}
}
} // namespace bson
} // namespace bson
} // namespace rfl
#endif

View file

@ -2,7 +2,6 @@
#define RFL_BSON_READ_HPP_
#include <bson/bson.h>
#include <istream>
#include <string>
@ -12,50 +11,50 @@
#include "Reader.hpp"
namespace rfl {
namespace bson {
namespace bson {
using InputObjectType = typename Reader::InputObjectType;
using InputVarType = typename Reader::InputVarType;
using InputObjectType = typename Reader::InputObjectType;
using InputVarType = typename Reader::InputVarType;
/// Parses an object from a BSON var.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const InputVarType& _obj) {
/// Parses an object from a BSON var.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const InputVarType& _obj) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _obj);
}
}
/// Parses an BSON object using reflection.
template <class T, class... Ps>
auto read(const uint8_t* _bytes, const size_t _size) {
/// Parses an BSON object using reflection.
template <class T, class... Ps>
auto read(const uint8_t* _bytes, const size_t _size) {
Reader::BSONValue value;
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_type = BSON_TYPE_DOCUMENT;
auto doc = InputVarType{&value};
auto doc = InputVarType {&value};
return read<T, Ps...>(doc);
}
}
/// Parses an BSON object using reflection.
template <class T, class... Ps>
auto read(const char* _bytes, const size_t _size) {
/// Parses an BSON object using reflection.
template <class T, class... Ps>
auto read(const char* _bytes, const size_t _size) {
return read<T, Ps...>(reinterpret_cast<const uint8_t*>(_bytes), _size);
}
}
/// Parses an object from BSON using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
/// Parses an object from BSON using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
return read<T, Ps...>(_bytes.data(), _bytes.size());
}
}
/// Parses an object from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
/// Parses an object from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
std::istreambuf_iterator<char> begin(_stream), end;
auto bytes = std::vector<char>(begin, end);
return read<T, Ps...>(bytes.data(), bytes.size());
}
}
} // namespace bson
} // namespace bson
} // namespace rfl
#endif

View file

@ -10,17 +10,17 @@
#include "write.hpp"
namespace rfl {
namespace bson {
namespace bson {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
const auto write_func = [](const auto& _obj, auto& _stream) -> auto& {
return write<Ps...>(_obj, _stream);
};
return rfl::io::save_bytes(_fname, _obj, write_func);
}
}
} // namespace bson
} // namespace bson
} // namespace rfl
#endif

View file

@ -2,7 +2,6 @@
#define RFL_BSON_WRITE_HPP_
#include <bson/bson.h>
#include <ostream>
#include <sstream>
#include <string>
@ -13,12 +12,12 @@
#include "Parser.hpp"
namespace rfl {
namespace bson {
namespace bson {
/// Returns BSON bytes. Careful: It is the responsibility of the caller to call
/// bson_free on the returned pointer.
template <class... Ps>
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
/// Returns BSON bytes. Careful: It is the responsibility of the caller to
/// call bson_free on the returned pointer.
template <class... Ps>
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
using T = std::remove_cvref_t<decltype(_obj)>;
using ParentType = parsing::Parent<Writer>;
bson_t* doc = nullptr;
@ -29,33 +28,33 @@ std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
bson_writer_begin(bson_writer, &doc);
const auto rfl_writer = Writer(doc);
Parser<T, Processors<Ps...>>::write(rfl_writer, _obj,
typename ParentType::Root{});
typename ParentType::Root {});
bson_writer_end(bson_writer);
const auto len = bson_writer_get_length(bson_writer);
bson_writer_destroy(bson_writer);
return std::make_pair(buf, len);
}
}
/// Returns BSON bytes.
template <class... Ps>
std::vector<char> write(const auto& _obj) noexcept {
/// Returns BSON bytes.
template <class... Ps>
std::vector<char> write(const auto& _obj) noexcept {
auto [buf, len] = to_buffer<Ps...>(_obj);
const auto result = std::vector<char>(reinterpret_cast<char*>(buf),
reinterpret_cast<char*>(buf) + len);
bson_free(buf);
return result;
}
}
/// Writes a BSON into an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept {
/// Writes a BSON into an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept {
auto [buf, len] = to_buffer<Ps...>(_obj);
_stream.write(reinterpret_cast<const char*>(buf), len);
bson_free(buf);
return _stream;
}
}
} // namespace bson
} // namespace bson
} // namespace rfl
#endif // BSON_PARSER_HPP_

View file

@ -6,40 +6,46 @@
#include "Writer.hpp"
namespace rfl {
namespace parsing {
namespace parsing {
/// CBOR requires us to explicitly set the number of fields in advance. Because
/// of that, we require all of the fields and then set them to nullptr, if
/// necessary.
template <class ProcessorsType, class... FieldTypes>
requires AreReaderAndWriter<cbor::Reader, cbor::Writer,
/// CBOR requires us to explicitly set the number of fields in advance.
/// Because of that, we require all of the fields and then set them to
/// nullptr, if necessary.
template <class ProcessorsType, class... FieldTypes>
requires AreReaderAndWriter<cbor::Reader,
cbor::Writer,
NamedTuple<FieldTypes...>>
struct Parser<cbor::Reader, cbor::Writer, NamedTuple<FieldTypes...>,
struct Parser<cbor::Reader,
cbor::Writer,
NamedTuple<FieldTypes...>,
ProcessorsType>
: public NamedTupleParser<cbor::Reader, cbor::Writer,
: public NamedTupleParser<cbor::Reader,
cbor::Writer,
/*_ignore_empty_containers=*/false,
/*_all_required=*/true, ProcessorsType,
FieldTypes...> {
};
/*_all_required=*/true,
ProcessorsType,
FieldTypes...> {};
template <class ProcessorsType, class... Ts>
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, std::tuple<Ts...>>
struct Parser<cbor::Reader, cbor::Writer, std::tuple<Ts...>, ProcessorsType>
: public TupleParser<cbor::Reader, cbor::Writer,
template <class ProcessorsType, class... Ts>
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, std::tuple<Ts...>>
struct Parser<cbor::Reader, cbor::Writer, std::tuple<Ts...>, ProcessorsType>
: public TupleParser<cbor::Reader,
cbor::Writer,
/*_ignore_empty_containers=*/false,
/*_all_required=*/true, ProcessorsType, Ts...> {
};
/*_all_required=*/true,
ProcessorsType,
Ts...> {};
} // namespace parsing
} // namespace parsing
} // namespace rfl
namespace rfl {
namespace cbor {
namespace cbor {
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
}
}
} // namespace rfl
#endif

View file

@ -1,9 +1,8 @@
#ifndef RFL_CBOR_READER_HPP_
#define RFL_CBOR_READER_HPP_
#include <cbor.h>
#include <array>
#include <cbor.h>
#include <concepts>
#include <exception>
#include <map>
@ -22,10 +21,10 @@
#include "../always_false.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
/// Please refer to https://intel.github.io/tinycbor/current/index.html
struct Reader {
/// Please refer to https://intel.github.io/tinycbor/current/index.html
struct Reader {
struct CBORInputArray {
CborValue* val_;
};
@ -43,42 +42,30 @@ struct Reader {
using InputVarType = CBORInputVar;
template <class T>
static constexpr bool has_custom_constructor = (requires(InputVarType var) {
T::from_cbor_obj(var);
});
static constexpr bool has_custom_constructor =
(requires(InputVarType var) { T::from_cbor_obj(var); });
rfl::Result<InputVarType> get_field(
const std::string& _name, const InputObjectType& _obj) const noexcept {
const std::string& _name,
const InputObjectType& _obj) const noexcept {
CborValue val;
auto buffer = std::vector<char>();
auto err = cbor_value_enter_container(_obj.val_, &val);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
size_t length = 0;
err = cbor_value_get_map_length(_obj.val_, &length);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
for (size_t i = 0; i < length; ++i) {
if (!cbor_value_is_text_string(&val)) {
return Error("Expected the key to be a string value.");
}
err = get_string(&val, &buffer);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
err = cbor_value_advance(&val);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (_name == buffer.data()) {
return to_input_var(&val);
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
if (_name == buffer.data()) { return to_input_var(&val); }
err = cbor_value_advance(&val);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
}
return Error("No field named '" + _name + "' was found.");
}
@ -95,9 +82,7 @@ struct Reader {
}
std::vector<char> buffer;
const auto err = get_string(_var.val_, &buffer);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
return std::string(buffer.data());
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
if (!cbor_value_is_boolean(_var.val_)) {
@ -105,36 +90,29 @@ struct Reader {
}
bool result = false;
const auto err = cbor_value_get_boolean(_var.val_, &result);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
return result;
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>() ||
std::is_integral<std::remove_cvref_t<T>>()) {
if (cbor_value_is_integer(_var.val_)) {
std::int64_t result = 0;
const auto err = cbor_value_get_int64(_var.val_, &result);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
return static_cast<T>(result);
} else if (cbor_value_is_float(_var.val_)) {
float result = 0.0;
const auto err = cbor_value_get_float(_var.val_, &result);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
return static_cast<T>(result);
} else if (cbor_value_is_double(_var.val_)) {
double result = 0.0;
const auto err = cbor_value_get_double(_var.val_, &result);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
return static_cast<T>(result);
}
return rfl::Error(
"Could not cast to numeric value. The type must be integral, float "
"Could not cast to numeric value. The type must be integral, "
"float "
"or double.");
} else {
@ -147,7 +125,7 @@ struct Reader {
if (!cbor_value_is_array(_var.val_)) {
return Error("Could not cast to an array.");
}
return InputArrayType{_var.val_};
return InputArrayType {_var.val_};
}
rfl::Result<InputObjectType> to_object(
@ -155,11 +133,12 @@ struct Reader {
if (!cbor_value_is_map(_var.val_)) {
return Error("Could not cast to an object.");
}
return InputObjectType{_var.val_};
return InputObjectType {_var.val_};
}
template <class ArrayReader>
std::optional<Error> read_array(const ArrayReader& _array_reader,
std::optional<Error> read_array(
const ArrayReader& _array_reader,
const InputArrayType& _arr) const noexcept {
CborValue val;
auto buffer = std::vector<char>();
@ -174,9 +153,7 @@ struct Reader {
}
for (size_t i = 0; i < length; ++i) {
const auto err2 = _array_reader.read(to_input_var(&val));
if (err2) {
return err2;
}
if (err2) { return err2; }
err = cbor_value_advance(&val);
if (err != CborNoError && err != CborErrorOutOfMemory) {
return Error(cbor_error_string(err));
@ -186,33 +163,26 @@ struct Reader {
}
template <class ObjectReader>
std::optional<Error> read_object(const ObjectReader& _object_reader,
std::optional<Error> read_object(
const ObjectReader& _object_reader,
const InputObjectType& _obj) const noexcept {
size_t length = 0;
auto err = cbor_value_get_map_length(_obj.val_, &length);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
CborValue val;
err = cbor_value_enter_container(_obj.val_, &val);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
auto buffer = std::vector<char>();
for (size_t i = 0; i < length; ++i) {
err = get_string(&val, &buffer);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
err = cbor_value_advance(&val);
if (err != CborNoError) {
return Error(cbor_error_string(err));
}
if (err != CborNoError) { return Error(cbor_error_string(err)); }
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);
}
@ -224,9 +194,7 @@ struct Reader {
const InputVarType& _var) const noexcept {
try {
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:
@ -234,26 +202,25 @@ struct Reader {
std::vector<char>* _buffer) const noexcept {
size_t length = 0;
auto err = cbor_value_get_string_length(_ptr, &length);
if (err != CborNoError && err != CborErrorOutOfMemory) {
return err;
}
if (err != CborNoError && err != CborErrorOutOfMemory) { return err; }
_buffer->resize(length + 1);
(*_buffer)[length] = '\0';
return cbor_value_copy_text_string(_ptr, _buffer->data(), &length, NULL);
return cbor_value_copy_text_string(_ptr, _buffer->data(), &length,
NULL);
}
InputVarType to_input_var(CborValue* _ptr) const noexcept {
values_->emplace_back(rfl::Box<CborValue>::make(*_ptr));
auto* last_value = values_->back().get();
return InputVarType{last_value};
return InputVarType {last_value};
}
private:
/// Contains the values inside the object.
rfl::Box<std::vector<rfl::Box<CborValue>>> values_;
};
};
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif // JSON_PARSER_HPP_

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_WRITER_HPP_
#include <cbor.h>
#include <exception>
#include <map>
#include <sstream>
@ -19,9 +18,9 @@
#include "../always_false.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
class Writer {
class Writer {
public:
struct CBOROutputArray {
CborEncoder* encoder_;
@ -53,7 +52,7 @@ class Writer {
OutputVarType null_as_root() const noexcept {
cbor_encode_null(encoder_);
return OutputVarType{};
return OutputVarType {};
}
template <class T>
@ -61,38 +60,43 @@ class Writer {
return new_value(_var, encoder_);
}
OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType add_array_to_array(
const size_t _size,
OutputArrayType* _parent) const noexcept {
return new_array(_size, _parent->encoder_);
}
OutputArrayType add_array_to_object(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
return new_array(_size, _parent->encoder_);
}
OutputObjectType add_object_to_array(
const size_t _size, OutputArrayType* _parent) const noexcept {
const size_t _size,
OutputArrayType* _parent) const noexcept {
return new_object(_size, _parent->encoder_);
}
OutputObjectType add_object_to_object(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
return new_object(_size, _parent->encoder_);
}
template <class T>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
const noexcept {
return new_value(_var, _parent->encoder_);
}
template <class T>
OutputVarType add_value_to_object(const std::string_view& _name,
OutputVarType add_value_to_object(
const std::string_view& _name,
const T& _var,
OutputObjectType* _parent) const noexcept {
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
@ -101,14 +105,15 @@ class Writer {
OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept {
cbor_encode_null(_parent->encoder_);
return OutputVarType{};
return OutputVarType {};
}
OutputVarType add_null_to_object(const std::string_view& _name,
OutputVarType add_null_to_object(
const std::string_view& _name,
OutputObjectType* _parent) const noexcept {
cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size());
cbor_encode_null(_parent->encoder_);
return OutputVarType{};
return OutputVarType {};
}
void end_array(OutputArrayType* _arr) const noexcept {
@ -124,18 +129,19 @@ class Writer {
CborEncoder* _parent) const noexcept {
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
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) const noexcept {
subencoders_->emplace_back(rfl::Box<CborEncoder>::make());
cbor_encoder_create_map(_parent, subencoders_->back().get(), _size);
return OutputObjectType{subencoders_->back().get(), _parent};
return OutputObjectType {subencoders_->back().get(), _parent};
}
template <class T>
OutputVarType new_value(const T& _var, CborEncoder* _parent) const noexcept {
OutputVarType new_value(const T& _var,
CborEncoder* _parent) const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
cbor_encode_text_string(_parent, _var.c_str(), _var.size());
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
@ -147,7 +153,7 @@ class Writer {
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
return OutputVarType {};
}
private:
@ -156,9 +162,9 @@ class Writer {
/// Contain all of the subobjects and subarrays.
const rfl::Box<std::vector<rfl::Box<CborEncoder>>> subencoders_;
};
};
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif // CBOR_PARSER_HPP_

View file

@ -7,17 +7,17 @@
#include "read.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
const auto read_bytes = [](const auto& _bytes) {
return read<T, Ps...>(_bytes);
};
return rfl::io::load_bytes(_fname).and_then(read_bytes);
}
}
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_READ_HPP_
#include <cbor.h>
#include <istream>
#include <string>
@ -12,46 +11,46 @@
#include "Reader.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
using InputObjectType = typename Reader::InputObjectType;
using InputVarType = typename Reader::InputVarType;
using InputObjectType = typename Reader::InputObjectType;
using InputVarType = typename Reader::InputVarType;
/// Parses an object from a CBOR var.
template <class T, class... Ps>
auto read(const InputVarType& _obj) {
/// Parses an object from a CBOR var.
template <class T, class... Ps>
auto read(const InputVarType& _obj) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _obj);
}
}
/// Parses an object from CBOR using reflection.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
/// Parses an object from CBOR using reflection.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
const size_t _size) {
CborParser parser;
CborValue value;
cbor_parser_init(reinterpret_cast<const uint8_t*>(_bytes), _size, 0, &parser,
&value);
auto doc = InputVarType{&value};
cbor_parser_init(reinterpret_cast<const uint8_t*>(_bytes), _size, 0,
&parser, &value);
auto doc = InputVarType {&value};
auto result = read<T, Ps...>(doc);
return result;
}
}
/// Parses an object from CBOR using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
/// Parses an object from CBOR using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
return read<T, Ps...>(_bytes.data(), _bytes.size());
}
}
/// Parses an object from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
/// Parses an object from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
std::istreambuf_iterator<char> begin(_stream), end;
auto bytes = std::vector<char>(begin, end);
return read<T, Ps...>(bytes.data(), bytes.size());
}
}
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif

View file

@ -10,17 +10,17 @@
#include "write.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
const auto write_func = [](const auto& _obj, auto& _stream) -> auto& {
return write<Ps...>(_obj, _stream);
};
return rfl::io::save_bytes(_fname, _obj, write_func);
}
}
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_WRITE_HPP_
#include <cbor.h>
#include <cstdint>
#include <ostream>
#include <sstream>
@ -13,10 +12,11 @@
#include "Parser.hpp"
namespace rfl {
namespace cbor {
namespace cbor {
template <class... Ps>
void write_into_buffer(const auto& _obj, CborEncoder* _encoder,
template <class... Ps>
void write_into_buffer(const auto& _obj,
CborEncoder* _encoder,
std::vector<char>* _buffer) noexcept {
using T = std::remove_cvref_t<decltype(_obj)>;
using ParentType = parsing::Parent<Writer>;
@ -24,12 +24,12 @@ void write_into_buffer(const auto& _obj, CborEncoder* _encoder,
_buffer->size(), 0);
const auto writer = Writer(_encoder);
Parser<T, Processors<Ps...>>::write(writer, _obj,
typename ParentType::Root{});
}
typename ParentType::Root {});
}
/// Returns CBOR bytes.
template <class... Ps>
std::vector<char> write(const auto& _obj) noexcept {
/// Returns CBOR bytes.
template <class... Ps>
std::vector<char> write(const auto& _obj) noexcept {
std::vector<char> buffer(4096);
CborEncoder encoder;
write_into_buffer<Ps...>(_obj, &encoder, &buffer);
@ -43,17 +43,17 @@ std::vector<char> write(const auto& _obj) noexcept {
&encoder, reinterpret_cast<uint8_t*>(buffer.data()));
buffer.resize(length);
return buffer;
}
}
/// Writes a CBOR into an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept {
/// Writes a CBOR into an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept {
auto buffer = write<Ps...>(_obj);
_stream.write(buffer.data(), buffer.size());
return _stream;
}
}
} // namespace cbor
} // namespace cbor
} // namespace rfl
#endif

View file

@ -8,8 +8,8 @@
namespace rfl {
template <auto _threshold>
struct EqualTo {
template <auto _threshold>
struct EqualTo {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -28,12 +28,12 @@ struct EqualTo {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::EqualTo{.value_ = value}};
return ValidationType {ValidationType::EqualTo {.value_ = value}};
}
};
};
template <auto _threshold>
struct Minimum {
template <auto _threshold>
struct Minimum {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -52,12 +52,12 @@ struct Minimum {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::Minimum{.value_ = value}};
return ValidationType {ValidationType::Minimum {.value_ = value}};
}
};
};
template <auto _threshold>
struct ExclusiveMinimum {
template <auto _threshold>
struct ExclusiveMinimum {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -76,12 +76,13 @@ struct ExclusiveMinimum {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::ExclusiveMinimum{.value_ = value}};
return ValidationType {
ValidationType::ExclusiveMinimum {.value_ = value}};
}
};
};
template <auto _threshold>
struct Maximum {
template <auto _threshold>
struct Maximum {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -100,12 +101,12 @@ struct Maximum {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::Maximum{.value_ = value}};
return ValidationType {ValidationType::Maximum {.value_ = value}};
}
};
};
template <auto _threshold>
struct ExclusiveMaximum {
template <auto _threshold>
struct ExclusiveMaximum {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -124,12 +125,13 @@ struct ExclusiveMaximum {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::ExclusiveMaximum{.value_ = value}};
return ValidationType {
ValidationType::ExclusiveMaximum {.value_ = value}};
}
};
};
template <auto _threshold>
struct NotEqualTo {
template <auto _threshold>
struct NotEqualTo {
template <class T>
static Result<T> validate(T _value) noexcept {
constexpr auto threshold = static_cast<T>(_threshold);
@ -148,9 +150,9 @@ struct NotEqualTo {
std::is_floating_point_v<T>
? std::variant<double, int>(static_cast<double>(_threshold))
: std::variant<double, int>(static_cast<int>(_threshold));
return ValidationType{ValidationType::NotEqualTo{.value_ = value}};
return ValidationType {ValidationType::NotEqualTo {.value_ = value}};
}
};
};
} // namespace rfl

View file

@ -3,11 +3,11 @@
namespace rfl {
/// Helper class that can be passed to a field
/// to trigger the default value of the type.
struct Default {};
/// Helper class that can be passed to a field
/// to trigger the default value of the type.
struct Default {};
inline static const auto default_value = Default{};
inline static const auto default_value = Default {};
} // namespace rfl

View file

@ -6,9 +6,9 @@
namespace rfl {
/// Allows you to combine several literal types.
template <class... LiteralTypes>
using define_literal_t =
/// Allows you to combine several literal types.
template <class... LiteralTypes>
using define_literal_t =
typename internal::define_literal<LiteralTypes...>::type;
} // namespace rfl

View file

@ -6,8 +6,8 @@
namespace rfl {
template <class... FieldTypes>
using define_named_tuple_t =
template <class... FieldTypes>
using define_named_tuple_t =
typename internal::define_named_tuple<FieldTypes...>::type;
} // namespace rfl

View file

@ -7,8 +7,8 @@
namespace rfl {
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
using define_tagged_union_t =
template <internal::StringLiteral _discriminator, class... TaggedUnionTypes>
using define_tagged_union_t =
typename internal::define_tagged_union<_discriminator,
TaggedUnionTypes...>::type;

View file

@ -7,8 +7,8 @@
namespace rfl {
template <class... Vars>
using define_variant_t = typename internal::define_variant<Vars...>::type;
template <class... Vars>
using define_variant_t = typename internal::define_variant<Vars...>::type;
} // namespace rfl

View file

@ -11,53 +11,55 @@
namespace rfl {
// Converts an enum value to a string.
template <internal::enums::is_scoped_enum EnumType>
std::string enum_to_string(EnumType _enum) {
return rfl::internal::enums::StringConverter<EnumType>::enum_to_string(_enum);
}
// Converts an enum value to a string.
template <internal::enums::is_scoped_enum EnumType>
std::string enum_to_string(EnumType _enum) {
return rfl::internal::enums::StringConverter<EnumType>::enum_to_string(
_enum);
}
// Converts a string to a value of the given enum type.
template <internal::enums::is_scoped_enum EnumType>
rfl::Result<EnumType> string_to_enum(const std::string& _str) {
return rfl::internal::enums::StringConverter<EnumType>::string_to_enum(_str);
}
// Converts a string to a value of the given enum type.
template <internal::enums::is_scoped_enum EnumType>
rfl::Result<EnumType> string_to_enum(const std::string& _str) {
return rfl::internal::enums::StringConverter<EnumType>::string_to_enum(
_str);
}
// Returns a named tuple mapping names of enumerators of the given enum type to
// their values.
template <internal::enums::is_scoped_enum EnumType>
auto get_enumerators() {
// Returns a named tuple mapping names of enumerators of the given enum type
// to their values.
template <internal::enums::is_scoped_enum EnumType>
auto get_enumerators() {
constexpr auto names = internal::enums::get_enum_names<
EnumType, internal::enums::is_flag_enum<EnumType>>();
return internal::enums::names_to_enumerator_named_tuple(names);
}
}
// Returns a named tuple mapping names of enumerators of the given enum type to
// their underlying values.
template <internal::enums::is_scoped_enum EnumType>
auto get_underlying_enumerators() {
// Returns a named tuple mapping names of enumerators of the given enum type
// to their underlying values.
template <internal::enums::is_scoped_enum EnumType>
auto get_underlying_enumerators() {
constexpr auto names = internal::enums::get_enum_names<
EnumType, internal::enums::is_flag_enum<EnumType>>();
return internal::enums::names_to_underlying_enumerator_named_tuple(names);
}
}
// Returns an std::array containing pairs of enumerator names (as
// std::string_view) and values.
template <internal::enums::is_scoped_enum EnumType>
constexpr auto get_enumerator_array() {
// Returns an std::array containing pairs of enumerator names (as
// std::string_view) and values.
template <internal::enums::is_scoped_enum EnumType>
constexpr auto get_enumerator_array() {
constexpr auto names = internal::enums::get_enum_names<
EnumType, internal::enums::is_flag_enum<EnumType>>();
return internal::enums::names_to_enumerator_array(names);
}
}
// Returns an std::array containing pairs of enumerator names (as
// std::string_view) and underlying values.
template <internal::enums::is_scoped_enum EnumType>
constexpr auto get_underlying_enumerator_array() {
// Returns an std::array containing pairs of enumerator names (as
// std::string_view) and underlying values.
template <internal::enums::is_scoped_enum EnumType>
constexpr auto get_underlying_enumerator_array() {
constexpr auto names = internal::enums::get_enum_names<
EnumType, internal::enums::is_flag_enum<EnumType>>();
return internal::enums::names_to_underlying_enumerator_array(names);
}
}
} // namespace rfl

View file

@ -10,9 +10,10 @@
namespace rfl {
/// Extracts a Literal containing all of the discriminators from a TaggedUnion.
template <class TaggedUnionType>
using extract_discriminators_t =
/// Extracts a Literal containing all of the discriminators from a
/// TaggedUnion.
template <class TaggedUnionType>
using extract_discriminators_t =
typename internal::extract_discriminators<TaggedUnionType>::type;
} // namespace rfl

View file

@ -8,9 +8,9 @@
namespace rfl {
/// Returns a rfl::Literal containing the field names of struct T.
template <class T>
using field_names_t = typename std::invoke_result<
/// Returns a rfl::Literal containing the field names of struct T.
template <class T>
using field_names_t = typename std::invoke_result<
decltype(internal::get_field_names<std::remove_cvref_t<T>>)>::type;
} // namespace rfl

View file

@ -10,8 +10,8 @@
namespace rfl {
template <internal::StringLiteral _field_name, class T>
using field_type_t = typename internal::FieldType<_field_name, T>::Type;
template <internal::StringLiteral _field_name, class T>
using field_type_t = typename internal::FieldType<_field_name, T>::Type;
} // namespace rfl

View file

@ -6,11 +6,11 @@
namespace rfl {
/// Returns meta-information about the fields.
template <class T>
auto fields() {
/// Returns meta-information about the fields.
template <class T>
auto fields() {
return internal::get_meta_fields<named_tuple_t<T>>();
}
}
} // namespace rfl

View file

@ -6,12 +6,12 @@
#include "Writer.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
template <class T, class ProcessorsType>
using Parser = parsing::Parser<Reader, Writer, T, ProcessorsType>;
}
}
} // namespace rfl
#endif

View file

@ -1,9 +1,8 @@
#ifndef FLEXBUF_READER_HPP_
#define FLEXBUF_READER_HPP_
#include <flatbuffers/flexbuffers.h>
#include <exception>
#include <flatbuffers/flexbuffers.h>
#include <map>
#include <sstream>
#include <stdexcept>
@ -16,9 +15,9 @@
#include "../always_false.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
struct Reader {
struct Reader {
using InputArrayType = flexbuffers::Vector;
using InputObjectType = flexbuffers::Map;
using InputVarType = flexbuffers::Reference;
@ -28,26 +27,29 @@ struct Reader {
template <class T>
struct has_from_flexbuf<
T, std::enable_if_t<std::is_invocable_r<T, decltype(T::from_flexbuf),
T,
std::enable_if_t<std::is_invocable_r<T,
decltype(T::from_flexbuf),
InputVarType>::value>>
: std::true_type {};
template <class T>
struct has_from_flexbuf<
T, std::enable_if_t<std::is_invocable_r<
rfl::Result<T>, decltype(T::from_flexbuf), InputVarType>::value>>
T,
std::enable_if_t<std::is_invocable_r<rfl::Result<T>,
decltype(T::from_flexbuf),
InputVarType>::value>>
: std::true_type {};
template <class T>
static constexpr bool has_custom_constructor = has_from_flexbuf<T>::value;
rfl::Result<InputVarType> get_field(
const std::string& _name, const InputObjectType& _obj) const noexcept {
const std::string& _name,
const InputObjectType& _obj) const noexcept {
const auto keys = _obj.Keys();
for (size_t i = 0; i < keys.size(); ++i) {
if (_name == keys[i].AsString().c_str()) {
return _obj.Values()[i];
}
if (_name == keys[i].AsString().c_str()) { return _obj.Values()[i]; }
}
return rfl::Error("Map does not contain any element called '" + _name +
"'.");
@ -85,20 +87,20 @@ struct Reader {
}
template <class ArrayReader>
std::optional<Error> read_array(const ArrayReader& _array_reader,
std::optional<Error> read_array(
const ArrayReader& _array_reader,
const InputArrayType& _arr) const noexcept {
const auto size = _arr.size();
for (size_t i = 0; i < size; ++i) {
const auto err = _array_reader.read(InputVarType(_arr[i]));
if (err) {
return err;
}
if (err) { return err; }
}
return std::nullopt;
}
template <class ObjectReader>
std::optional<Error> read_object(const ObjectReader& _object_reader,
std::optional<Error> read_object(
const ObjectReader& _object_reader,
const InputObjectType& _obj) const noexcept {
const auto keys = _obj.Keys();
const auto values = _obj.Values();
@ -122,9 +124,7 @@ struct Reader {
rfl::Result<InputObjectType> to_object(
const InputVarType& _var) const noexcept {
if (!_var.IsMap()) {
return rfl::Error("Could not cast to Map!");
}
if (!_var.IsMap()) { return rfl::Error("Could not cast to Map!"); }
return _var.AsMap();
}
@ -133,13 +133,11 @@ struct Reader {
const InputVarType& _var) const noexcept {
try {
return T::from_flexbuf(_var);
} catch (std::exception& e) {
return rfl::Error(e.what());
} catch (std::exception& e) { return rfl::Error(e.what()); }
}
}
};
};
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -1,9 +1,8 @@
#ifndef FLEXBUF_WRITER_HPP_
#define FLEXBUF_WRITER_HPP_
#include <flatbuffers/flexbuffers.h>
#include <exception>
#include <flatbuffers/flexbuffers.h>
#include <functional>
#include <map>
#include <optional>
@ -19,9 +18,9 @@
#include "../always_false.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
struct Writer {
struct Writer {
struct OutputArray {
size_t start_;
};
@ -50,7 +49,7 @@ struct Writer {
OutputVarType null_as_root() const noexcept {
fbb_->Null();
return OutputVarType{};
return OutputVarType {};
}
template <class T>
@ -58,36 +57,41 @@ struct Writer {
return insert_value(_var);
}
OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType add_array_to_array(
const size_t _size,
OutputArrayType* _parent) const noexcept {
return new_array();
}
OutputArrayType add_array_to_object(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
return new_array(_name);
}
OutputObjectType add_object_to_array(
const size_t _size, OutputArrayType* _parent) const noexcept {
const size_t _size,
OutputArrayType* _parent) const noexcept {
return new_object();
}
OutputObjectType add_object_to_object(
const std::string_view& _name, const size_t _size,
const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept {
return new_object(_name);
}
template <class T>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent)
const noexcept {
return insert_value(_var);
}
template <class T>
OutputVarType add_value_to_object(const std::string_view& _name,
OutputVarType add_value_to_object(
const std::string_view& _name,
const T& _var,
OutputObjectType* _parent) const noexcept {
return insert_value(_name, _var);
@ -95,13 +99,14 @@ struct Writer {
OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept {
fbb_->Null();
return OutputVarType{};
return OutputVarType {};
}
OutputVarType add_null_to_object(const std::string_view& _name,
OutputVarType add_null_to_object(
const std::string_view& _name,
OutputObjectType* _parent) const noexcept {
fbb_->Null(_name.data());
return OutputVarType{};
return OutputVarType {};
}
void end_array(OutputArrayType* _arr) const noexcept {
@ -127,7 +132,7 @@ struct Writer {
} else {
static_assert(always_false_v<T>, "Unsupported type");
}
return OutputVarType{};
return OutputVarType {};
}
template <class T>
@ -143,34 +148,35 @@ struct Writer {
} else {
static_assert(always_false_v<T>, "Unsupported type");
}
return OutputVarType{};
return OutputVarType {};
}
OutputArrayType new_array(const std::string_view& _name) const noexcept {
const auto start = fbb_->StartVector(_name.data());
return OutputArrayType{start};
return OutputArrayType {start};
}
OutputArrayType new_array() const noexcept {
const auto start = fbb_->StartVector();
return OutputArrayType{start};
return OutputArrayType {start};
}
OutputObjectType new_object(const std::string_view& _name) const noexcept {
OutputObjectType new_object(
const std::string_view& _name) const noexcept {
const auto start = fbb_->StartMap(_name.data());
return OutputObjectType{start};
return OutputObjectType {start};
}
OutputObjectType new_object() const noexcept {
const auto start = fbb_->StartMap();
return OutputObjectType{start};
return OutputObjectType {start};
}
private:
Ref<flexbuffers::Builder> fbb_;
};
};
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -6,17 +6,17 @@
#include "read.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
template <class T, class... Ps>
Result<T> load(const std::string& _fname) {
const auto read_bytes = [](const auto& _bytes) {
return read<T, Ps...>(_bytes);
};
return rfl::io::load_bytes(_fname).and_then(read_bytes);
}
}
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -2,7 +2,6 @@
#define FLEXBUF_READ_HPP_
#include <flatbuffers/flexbuffers.h>
#include <istream>
#include <vector>
@ -11,40 +10,40 @@
#include "Parser.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
using InputVarType = typename Reader::InputVarType;
using InputVarType = typename Reader::InputVarType;
/// Parses an object from flexbuf var.
template <class T, class... Ps>
auto read(const InputVarType& _obj) {
/// Parses an object from flexbuf var.
template <class T, class... Ps>
auto read(const InputVarType& _obj) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _obj);
}
}
/// Parses an object from flexbuf using reflection.
template <class T, class... Ps>
auto read(const char* _bytes, const size_t _size) {
/// Parses an object from flexbuf using reflection.
template <class T, class... Ps>
auto read(const char* _bytes, const size_t _size) {
const InputVarType root =
flexbuffers::GetRoot(reinterpret_cast<const uint8_t*>(_bytes), _size);
return read<T, Ps...>(root);
}
}
/// Parses an object from flexbuf using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
/// Parses an object from flexbuf using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes) {
return read<T, Ps...>(_bytes.data(), _bytes.size());
}
}
/// Parses an object directly from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
/// Parses an object directly from a stream.
template <class T, class... Ps>
auto read(std::istream& _stream) {
std::istreambuf_iterator<char> begin(_stream), end;
const auto bytes = std::vector<char>(begin, end);
return read<T, Ps...>(bytes.data(), bytes.size());
}
}
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -10,17 +10,17 @@
#include "write.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj) {
const auto write_func = [](const auto& _obj, auto& _stream) -> auto& {
return write<Ps...>(_obj, _stream);
};
return rfl::io::save_bytes(_fname, _obj, write_func);
}
}
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -1,9 +1,8 @@
#ifndef FLEXBUF_WRITE_HPP_
#define FLEXBUF_WRITE_HPP_
#include <flatbuffers/flexbuffers.h>
#include <cstddef>
#include <flatbuffers/flexbuffers.h>
#include <ostream>
#include <sstream>
#include <vector>
@ -14,37 +13,38 @@
#include "Parser.hpp"
namespace rfl {
namespace flexbuf {
namespace flexbuf {
template <class... Ps>
std::vector<uint8_t> to_buffer(const auto& _obj) {
template <class... Ps>
std::vector<uint8_t> to_buffer(const auto& _obj) {
using T = std::remove_cvref_t<decltype(_obj)>;
using ParentType = parsing::Parent<Writer>;
const auto fbb = Ref<flexbuffers::Builder>::make();
auto w = Writer(fbb);
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
Parser<T, Processors<Ps...>>::write(w, _obj,
typename ParentType::Root {});
fbb->Finish();
return fbb->GetBuffer();
}
}
/// Writes an object to flexbuf.
template <class... Ps>
std::vector<char> write(const auto& _obj) {
/// Writes an object to flexbuf.
template <class... Ps>
std::vector<char> write(const auto& _obj) {
const auto buffer = to_buffer<Ps...>(_obj);
const auto data = reinterpret_cast<const char*>(buffer.data());
return std::vector<char>(data, data + buffer.size());
}
}
/// Writes an object to an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) {
/// Writes an object to an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream) {
const auto buffer = to_buffer<Ps...>(_obj);
const auto data = reinterpret_cast<const char*>(buffer.data());
_stream.write(data, buffer.size());
return _stream;
}
}
} // namespace flexbuf
} // namespace flexbuf
} // namespace rfl
#endif

View file

@ -12,31 +12,32 @@
namespace rfl {
/// Generates the struct T from a named tuple.
template <class T, class NamedTupleType>
auto from_named_tuple(NamedTupleType&& _n) {
/// Generates the struct T from a named tuple.
template <class T, class NamedTupleType>
auto from_named_tuple(NamedTupleType&& _n) {
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
RequiredType>()) {
return from_named_tuple<T>(RequiredType(std::forward<NamedTupleType>(_n)));
return from_named_tuple<T>(
RequiredType(std::forward<NamedTupleType>(_n)));
} 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);
} else {
return internal::move_from_named_tuple<T>(_n);
}
} else {
if constexpr (std::is_lvalue_reference<NamedTupleType>{}) {
if constexpr (std::is_lvalue_reference<NamedTupleType> {}) {
return internal::copy_from_tuple<T>(_n.values());
} else {
return internal::move_from_tuple<T>(std::move(_n.values()));
}
}
}
}
/// Generates the struct T from a named tuple.
template <class T, class NamedTupleType>
auto from_named_tuple(const NamedTupleType& _n) {
/// Generates the struct T from a named tuple.
template <class T, class NamedTupleType>
auto from_named_tuple(const NamedTupleType& _n) {
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
RequiredType>()) {
@ -46,7 +47,7 @@ auto from_named_tuple(const NamedTupleType& _n) {
} else {
return internal::copy_from_tuple<T>(_n.values());
}
}
}
} // namespace rfl

View file

@ -6,42 +6,42 @@
namespace rfl {
/// Gets a field by index.
template <int _index, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
/// Gets a field by index.
template <int _index, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get<_index>(_tup);
}
}
/// Gets a field by name.
template <internal::StringLiteral _field_name, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
/// Gets a field by name.
template <internal::StringLiteral _field_name, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get<_field_name>(_tup);
}
}
/// Gets a field by the field type.
template <class Field, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
/// Gets a field by the field type.
template <class Field, class NamedTupleType>
inline auto& get(NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get<Field>(_tup);
}
}
/// Gets a field by index.
template <int _index, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
/// Gets a field by index.
template <int _index, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get_const<_index>(_tup);
}
}
/// Gets a field by name.
template <internal::StringLiteral _field_name, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
/// Gets a field by name.
template <internal::StringLiteral _field_name, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get_const<_field_name>(
_tup);
}
}
/// Gets a field by the field type.
template <class Field, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
/// Gets a field by the field type.
template <class Field, class NamedTupleType>
inline const auto& get(const NamedTupleType& _tup) {
return internal::Getter<NamedTupleType>::template get_const<Field>(_tup);
}
}
} // namespace rfl

View file

@ -8,26 +8,26 @@
#include "to_std_array.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
requires std::is_array_v<T>
struct Array {
template <class T>
requires std::is_array_v<T>
struct Array {
using Type = T;
using StdArrayType = to_std_array_t<T>;
Array() = default;
Array(const StdArrayType &_arr) : arr_(_arr) {}
Array(StdArrayType &&_arr) : arr_(std::move(_arr)) {}
Array(const T &_arr) : arr_(to_std_array(_arr)) {}
Array(T &&_arr) : arr_(to_std_array(_arr)) {}
Array(const StdArrayType& _arr) : arr_(_arr) {}
Array(StdArrayType&& _arr) : arr_(std::move(_arr)) {}
Array(const T& _arr) : arr_(to_std_array(_arr)) {}
Array(T&& _arr) : arr_(to_std_array(_arr)) {}
~Array() = default;
StdArrayType arr_;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -8,13 +8,13 @@
#include "copy_to_field_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
using field_tuple_t =
template <class T>
using field_tuple_t =
typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
}
}
} // namespace rfl
#endif

View file

@ -8,16 +8,16 @@
#include <unordered_map>
namespace rfl {
namespace internal {
namespace internal {
template <int N>
struct Fields {
template <int N>
struct Fields {
std::array<std::string, N> names_;
std::unordered_map<std::string_view, std::int16_t> indices_;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -9,16 +9,16 @@
namespace rfl::internal {
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
template <class NamedTupleType>
struct Getter;
template <class NamedTupleType>
struct Getter;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// Default case - anything that cannot be explicitly matched.
template <class NamedTupleType>
struct Getter {
/// Default case - anything that cannot be explicitly matched.
template <class NamedTupleType>
struct Getter {
public:
/// Retrieves the indicated value from the tuple.
template <int _index>
@ -77,13 +77,13 @@ struct Getter {
"well.");
return Getter<NamedTupleType>::template get_const<index>(_tup);
}
};
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// For handling std::variant.
template <class... NamedTupleTypes>
struct Getter<std::variant<NamedTupleTypes...>> {
/// For handling std::variant.
template <class... NamedTupleTypes>
struct Getter<std::variant<NamedTupleTypes...>> {
public:
/// Retrieves the indicated value from the tuple.
template <int _index>
@ -147,9 +147,9 @@ struct Getter<std::variant<NamedTupleTypes...>> {
};
return std::visit(apply, _tup);
}
};
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
} // namespace rfl::internal

View file

@ -6,14 +6,14 @@
#include "../Result.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class Class, typename T>
concept HasValidation = requires(Class obj, T value) {
template <class Class, typename T>
concept HasValidation = requires(Class obj, T value) {
{ Class::validate(value) } -> std::same_as<rfl::Result<T>>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -5,11 +5,11 @@
#include <mutex>
namespace rfl {
namespace internal {
namespace internal {
/// For a thread-safe memoization pattern.
template <class T>
class Memoization {
/// For a thread-safe memoization pattern.
template <class T>
class Memoization {
public:
Memoization() { flag_.clear(); }
@ -19,15 +19,11 @@ class Memoization {
/// Returns the underlying value.
template <class F>
const T& value(const F& _f) {
if (flag_.test()) {
return value_;
}
if (flag_.test()) { return value_; }
std::lock_guard<std::mutex> guard(mtx_);
if (flag_.test()) {
return value_;
}
if (flag_.test()) { return value_; }
_f(&value_);
@ -45,9 +41,9 @@ class Memoization {
/// The type to be initialized.
T value_;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -5,8 +5,8 @@
namespace rfl::internal {
template <class T, bool _skip_serialization, bool _skip_deserialization>
class Skip {
template <class T, bool _skip_serialization, bool _skip_deserialization>
class Skip {
private:
using SelfType = Skip<T, _skip_serialization, _skip_deserialization>;
@ -39,15 +39,19 @@ class Skip {
template <class U, bool _skip_s, bool _skip_d>
Skip(Skip<U, _skip_s, _skip_d>&& _other) : value_(_other.get()) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Skip(const U& _value) : value_(_value) {}
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Skip(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
template <class U, bool _skip_s, bool _skip_d,
template <class U,
bool _skip_s,
bool _skip_d,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
Skip(const Skip<U, _skip_s, _skip_d>& _skip) : value_(_skip.value()) {}
@ -85,7 +89,8 @@ class Skip {
}
/// Assigns the underlying object.
template <class U, typename std::enable_if<std::is_convertible_v<U, Type>,
template <class U,
typename std::enable_if<std::is_convertible_v<U, Type>,
bool>::type = true>
auto& operator=(const U& _value) {
value_ = _value;
@ -139,7 +144,7 @@ class Skip {
private:
/// The underlying value
T value_;
};
};
} // namespace rfl::internal

View file

@ -7,14 +7,14 @@
#include <string_view>
namespace rfl {
namespace internal {
namespace internal {
/// Normal strings cannot be used as template
/// parameters, but this can. This is needed
/// for the parameters names in the NamedTuples.
template <size_t N>
struct StringLiteral {
constexpr StringLiteral(const auto... _chars) : arr_{_chars..., '\0'} {}
/// Normal strings cannot be used as template
/// parameters, but this can. This is needed
/// for the parameters names in the NamedTuples.
template <size_t N>
struct StringLiteral {
constexpr StringLiteral(const auto... _chars) : arr_ {_chars..., '\0'} {}
constexpr StringLiteral(const std::array<char, N> _arr) : arr_(_arr) {}
@ -30,25 +30,23 @@ struct StringLiteral {
return std::string_view(std::data(arr_), N - 1);
}
std::array<char, N> arr_{};
};
std::array<char, N> arr_ {};
};
template <size_t N1, size_t N2>
constexpr inline bool operator==(const StringLiteral<N1>& _first,
template <size_t N1, size_t N2>
constexpr inline bool operator==(const StringLiteral<N1>& _first,
const StringLiteral<N2>& _second) {
if constexpr (N1 != N2) {
return false;
}
if constexpr (N1 != N2) { return false; }
return _first.string_view() == _second.string_view();
}
}
template <size_t N1, size_t N2>
constexpr inline bool operator!=(const StringLiteral<N1>& _first,
template <size_t N1, size_t N2>
constexpr inline bool operator!=(const StringLiteral<N1>& _first,
const StringLiteral<N2>& _second) {
return !(_first == _second);
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -2,12 +2,13 @@
#define RFL_INTERNAL_VISITTREE_HPP_
namespace rfl {
namespace internal {
namespace internal {
struct VisitTree {
struct VisitTree {
/// Evaluates a visitor pattern using a tree-like structure.
template <int _begin, int _end, class Visitor, class... Args>
static inline auto visit(const auto& _v, const int _i,
static inline auto visit(const auto& _v,
const int _i,
const Args&... _args) {
static_assert(_end > _begin, "_end needs to be greater than _begin.");
if constexpr (_end - _begin == 1) {
@ -21,9 +22,9 @@ struct VisitTree {
}
}
}
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -6,11 +6,11 @@
#include "StringLiteral.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Necessary for the VisitTree structure.
template <class Visitor, internal::StringLiteral... _fields>
struct VisitorWrapper {
/// Necessary for the VisitTree structure.
template <class Visitor, internal::StringLiteral... _fields>
struct VisitorWrapper {
/// Calls the underlying visitor when required to do so.
template <int _i, class... Args>
inline auto visit(const Args&... _args) const {
@ -19,9 +19,9 @@ struct VisitorWrapper {
/// The underlying visitor.
const Visitor* visitor_;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif // RFL_VISIT_HPP_

View file

@ -8,19 +8,19 @@
#include "is_field.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class TupleType, int _i = 0>
constexpr bool all_fields() {
template <class TupleType, int _i = 0>
constexpr bool all_fields() {
if constexpr (_i == std::tuple_size_v<TupleType>) {
return true;
} else {
using T = std::tuple_element_t<_i, TupleType>;
return is_field_v<T> && all_fields<TupleType, _i + 1>();
}
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -6,14 +6,14 @@
#include <type_traits>
#include "../Field.hpp"
#include "lit_name.hpp"
#include "../make_named_tuple.hpp"
#include "lit_name.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class FieldNames, class... Fields>
auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple,
template <class FieldNames, class... Fields>
auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple,
Fields&&... _fields) {
constexpr auto size =
std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
@ -28,9 +28,9 @@ auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple,
return copy_flattened_tuple_to_named_tuple<FieldNames>(
_flattened_tuple, std::move(_fields)..., std::move(new_field));
}
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,17 +4,17 @@
#include "move_from_named_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Creates a struct of type T from a named tuple.
/// All fields of the struct must be an rfl::Field.
template <class T, class NamedTupleType>
T copy_from_named_tuple(const NamedTupleType& _n) {
/// Creates a struct of type T from a named tuple.
/// All fields of the struct must be an rfl::Field.
template <class T, class NamedTupleType>
T copy_from_named_tuple(const NamedTupleType& _n) {
auto n = _n;
return move_from_named_tuple<T>(std::move(n));
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,17 +4,17 @@
#include "move_from_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Creates a struct of type T from a tuple by copying the underlying
/// fields.
template <class T, class TupleType>
T copy_from_tuple(const TupleType& _t) {
/// Creates a struct of type T from a tuple by copying the underlying
/// fields.
template <class T, class TupleType>
T copy_from_tuple(const TupleType& _t) {
auto t = _t;
return move_from_tuple<T, TupleType>(std::move(t));
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,15 +4,15 @@
#include "move_to_field_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
auto copy_to_field_tuple(const T& _t) {
template <class T>
auto copy_to_field_tuple(const T& _t) {
auto t = _t;
return move_to_field_tuple(std::move(t));
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,26 +4,30 @@
#include "../Literal.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Allows you to combine several literals.
template <class... LiteralTypes>
struct define_literal;
/// Allows you to combine several literals.
template <class... LiteralTypes>
struct define_literal;
/// General case
template <StringLiteral... _content1, StringLiteral... _content2, class... Tail>
struct define_literal<Literal<_content1...>, Literal<_content2...>, Tail...> {
/// General case
template <StringLiteral... _content1,
StringLiteral... _content2,
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
template <StringLiteral... _content>
struct define_literal<Literal<_content...>> {
/// Special case - only a single literal is left
template <StringLiteral... _content>
struct define_literal<Literal<_content...>> {
using type = Literal<_content...>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,43 +4,45 @@
#include "../NamedTuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class... FieldTypes>
struct define_named_tuple;
template <class... FieldTypes>
struct define_named_tuple;
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - all types are fields.
template <class Head, class... Tail>
struct define_named_tuple<Head, Tail...> {
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - all types are fields.
template <class Head, class... Tail>
struct define_named_tuple<Head, Tail...> {
using type = typename define_named_tuple<NamedTuple<Head>, Tail...>::type;
};
};
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - first type is NamedTuple, second type is field.
template <class Head, class... TupContent, class... Tail>
struct define_named_tuple<NamedTuple<TupContent...>, Head, Tail...> {
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - first type is NamedTuple, second type is field.
template <class Head, class... TupContent, class... Tail>
struct define_named_tuple<NamedTuple<TupContent...>, Head, Tail...> {
using type = typename define_named_tuple<NamedTuple<TupContent..., Head>,
Tail...>::type;
};
};
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - first type is NamedTuple, second type is also NamedTuple.
template <class... TupContent, class... TupContent2, class... Tail>
struct define_named_tuple<NamedTuple<TupContent...>, NamedTuple<TupContent2...>,
/// Allows you to combine several named tuples and/or additional fields.
/// Recursive case - first type is NamedTuple, second type is also
/// NamedTuple.
template <class... TupContent, class... TupContent2, class... Tail>
struct define_named_tuple<NamedTuple<TupContent...>,
NamedTuple<TupContent2...>,
Tail...> {
using type =
typename define_named_tuple<NamedTuple<TupContent..., TupContent2...>,
Tail...>::type;
};
};
/// Allows you to combine several named tuples and/or additional fields.
template <class... TupContent>
struct define_named_tuple<NamedTuple<TupContent...>> {
/// Allows you to combine several named tuples and/or additional fields.
template <class... TupContent>
struct define_named_tuple<NamedTuple<TupContent...>> {
using type = NamedTuple<TupContent...>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -5,53 +5,64 @@
#include "StringLiteral.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Allows you to combine several tagged unions.
template <StringLiteral _discriminator, class... TaggedUnionTypes>
struct define_tagged_union;
/// Allows you to combine several tagged unions.
template <StringLiteral _discriminator, class... TaggedUnionTypes>
struct define_tagged_union;
/// Recursive case - both tagged union.
template <StringLiteral _discriminator, class... NamedTupleTypes1,
class... NamedTupleTypes2, class... Tail>
struct define_tagged_union<
_discriminator, TaggedUnion<_discriminator, NamedTupleTypes1...>,
TaggedUnion<_discriminator, NamedTupleTypes2...>, Tail...> {
/// Recursive case - both tagged union.
template <StringLiteral _discriminator,
class... NamedTupleTypes1,
class... NamedTupleTypes2,
class... Tail>
struct define_tagged_union<_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes1...>,
TaggedUnion<_discriminator, NamedTupleTypes2...>,
Tail...> {
using type = typename define_tagged_union<
_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
Tail...>::type;
};
};
/// Recursive case - tagged union plus named tuple.
template <StringLiteral _discriminator, class... NamedTupleTypes,
class... FieldTypes, class... Tail>
struct define_tagged_union<_discriminator,
/// Recursive case - tagged union plus named tuple.
template <StringLiteral _discriminator,
class... NamedTupleTypes,
class... FieldTypes,
class... Tail>
struct define_tagged_union<_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes...>,
NamedTuple<FieldTypes...>, Tail...> {
using type = typename define_tagged_union<
_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes...,
NamedTuple<FieldTypes...>,
Tail...> {
using type =
typename define_tagged_union<_discriminator,
TaggedUnion<_discriminator,
NamedTupleTypes...,
NamedTuple<FieldTypes...>>,
Tail...>::type;
};
};
/// Recursive case - named tuple.
template <StringLiteral _discriminator, class... FieldTypes, class... Tail>
struct define_tagged_union<_discriminator, NamedTuple<FieldTypes...>, Tail...> {
/// Recursive case - named tuple.
template <StringLiteral _discriminator, class... FieldTypes, class... Tail>
struct define_tagged_union<_discriminator,
NamedTuple<FieldTypes...>,
Tail...> {
using type = typename define_tagged_union<
_discriminator, TaggedUnion<_discriminator, NamedTuple<FieldTypes...>>,
_discriminator,
TaggedUnion<_discriminator, NamedTuple<FieldTypes...>>,
Tail...>::type;
};
};
/// Special case - only a single TaggedUnion is left.
template <StringLiteral _discriminator, class... NamedTupleTypes>
struct define_tagged_union<_discriminator,
/// Special case - only a single TaggedUnion is left.
template <StringLiteral _discriminator, class... NamedTupleTypes>
struct define_tagged_union<
_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes...>> {
using type = TaggedUnion<_discriminator, NamedTupleTypes...>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -4,39 +4,41 @@
#include <variant>
namespace rfl {
namespace internal {
namespace internal {
/// Allows you to combine several variants.
template <class... Vars>
struct define_variant;
/// Allows you to combine several variants.
template <class... Vars>
struct define_variant;
/// Recursive case - both variants.
template <class... Vars1, class... Vars2, class... Tail>
struct define_variant<std::variant<Vars1...>, std::variant<Vars2...>, Tail...> {
/// Recursive case - both variants.
template <class... Vars1, class... Vars2, class... Tail>
struct define_variant<std::variant<Vars1...>,
std::variant<Vars2...>,
Tail...> {
using type = typename define_variant<std::variant<Vars1..., Vars2...>,
Tail...>::type;
};
};
/// Recursive case - variant plus other type.
template <class... Vars, class Head, class... Tail>
struct define_variant<std::variant<Vars...>, Head, Tail...> {
/// Recursive case - variant plus other type.
template <class... Vars, class Head, class... Tail>
struct define_variant<std::variant<Vars...>, Head, Tail...> {
using type =
typename define_variant<std::variant<Vars..., Head>, Tail...>::type;
};
};
/// Recursive case - other type.
template <class Head, class... Tail>
struct define_variant<Head, Tail...> {
/// Recursive case - other type.
template <class Head, class... Tail>
struct define_variant<Head, Tail...> {
using type = typename define_variant<std::variant<Head>, Tail...>::type;
};
};
/// Special case - only a single variant is left.
template <class... Vars>
struct define_variant<std::variant<Vars...>> {
/// Special case - only a single variant is left.
template <class... Vars>
struct define_variant<std::variant<Vars...>> {
using type = std::variant<Vars...>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -14,11 +14,11 @@
#include "../StringLiteral.hpp"
namespace rfl {
namespace internal {
namespace enums {
namespace internal {
namespace enums {
template <class EnumType, class LiteralType, size_t N, auto... _enums>
struct Names {
template <class EnumType, class LiteralType, size_t N, auto... _enums>
struct Names {
/// Contains a collection of enums as compile-time strings.
using Literal = LiteralType;
@ -27,50 +27,69 @@ struct Names {
/// A list of all the possible enums
constexpr static std::array<EnumType, N> enums_ =
std::array<EnumType, N>{_enums...};
std::array<EnumType, N> {_enums...};
static_assert(N == 0 || LiteralType::size() == N,
"Size of literal and enum do not match.");
template <class NewLiteral, auto _new_enum>
using AddOneType = std::conditional_t<
N == 0, Names<EnumType, NewLiteral, 1, _new_enum>,
Names<EnumType, define_literal_t<LiteralType, NewLiteral>, N + 1,
_enums..., _new_enum>>;
};
using AddOneType =
std::conditional_t<N == 0,
Names<EnumType, NewLiteral, 1, _new_enum>,
Names<EnumType,
define_literal_t<LiteralType, NewLiteral>,
N + 1,
_enums...,
_new_enum>>;
};
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
auto names_to_enumerator_named_tuple(
template <class EnumType,
size_t N,
StringLiteral... _names,
auto... _enums>
auto names_to_enumerator_named_tuple(
Names<EnumType, Literal<_names...>, N, _enums...>) {
return make_named_tuple(Field<_names, EnumType>{_enums}...);
}
return make_named_tuple(Field<_names, EnumType> {_enums}...);
}
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
auto names_to_underlying_enumerator_named_tuple(
template <class EnumType,
size_t N,
StringLiteral... _names,
auto... _enums>
auto names_to_underlying_enumerator_named_tuple(
Names<EnumType, Literal<_names...>, N, _enums...>) {
return make_named_tuple(Field<_names, std::underlying_type_t<EnumType>>{
return make_named_tuple(
Field<_names, std::underlying_type_t<EnumType>> {
static_cast<std::underlying_type_t<EnumType>>(_enums)}...);
}
}
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
constexpr std::array<std::pair<std::string_view, EnumType>, N>
names_to_enumerator_array(Names<EnumType, Literal<_names...>, N, _enums...>) {
return {
std::make_pair(LiteralHelper<_names>::field_.string_view(), _enums)...};
}
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
constexpr std::array<
std::pair<std::string_view, std::underlying_type_t<EnumType>>, N>
names_to_underlying_enumerator_array(
template <class EnumType,
size_t N,
StringLiteral... _names,
auto... _enums>
constexpr std::array<std::pair<std::string_view, EnumType>, N>
names_to_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))...};
}
return {std::make_pair(LiteralHelper<_names>::field_.string_view(),
_enums)...};
}
} // namespace enums
} // namespace internal
template <class EnumType,
size_t N,
StringLiteral... _names,
auto... _enums>
constexpr std::array<
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 internal
} // namespace rfl
#endif

View file

@ -15,15 +15,16 @@
#include "is_flag_enum.hpp"
namespace rfl {
namespace internal {
namespace enums {
namespace internal {
namespace enums {
template <class EnumType>
class StringConverter {
template <class EnumType>
class StringConverter {
public:
static constexpr bool is_flag_enum_ = is_flag_enum<EnumType>;
static constexpr auto names_ = get_enum_names<EnumType, is_flag_enum_>();
static constexpr auto names_ =
get_enum_names<EnumType, is_flag_enum_>();
using NamesLiteral = typename decltype(names_)::Literal;
@ -39,7 +40,8 @@ class StringConverter {
/// Transforms a string to the matching enum.
static Result<EnumType> string_to_enum(const std::string& _str) {
static_assert(names_.size != 0,
static_assert(
names_.size != 0,
"No enum could be identified. Please choose enum values "
"between 0 to 127 or for flag enums choose 1,2,4,8,16,...");
if constexpr (is_flag_enum_) {
@ -50,7 +52,8 @@ class StringConverter {
}
private:
/// Iterates through the enum bit by bit and matches it against the flags.
/// Iterates through the enum bit by bit and matches it against the
/// flags.
static std::string flag_enum_to_string(const EnumType _e) {
using T = std::underlying_type_t<EnumType>;
auto val = static_cast<T>(_e);
@ -69,8 +72,8 @@ class StringConverter {
return strings::join("|", flags);
}
/// This assumes that _enum can be exactly matched to one of the names and
/// does not have to be combined using |.
/// This assumes that _enum can be exactly matched to one of the names
/// and does not have to be combined using |.
static std::string enum_to_single_string(const EnumType _enum) {
const auto to_str = [](const auto _l) { return _l.str(); };
@ -83,7 +86,8 @@ class StringConverter {
}
}
return std::to_string(static_cast<std::underlying_type_t<EnumType>>(_enum));
return std::to_string(
static_cast<std::underlying_type_t<EnumType>>(_enum));
}
/// Finds the enum matching the literal.
@ -91,23 +95,22 @@ class StringConverter {
return names_.enums_[_lit.value()];
}
/// This assumes that _enum can be exactly matched to one of the names and
/// does not have to be combined using |.
/// This assumes that _enum can be exactly matched to one of the names
/// and does not have to be combined using |.
static Result<EnumType> single_string_to_enum(const std::string& _str) {
const auto r = NamesLiteral::from_string(_str).transform(literal_to_enum);
const auto r =
NamesLiteral::from_string(_str).transform(literal_to_enum);
if (r) {
return r;
} else {
try {
return static_cast<EnumType>(std::stoi(_str));
} catch (std::exception& exp) {
return Error(exp.what());
}
} catch (std::exception& exp) { return Error(exp.what()); }
}
}
/// Only relevant if this is a flag enum - combines the different matches
/// using |.
/// Only relevant if this is a flag enum - combines the different
/// matches using |.
static Result<EnumType> string_to_flag_enum(
const std::string& _str) noexcept {
using T = std::underlying_type_t<EnumType>;
@ -123,10 +126,10 @@ class StringConverter {
}
return static_cast<EnumType>(res);
}
};
};
} // namespace enums
} // namespace internal
} // namespace enums
} // namespace internal
} // namespace rfl
#endif

View file

@ -36,18 +36,19 @@
// defined.
namespace rfl {
namespace internal {
namespace enums {
namespace internal {
namespace enums {
template <auto e>
consteval auto get_enum_name_str_view() {
// Unfortunately, we cannot avoid the use of a compiler-specific macro for
// Clang on Windows. For all other compilers, function_name works as intended.
template <auto e>
consteval auto get_enum_name_str_view() {
// Unfortunately, we cannot avoid the use of a compiler-specific macro
// for Clang on Windows. For all other compilers, function_name works as
// intended.
#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
const auto func_name =
std::string_view{std::source_location::current().function_name()};
std::string_view {std::source_location::current().function_name()};
#endif
#if defined(__clang__)
const auto split = func_name.substr(0, func_name.size() - 1);
@ -59,51 +60,57 @@ consteval auto get_enum_name_str_view() {
const auto split = func_name.substr(0, func_name.size() - 7);
return split.substr(split.find("get_enum_name_str_view<") + 23);
#else
static_assert(false,
static_assert(
false,
"You are using an unsupported compiler. Please use GCC, Clang "
"or MSVC or use rfl::Literal.");
#endif
}
}
template <auto e>
consteval auto get_enum_name() {
template <auto e>
consteval auto get_enum_name() {
constexpr auto name = get_enum_name_str_view<e>();
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()> {});
}
template <class T>
consteval T calc_greatest_power_of_two() {
template <class T>
consteval T calc_greatest_power_of_two() {
if constexpr (std::is_signed_v<T>) {
return static_cast<T>(1) << (sizeof(T) * 8 - 2);
} else {
return static_cast<T>(1) << (sizeof(T) * 8 - 1);
}
}
}
template <class T, bool _is_flag>
consteval T get_max() {
template <class T, bool _is_flag>
consteval T get_max() {
if constexpr (_is_flag) {
return calc_greatest_power_of_two<T>();
} else {
return std::numeric_limits<T>::max() > 127 ? static_cast<T>(127)
return std::numeric_limits<T>::max() > 127
? static_cast<T>(127)
: std::numeric_limits<T>::max();
}
}
}
template <class T, bool _is_flag, int _i>
consteval T calc_j() {
template <class T, bool _is_flag, int _i>
consteval T calc_j() {
if constexpr (_is_flag) {
return static_cast<T>(1) << _i;
} else {
return static_cast<T>(_i);
}
}
}
template <class EnumType, class NamesType, auto _max, bool _is_flag, int _i>
consteval auto get_enum_names_impl() {
template <class EnumType,
class NamesType,
auto _max,
bool _is_flag,
int _i>
consteval auto get_enum_names_impl() {
using T = std::underlying_type_t<EnumType>;
constexpr T j = calc_j<T, _is_flag, _i>();
@ -112,40 +119,44 @@ consteval auto get_enum_names_impl() {
if constexpr (std::get<0>(name.arr_) == '(') {
if constexpr (j == _max) {
return NamesType{};
return NamesType {};
} else {
return get_enum_names_impl<EnumType, NamesType, _max, _is_flag, _i + 1>();
return get_enum_names_impl<EnumType, NamesType, _max, _is_flag,
_i + 1>();
}
} else {
using NewNames = typename NamesType::template AddOneType<
Literal<remove_namespaces<name>()>, static_cast<EnumType>(j)>;
if constexpr (j == _max) {
return NewNames{};
return NewNames {};
} else {
return get_enum_names_impl<EnumType, NewNames, _max, _is_flag, _i + 1>();
return get_enum_names_impl<EnumType, NewNames, _max, _is_flag,
_i + 1>();
}
}
}
}
template <class EnumType, bool _is_flag>
consteval auto get_enum_names() {
static_assert(is_scoped_enum<EnumType>,
template <class EnumType, bool _is_flag>
consteval auto get_enum_names() {
static_assert(
is_scoped_enum<EnumType>,
"You must use scoped enums (using class or struct) for the "
"parsing to work!");
static_assert(std::is_integral_v<std::underlying_type_t<EnumType>>,
"The underlying type of any Enum must be integral!");
constexpr auto max = get_max<std::underlying_type_t<EnumType>, _is_flag>();
constexpr auto max =
get_max<std::underlying_type_t<EnumType>, _is_flag>();
using EmptyNames = Names<EnumType, rfl::Literal<"">, 0>;
return get_enum_names_impl<EnumType, EmptyNames, max, _is_flag, 0>();
}
}
} // namespace enums
} // namespace internal
} // namespace enums
} // namespace internal
} // namespace rfl
#endif

View file

@ -6,17 +6,17 @@
#include "is_scoped_enum.hpp"
namespace rfl {
namespace internal {
namespace enums {
namespace internal {
namespace enums {
template <class EnumType>
concept is_flag_enum = is_scoped_enum<EnumType> &&
requires(EnumType e1, EnumType e2) {
template <class EnumType>
concept is_flag_enum =
is_scoped_enum<EnumType> && requires(EnumType e1, EnumType e2) {
{ e1 | e2 } -> std::same_as<EnumType>;
};
};
} // namespace enums
} // namespace internal
} // namespace enums
} // namespace internal
} // namespace rfl
#endif

View file

@ -5,15 +5,16 @@
#include <type_traits>
namespace rfl {
namespace internal {
namespace enums {
namespace internal {
namespace enums {
template <class EnumType>
concept is_scoped_enum = std::is_enum_v<EnumType> &&
template <class EnumType>
concept is_scoped_enum =
std::is_enum_v<EnumType> &&
!std::is_convertible_v<EnumType, std::underlying_type_t<EnumType>>;
} // namespace enums
} // namespace internal
} // namespace enums
} // namespace internal
} // namespace rfl
#endif

View file

@ -8,18 +8,19 @@
#include "../field_type.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class TaggedUnionType>
struct extract_discriminators;
template <class TaggedUnionType>
struct extract_discriminators;
template <StringLiteral _discriminator, class... NamedTupleType>
struct extract_discriminators<TaggedUnion<_discriminator, NamedTupleType...>> {
template <StringLiteral _discriminator, class... NamedTupleType>
struct extract_discriminators<
TaggedUnion<_discriminator, NamedTupleType...>> {
using type = define_literal_t<
std::remove_cvref_t<field_type_t<_discriminator, NamedTupleType>>...>;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -8,13 +8,13 @@
#include "copy_to_field_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
using field_tuple_t =
template <class T>
using field_tuple_t =
typename std::invoke_result<decltype(copy_to_field_tuple<T>), T>::type;
}
}
} // namespace rfl
#endif

View file

@ -7,37 +7,39 @@
#include "../NamedTuple.hpp"
#include "../TaggedUnion.hpp"
#include "../named_tuple_t.hpp"
#include "StringLiteral.hpp"
#include "find_index.hpp"
#include "../named_tuple_t.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};
template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};
/// Finds the type of the field signified by _field_name
template <StringLiteral _field_name, class T>
struct FieldType;
/// Finds the type of the field signified by _field_name
template <StringLiteral _field_name, class T>
struct FieldType;
/// Default option - for named tuples.
template <StringLiteral _field_name, class T>
struct FieldType {
/// Default option - for named tuples.
template <StringLiteral _field_name, class T>
struct FieldType {
using NamedTupleType = named_tuple_t<T>;
static constexpr int field_ix_ =
internal::find_index<_field_name, typename NamedTupleType::Fields>();
using Type = typename std::tuple_element<
field_ix_, typename NamedTupleType::Fields>::type::Type;
};
using Type = typename std::
tuple_element<field_ix_, typename NamedTupleType::Fields>::type::Type;
};
/// For variants - in this case the FieldType returned by all options must be
/// the same.
template <StringLiteral _field_name, class FirstAlternativeType,
/// For variants - in this case the FieldType returned by all options must
/// be the same.
template <StringLiteral _field_name,
class FirstAlternativeType,
class... OtherAlternativeTypes>
struct FieldType<_field_name,
struct FieldType<
_field_name,
std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
constexpr static bool all_types_match = std::conjunction_v<std::is_same<
typename FieldType<_field_name, FirstAlternativeType>::Type,
@ -46,18 +48,21 @@ struct FieldType<_field_name,
static_assert(all_types_match, "All field types must be the same.");
using Type = typename FieldType<_field_name, FirstAlternativeType>::Type;
};
};
/// For tagged union - just defers to the variant.
template <StringLiteral _field_name, StringLiteral _discriminator_name,
/// For tagged union - just defers to the variant.
template <StringLiteral _field_name,
StringLiteral _discriminator_name,
class... VarTypes>
struct FieldType<_field_name, TaggedUnion<_discriminator_name, VarTypes...>> {
struct FieldType<_field_name,
TaggedUnion<_discriminator_name, VarTypes...>> {
using Type = typename FieldType<
_field_name, typename TaggedUnion<_discriminator_name,
_field_name,
typename TaggedUnion<_discriminator_name,
VarTypes...>::VariantType>::Type;
};
};
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -7,11 +7,11 @@
#include "StringLiteral.hpp"
namespace rfl {
namespace internal {
namespace internal {
/// Finds the index of the field signified by _field_name
template <StringLiteral _field_name, class Fields, int I = 0>
constexpr static int find_index() {
/// Finds the index of the field signified by _field_name
template <StringLiteral _field_name, class Fields, int I = 0>
constexpr static int find_index() {
using FieldType =
std::remove_cvref_t<typename std::tuple_element<I, Fields>::type>;
@ -31,9 +31,9 @@ constexpr static int find_index() {
return find_index<_field_name, Fields, I + 1>();
}
}
}
}
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -7,13 +7,14 @@
#include "to_flattened_ptr_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
using flattened_ptr_tuple_t =
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
template <class T>
using flattened_ptr_tuple_t =
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>),
T>::type;
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -5,18 +5,18 @@
#include <tuple>
#include <type_traits>
#include "../to_named_tuple.hpp"
#include "flattened_ptr_tuple_t.hpp"
#include "remove_ptrs_tup.hpp"
#include "../to_named_tuple.hpp"
namespace rfl {
namespace internal {
namespace internal {
template <class T>
using flattened_tuple_t =
template <class T>
using flattened_tuple_t =
typename remove_ptrs_tup<flattened_ptr_tuple_t<T>>::TupleType;
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

View file

@ -2,7 +2,7 @@
#define RFL_INTERNAL_GETFAKEOBJECT_HPP_
namespace rfl {
namespace internal {
namespace internal {
#if __GNUC__
#ifndef __clang__
@ -21,16 +21,16 @@ namespace internal {
#pragma warning(disable : 7631)
#endif
template <class T>
struct wrapper {
template <class T>
struct wrapper {
const T value;
static const wrapper<T> report_if_you_see_a_link_error_with_this_object;
};
};
template <class T>
consteval const T& get_fake_object() noexcept {
template <class T>
consteval const T& get_fake_object() noexcept {
return wrapper<T>::report_if_you_see_a_link_error_with_this_object.value;
}
}
#ifdef __clang__
#pragma clang diagnostic pop
@ -40,7 +40,7 @@ consteval const T& get_fake_object() noexcept {
#pragma warning(pop)
#endif
} // namespace internal
} // namespace internal
} // namespace rfl
#endif

Some files were not shown because too many files have changed in this diff Show more