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

@ -21,7 +21,8 @@ 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()));
}

View file

@ -29,7 +29,8 @@ struct AnyOf {
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();

View file

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

View file

@ -9,9 +9,9 @@
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).
/// 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:
@ -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));
}
@ -99,7 +97,8 @@ inline auto operator<=>(const Box<T1>& _b1, const Box<T2>& _b2) {
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os, const Box<T>& _b) {
std::basic_ostream<CharT, Traits>& _os,
const Box<T>& _b) {
_os << _b.get();
return _os;
}

View file

@ -13,8 +13,8 @@
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.
/// 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.
@ -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;

View file

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

View file

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

View file

@ -28,7 +28,8 @@ class Literal {
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);
}

View file

@ -31,7 +31,8 @@ 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...>>();
@ -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...);
}
@ -626,8 +636,10 @@ class NamedTuple<> {
// ----------------------------------------------------------------------------
template <internal::StringLiteral _name1, class Type1,
internal::StringLiteral _name2, class Type2>
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);
@ -651,8 +663,10 @@ inline auto operator*(const NamedTuple<FieldTypes1...>& _tup1,
return _tup1.add(_tup2);
}
template <internal::StringLiteral _name1, class Type1,
internal::StringLiteral _name2, class Type2>
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),

View file

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

View file

@ -9,9 +9,9 @@
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).
/// 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:
@ -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);
}
@ -121,7 +117,8 @@ inline auto operator<=>(const Ref<T1>& _t1, const Ref<T2>& _t2) {
template <class CharT, class Traits, class T>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& _os, const Ref<T>& _b) {
std::basic_ostream<CharT, Traits>& _os,
const Ref<T>& _b) {
_os << _b.get();
return _os;
}
@ -145,4 +142,3 @@ inline void swap(rfl::Ref<T>& _r1, rfl::Ref<T>& _r2) {
} // namespace std
#endif // RFL_REF_HPP_

View file

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

View file

@ -40,9 +40,11 @@ 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.");
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 {

View file

@ -17,4 +17,3 @@ using SkipDeserialization = internal::Skip<T, false, true>;
} // namespace rfl
#endif

View file

@ -19,7 +19,8 @@ struct TaggedUnion {
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) {}
@ -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,8 +146,8 @@ 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_);
}
};

View file

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

View file

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

View file

@ -9,8 +9,8 @@
namespace rfl::parsing {
/// bson_oid_t needs to be treated as a special case, otherwise it will be read
/// as a struct.
/// 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> {
@ -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);
}

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>
@ -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.");
}
@ -134,7 +132,8 @@ 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 {
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;
@ -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_)); }
}
};

View file

@ -2,7 +2,6 @@
#define RFL_BSON_WRITER_HPP_
#include <bson/bson.h>
#include <exception>
#include <map>
#include <sstream>
@ -85,7 +84,8 @@ class Writer {
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);
@ -93,7 +93,8 @@ class Writer {
}
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(),
@ -102,26 +103,30 @@ class Writer {
}
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,7 +138,8 @@ 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.");
@ -142,7 +148,8 @@ class Writer {
}
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,7 +167,8 @@ 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 {
@ -174,7 +182,8 @@ class Writer {
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()));
@ -185,7 +194,8 @@ class Writer {
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>()) {

View file

@ -2,7 +2,6 @@
#define RFL_BSON_READ_HPP_
#include <bson/bson.h>
#include <istream>
#include <string>

View file

@ -2,7 +2,6 @@
#define RFL_BSON_WRITE_HPP_
#include <bson/bson.h>
#include <ostream>
#include <sstream>
#include <string>
@ -15,8 +14,8 @@
namespace rfl {
namespace bson {
/// Returns BSON bytes. Careful: It is the responsibility of the caller to call
/// bson_free on the returned pointer.
/// 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)>;

View file

@ -8,27 +8,33 @@
namespace rfl {
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.
/// 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,
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,
: public TupleParser<cbor::Reader,
cbor::Writer,
/*_ignore_empty_containers=*/false,
/*_all_required=*/true, ProcessorsType, Ts...> {
};
/*_all_required=*/true,
ProcessorsType,
Ts...> {};
} // namespace parsing
} // namespace rfl

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>
@ -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 {
@ -159,7 +137,8 @@ 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 {
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,31 +163,24 @@ 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});
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,12 +202,11 @@ 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 {

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_WRITER_HPP_
#include <cbor.h>
#include <exception>
#include <map>
#include <sstream>
@ -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());
@ -104,7 +108,8 @@ class Writer {
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_);
@ -135,7 +140,8 @@ class Writer {
}
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>()) {

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_READ_HPP_
#include <cbor.h>
#include <istream>
#include <string>
@ -30,8 +29,8 @@ 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);
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;

View file

@ -2,7 +2,6 @@
#define RFL_CBOR_WRITE_HPP_
#include <cbor.h>
#include <cstdint>
#include <ostream>
#include <sstream>
@ -16,7 +15,8 @@ namespace rfl {
namespace cbor {
template <class... Ps>
void write_into_buffer(const auto& _obj, CborEncoder* _encoder,
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>;

View file

@ -76,7 +76,8 @@ 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}};
}
};
@ -124,7 +125,8 @@ 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}};
}
};

View file

@ -14,17 +14,19 @@ 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);
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);
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.
// 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<
@ -32,8 +34,8 @@ auto get_enumerators() {
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.
// 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<

View file

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

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>
@ -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,9 +133,7 @@ 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()); }
}
};

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>
@ -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);
@ -98,7 +102,8 @@ struct Writer {
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 {};
@ -156,7 +161,8 @@ struct Writer {
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};
}

View file

@ -2,7 +2,6 @@
#define FLEXBUF_READ_HPP_
#include <flatbuffers/flexbuffers.h>
#include <istream>
#include <vector>

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>
@ -22,7 +21,8 @@ std::vector<uint8_t> to_buffer(const auto& _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();
}

View file

@ -18,7 +18,8 @@ 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> {}) {
return internal::copy_from_named_tuple<T>(_n);

View file

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

View file

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

View file

@ -36,9 +36,7 @@ struct StringLiteral {
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();
}

View file

@ -7,7 +7,8 @@ namespace internal {
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) {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -6,8 +6,8 @@
#include <type_traits>
#include "../Field.hpp"
#include "lit_name.hpp"
#include "../make_named_tuple.hpp"
#include "lit_name.hpp"
namespace rfl {
namespace internal {

View file

@ -11,8 +11,12 @@ template <class... LiteralTypes>
struct define_literal;
/// General case
template <StringLiteral... _content1, StringLiteral... _content2, class... Tail>
struct define_literal<Literal<_content1...>, Literal<_content2...>, Tail...> {
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;
};

View file

@ -25,9 +25,11 @@ 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 also NamedTuple.
/// 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...>,
struct define_named_tuple<NamedTuple<TupContent...>,
NamedTuple<TupContent2...>,
Tail...> {
using type =
typename define_named_tuple<NamedTuple<TupContent..., TupContent2...>,

View file

@ -12,11 +12,14 @@ 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...> {
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...>,
@ -24,29 +27,37 @@ struct define_tagged_union<
};
/// Recursive case - tagged union plus named tuple.
template <StringLiteral _discriminator, class... NamedTupleTypes,
class... FieldTypes, class... Tail>
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...> {
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,
struct define_tagged_union<
_discriminator,
TaggedUnion<_discriminator, NamedTupleTypes...>> {
using type = TaggedUnion<_discriminator, NamedTupleTypes...>;
};

View file

@ -12,7 +12,9 @@ struct define_variant;
/// Recursive case - both variants.
template <class... Vars1, class... Vars2, class... Tail>
struct define_variant<std::variant<Vars1...>, std::variant<Vars2...>, Tail...> {
struct define_variant<std::variant<Vars1...>,
std::variant<Vars2...>,
Tail...> {
using type = typename define_variant<std::variant<Vars1..., Vars2...>,
Tail...>::type;
};

View file

@ -33,39 +33,58 @@ struct Names {
"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>
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}...);
}
template <class EnumType, size_t N, StringLiteral... _names, auto... _enums>
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>
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)...};
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>
template <class EnumType,
size_t N,
StringLiteral... _names,
auto... _enums>
constexpr std::array<
std::pair<std::string_view, std::underlying_type_t<EnumType>>, N>
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(),
return {std::make_pair(
LiteralHelper<_names>::field_.string_view(),
static_cast<std::underlying_type_t<EnumType>>(_enums))...};
}

View file

@ -23,7 +23,8 @@ 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>;

View file

@ -41,8 +41,9 @@ 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.
// 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__};
#else
@ -59,7 +60,8 @@ 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
@ -88,7 +90,8 @@ 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();
}
}
@ -102,7 +105,11 @@ consteval T calc_j() {
}
}
template <class EnumType, class NamesType, auto _max, bool _is_flag, int _i>
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>;
@ -114,7 +121,8 @@ consteval auto get_enum_names_impl() {
if constexpr (j == _max) {
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<
@ -123,21 +131,24 @@ consteval auto get_enum_names_impl() {
if constexpr (j == _max) {
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>,
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>;

View file

@ -10,8 +10,8 @@ namespace internal {
namespace enums {
template <class EnumType>
concept is_flag_enum = is_scoped_enum<EnumType> &&
requires(EnumType e1, EnumType e2) {
concept is_flag_enum =
is_scoped_enum<EnumType> && requires(EnumType e1, EnumType e2) {
{ e1 | e2 } -> std::same_as<EnumType>;
};

View file

@ -9,7 +9,8 @@ namespace internal {
namespace enums {
template <class EnumType>
concept is_scoped_enum = std::is_enum_v<EnumType> &&
concept is_scoped_enum =
std::is_enum_v<EnumType> &&
!std::is_convertible_v<EnumType, std::underlying_type_t<EnumType>>;
} // namespace enums

View file

@ -14,7 +14,8 @@ template <class TaggedUnionType>
struct extract_discriminators;
template <StringLiteral _discriminator, class... NamedTupleType>
struct extract_discriminators<TaggedUnion<_discriminator, NamedTupleType...>> {
struct extract_discriminators<
TaggedUnion<_discriminator, NamedTupleType...>> {
using type = define_literal_t<
std::remove_cvref_t<field_type_t<_discriminator, NamedTupleType>>...>;
};

View file

@ -7,9 +7,9 @@
#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 {
@ -29,15 +29,17 @@ struct FieldType {
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,
@ -49,11 +51,14 @@ struct FieldType<_field_name,
};
/// For tagged union - just defers to the variant.
template <StringLiteral _field_name, StringLiteral _discriminator_name,
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;
};

View file

@ -11,7 +11,8 @@ namespace internal {
template <class T>
using flattened_ptr_tuple_t =
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>),
T>::type;
} // namespace internal
} // namespace rfl

View file

@ -5,9 +5,9 @@
#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 {

View file

@ -43,7 +43,8 @@ constexpr auto wrap(const T& arg) noexcept {
template <class T, auto ptr>
consteval auto get_field_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.
// 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__};
#else
@ -60,7 +61,8 @@ consteval auto get_field_name_str_view() {
const auto split = func_name.substr(0, func_name.size() - 7);
return split.substr(split.rfind("->") + 2);
#else
static_assert(false,
static_assert(
false,
"You are using an unsupported compiler. Please use GCC, Clang "
"or MSVC or switch to the rfl::Field-syntax.");
#endif

View file

@ -17,7 +17,8 @@ auto get_meta_fields(AlreadyExtracted&&... _already_extracted) {
if constexpr (NamedTupleType::size() == i) {
return std::array<MetaField, i> {std::move(_already_extracted)...};
} else {
using FieldType = std::tuple_element_t<i, typename NamedTupleType::Fields>;
using FieldType =
std::tuple_element_t<i, typename NamedTupleType::Fields>;
auto name = typename FieldType::Name().str();
auto type = type_name_t<typename FieldType::Type>().str();
return get_meta_fields<NamedTupleType>(

View file

@ -11,7 +11,8 @@ namespace internal {
template <class T>
consteval auto get_type_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.
// 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__};
#else
@ -28,9 +29,7 @@ consteval auto get_type_name_str_view() {
auto split = func_name.substr(0, func_name.size() - 7);
split = split.substr(split.find("get_type_name_str_view<") + 23);
auto pos = split.find(" ");
if (pos != std::string_view::npos) {
return split.substr(pos + 1);
}
if (pos != std::string_view::npos) { return split.substr(pos + 1); }
return split;
#else
static_assert(

View file

@ -7,7 +7,8 @@ namespace rfl {
namespace internal {
template <typename Wrapper>
using to_class_method_t = decltype(std::declval<const Wrapper>().to_class());
using to_class_method_t =
decltype(std::declval<const Wrapper>().to_class());
template <typename Wrapper, typename = std::void_t<>>
struct has_to_class_m : std::false_type {};

View file

@ -4,11 +4,11 @@
#include <functional>
#include <type_traits>
#include "../named_tuple_t.hpp"
#include "is_field.hpp"
#include "is_named_tuple.hpp"
#include "nt_to_ptr_named_tuple.hpp"
#include "ptr_field_tuple_t.hpp"
#include "../named_tuple_t.hpp"
namespace rfl {
namespace internal {
@ -25,7 +25,8 @@ auto make_ptr_fields(PtrNamedTupleType& _n, Args... _args) {
} else {
using Field =
std::remove_cvref_t<std::tuple_element_t<i, PtrFieldTupleType>>;
using T = std::remove_cvref_t<std::remove_pointer_t<typename Field::Type>>;
using T =
std::remove_cvref_t<std::remove_pointer_t<typename Field::Type>>;
if constexpr (is_named_tuple_v<T>) {
using SubPtrNamedTupleType =
@ -36,7 +37,8 @@ auto make_ptr_fields(PtrNamedTupleType& _n, Args... _args) {
_n, _args..., SubPtrNamedTupleType(_n).fields());
} else if constexpr (is_flatten_field<Field>::value) {
using SubPtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
using SubPtrFieldTupleType =
std::remove_cvref_t<ptr_field_tuple_t<T>>;
return make_ptr_fields<PtrFieldTupleType>(
_n, _args..., make_ptr_fields<SubPtrFieldTupleType>(_n));
@ -54,7 +56,8 @@ auto move_from_ptr_fields(Pointers& _ptrs, Args&&... _args) {
if constexpr (i == std::tuple_size_v<std::remove_cvref_t<Pointers>>) {
return T {std::move(_args)...};
} else {
using FieldType = std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
using FieldType =
std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
if constexpr (is_field_v<FieldType>) {
return move_from_ptr_fields<T>(
@ -95,7 +98,8 @@ T move_from_named_tuple(NamedTupleType&& _n) {
return move_from_ptr_fields<T>(pointers);
} else {
return move_from_named_tuple<T, RequiredType>(RequiredType(std::move(_n)));
return move_from_named_tuple<T, RequiredType>(
RequiredType(std::move(_n)));
}
}

View file

@ -29,11 +29,15 @@ constexpr int calc_flattened_size() {
}
}
template <class TargetTupleType, class PtrTupleType, int _j = 0, class... Args>
template <class TargetTupleType,
class PtrTupleType,
int _j = 0,
class... Args>
auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
constexpr auto i = sizeof...(Args);
constexpr auto size = std::tuple_size_v<std::remove_cvref_t<TargetTupleType>>;
constexpr auto size =
std::tuple_size_v<std::remove_cvref_t<TargetTupleType>>;
if constexpr (i == size) {
return std::make_tuple(_args...);
@ -45,7 +49,8 @@ auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
using SubTargetTupleType =
ptr_tuple_t<std::remove_pointer_t<typename T::Type>>;
constexpr int flattened_size = calc_flattened_size<SubTargetTupleType>();
constexpr int flattened_size =
calc_flattened_size<SubTargetTupleType>();
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType,
_j + flattened_size>(
@ -65,7 +70,8 @@ auto move_from_pointers(Pointers& _ptrs, Args&&... _args) {
if constexpr (i == std::tuple_size_v<std::remove_cvref_t<Pointers>>) {
return std::remove_cvref_t<T> {std::move(_args)...};
} else {
using FieldType = std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
using FieldType =
std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
if constexpr (std::is_pointer_v<FieldType>) {
return move_from_pointers<T>(_ptrs, std::move(_args)...,
@ -77,7 +83,8 @@ auto move_from_pointers(Pointers& _ptrs, Args&&... _args) {
using U = std::remove_cvref_t<typename std::remove_pointer_t<
typename std::tuple_element_t<i, PtrTupleType>>::Type>;
return move_from_pointers<T>(_ptrs, std::move(_args)...,
return move_from_pointers<T>(
_ptrs, std::move(_args)...,
move_from_pointers<U>(std::get<i>(_ptrs)));
}
}

View file

@ -18,10 +18,10 @@ constexpr inline bool no_duplicate_field_names() {
} else if constexpr (_j == -1) {
return no_duplicate_field_names<Fields, _i + 1, _i>();
} else {
using FieldType1 =
std::remove_cvref_t<typename std::tuple_element<_i, Fields>::type>;
using FieldType2 =
std::remove_cvref_t<typename std::tuple_element<_j, Fields>::type>;
using FieldType1 = std::remove_cvref_t<
typename std::tuple_element<_i, Fields>::type>;
using FieldType2 = std::remove_cvref_t<
typename std::tuple_element<_j, Fields>::type>;
constexpr auto field_name_i = FieldType1::name_;
constexpr auto field_name_j = FieldType2::name_;

View file

@ -24,14 +24,16 @@ auto nt_to_ptr_named_tuple(NamedTupleType& _nt, AlreadyExtracted... _a) {
using FieldType = typename std::tuple_element<i, Fields>::type;
using T = std::remove_cvref_t<typename FieldType::Type>;
return nt_to_ptr_named_tuple(
_nt, _a..., Field<FieldType::name_, T*>(&std::get<i>(_nt.values())));
_nt, _a...,
Field<FieldType::name_, T*>(&std::get<i>(_nt.values())));
}
}
/// Generates a named tuple that contains pointers to the original values in
/// the struct from a named tuple.
template <class NamedTupleType, class... AlreadyExtracted>
auto nt_to_ptr_named_tuple(const NamedTupleType& _nt, AlreadyExtracted... _a) {
auto nt_to_ptr_named_tuple(const NamedTupleType& _nt,
AlreadyExtracted... _a) {
using Fields = typename NamedTupleType::Fields;
constexpr auto i = sizeof...(AlreadyExtracted);

View file

@ -53,11 +53,11 @@ template <class Derived>
struct any_empty_base {
any_empty_base(std::size_t);
template <class Base>
requires(
std::is_empty_v<std::remove_cvref_t<Base>> &&
requires(std::is_empty_v<std::remove_cvref_t<Base>> &&
std::is_base_of_v<std::remove_cvref_t<Base>,
std::remove_cv_t<Derived>> &&
!std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
!std::is_same_v<std::remove_cvref_t<Base>,
std::remove_cv_t<Derived>>)
constexpr operator Base&() const noexcept;
};
@ -65,10 +65,10 @@ template <class Derived>
struct any_base {
any_base(std::size_t);
template <class Base>
requires(
std::is_base_of_v<std::remove_cvref_t<Base>,
requires(std::is_base_of_v<std::remove_cvref_t<Base>,
std::remove_cv_t<Derived>> &&
!std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
!std::is_same_v<std::remove_cvref_t<Base>,
std::remove_cv_t<Derived>>)
constexpr operator Base&() const noexcept;
};
@ -84,8 +84,7 @@ struct CountFieldsHelper {
static consteval bool constructible() {
return []<std::size_t... is>(std::index_sequence<is...>) {
return requires { T {any(is)...}; };
}
(std::make_index_sequence<n>());
}(std::make_index_sequence<n>());
}
template <std::size_t l, std::size_t nested, std::size_t r>
@ -94,8 +93,7 @@ struct CountFieldsHelper {
std::index_sequence<i...>, std::index_sequence<j...>,
std::index_sequence<k...>) {
return requires { T {any(i)..., {any(j)...}, any(k)...}; };
}
(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
}(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
std::make_index_sequence<r>());
}
@ -114,7 +112,8 @@ struct CountFieldsHelper {
if constexpr (size < 1) {
return 1;
} else if constexpr (constructible_with_nested<index, size, rest>() &&
!constructible_with_nested<index, size, rest + 1>()) {
!constructible_with_nested<index, size,
rest + 1>()) {
return size;
} else {
return get_nested_array_size<index, size - 1, rest + 1>();
@ -128,7 +127,8 @@ struct CountFieldsHelper {
std::index_sequence<l...>,
std::index_sequence<r...>) {
return requires {
T{any_empty_base<T>(l)..., any_base<T>(0), any_empty_base<T>(r)...};
T {any_empty_base<T>(l)..., any_base<T>(0),
any_empty_base<T>(r)...};
};
};
@ -154,8 +154,8 @@ struct CountFieldsHelper {
template <std::size_t n, std::size_t max_arg_num>
static consteval bool has_n_base_param() {
constexpr auto right_len = max_arg_num >= n ? max_arg_num - n : 0;
return []<std::size_t... l, std::size_t... r>(std::index_sequence<l...>,
std::index_sequence<r...>) {
return []<std::size_t... l, std::size_t... r>(
std::index_sequence<l...>, std::index_sequence<r...>) {
return requires { T {any_base<T>(l)..., any(r)...}; };
}(std::make_index_sequence<n>(), std::make_index_sequence<right_len>());
}
@ -175,9 +175,9 @@ struct CountFieldsHelper {
if constexpr (index == max) {
return 0;
} else {
return 1 +
constructible_no_brace_elision<
index + get_nested_array_size<index, max - index, 0>(), max>();
return 1 + constructible_no_brace_elision<
index + get_nested_array_size<index, max - index, 0>(),
max>();
}
}
@ -185,7 +185,8 @@ struct CountFieldsHelper {
constexpr std::size_t max_agg_args = count_max_args_in_agg_init();
constexpr std::size_t no_brace_ellison_args =
constructible_no_brace_elision<0, max_agg_args>();
constexpr std::size_t base_args = base_param_num<no_brace_ellison_args>();
constexpr std::size_t base_args =
base_param_num<no_brace_ellison_args>();
if constexpr (no_brace_ellison_args == 0 && base_args == 0) {
// Empty struct
return 0;

View file

@ -15,7 +15,8 @@ template <class StructType, class... Ps>
struct Processed<StructType, Processors<Ps...>> {
using NamedTupleType = named_tuple_t<StructType>;
using type = typename std::invoke_result<
decltype(Processors<Ps...>::template process<StructType, NamedTupleType>),
decltype(Processors<Ps...>::template process<StructType,
NamedTupleType>),
NamedTupleType>::type;
};

View file

@ -12,22 +12,30 @@
namespace rfl {
namespace internal {
/// Recursively builds a new NamedTuple type from the FieldTypes, leaving out
/// the field signified by _name.
template <class _OldNamedTupleType, StringLiteral _name,
class _NewNamedTupleType, int _i>
/// Recursively builds a new NamedTuple type from the FieldTypes, leaving
/// out the field signified by _name.
template <class _OldNamedTupleType,
StringLiteral _name,
class _NewNamedTupleType,
int _i>
struct remove_single_field;
/// Special case - _i == 0
template <class _OldNamedTupleType, StringLiteral _name,
template <class _OldNamedTupleType,
StringLiteral _name,
class _NewNamedTupleType>
struct remove_single_field<_OldNamedTupleType, _name, _NewNamedTupleType, 0> {
struct remove_single_field<_OldNamedTupleType,
_name,
_NewNamedTupleType,
0> {
using type = _NewNamedTupleType;
};
/// General case.
template <class _OldNamedTupleType, StringLiteral _name,
class _NewNamedTupleType, int _i>
template <class _OldNamedTupleType,
StringLiteral _name,
class _NewNamedTupleType,
int _i>
struct remove_single_field {
using OldNamedTupleType = std::remove_cvref_t<_OldNamedTupleType>;
@ -35,19 +43,25 @@ struct remove_single_field {
std::tuple_size_v<typename OldNamedTupleType::Fields>;
using FieldType = std::remove_cvref_t<typename std::tuple_element<
num_fields - _i, typename OldNamedTupleType::Fields>::type>;
num_fields - _i,
typename OldNamedTupleType::Fields>::type>;
using NewNamedTupleType =
std::conditional_t<_name == FieldType::name_, _NewNamedTupleType,
using NewNamedTupleType = std::conditional_t<
_name == FieldType::name_,
_NewNamedTupleType,
define_named_tuple_t<_NewNamedTupleType, FieldType>>;
using type = typename remove_single_field<OldNamedTupleType, _name,
NewNamedTupleType, _i - 1>::type;
using type = typename remove_single_field<OldNamedTupleType,
_name,
NewNamedTupleType,
_i - 1>::type;
};
/// Recursively removes all of the fields signified by _head and _tail from the
/// NamedTupleType.
template <class _NamedTupleType, StringLiteral _head, StringLiteral... _tail>
/// Recursively removes all of the fields signified by _head and _tail from
/// the NamedTupleType.
template <class _NamedTupleType,
StringLiteral _head,
StringLiteral... _tail>
struct remove_fields;
/// Special case - only head is left.
@ -58,20 +72,25 @@ struct remove_fields<_NamedTupleType, _head> {
constexpr static int num_fields =
std::tuple_size_v<typename NamedTupleType::Fields>;
using type = typename remove_single_field<NamedTupleType, _head, NamedTuple<>,
using type = typename remove_single_field<NamedTupleType,
_head,
NamedTuple<>,
num_fields>::type;
};
/// General case.
template <class _NamedTupleType, StringLiteral _head, StringLiteral... _tail>
template <class _NamedTupleType,
StringLiteral _head,
StringLiteral... _tail>
struct remove_fields {
using NamedTupleType = std::remove_cvref_t<_NamedTupleType>;
constexpr static int num_fields =
std::tuple_size_v<typename NamedTupleType::Fields>;
using NewNamedTupleType =
typename remove_single_field<NamedTupleType, _head, NamedTuple<>,
using NewNamedTupleType = typename remove_single_field<NamedTupleType,
_head,
NamedTuple<>,
num_fields>::type;
using type = typename remove_fields<NewNamedTupleType, _tail...>::type;

View file

@ -14,9 +14,7 @@ template <StringLiteral _name>
consteval auto remove_namespaces() {
constexpr auto name = _name.string_view();
constexpr size_t pos = name.find_last_of(":");
if constexpr (pos == std::string_view::npos) {
return _name;
}
if constexpr (pos == std::string_view::npos) { return _name; }
constexpr auto substr = name.substr(pos + 1);
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
return StringLiteral<sizeof...(Ns) + 1> {substr[Ns]...};

View file

@ -5,8 +5,8 @@
#include <tuple>
#include <type_traits>
#include "ptr_tuple_t.hpp"
#include "../to_named_tuple.hpp"
#include "ptr_tuple_t.hpp"
namespace rfl {
namespace internal {

View file

@ -11,9 +11,7 @@ namespace strings {
/// Joins a string using the delimiter
inline std::string join(const std::string& _delimiter,
const std::vector<std::string>& _strings) {
if (_strings.size() == 0) {
return "";
}
if (_strings.size() == 0) { return ""; }
auto res = _strings[0];
for (size_t i = 1; i < _strings.size(); ++i) {
res += _delimiter + _strings[i];

View file

@ -10,7 +10,8 @@ namespace rfl::internal {
template <internal::StringLiteral _discriminator, class T>
using tag_t =
typename std::invoke_result<decltype(make_tag<_discriminator, T>), T>::type;
typename std::invoke_result<decltype(make_tag<_discriminator, T>),
T>::type;
} // namespace rfl::internal

View file

@ -15,7 +15,8 @@ auto flatten_ptr_tuple(PtrTuple&& _t, Args... _args) {
constexpr auto i = sizeof...(Args);
if constexpr (i == 0 && !has_flatten_fields<PtrTuple>()) {
return std::forward<PtrTuple>(_t);
} else if constexpr (i == std::tuple_size_v<std::remove_cvref_t<PtrTuple>>) {
} else if constexpr (i ==
std::tuple_size_v<std::remove_cvref_t<PtrTuple>>) {
return std::tuple_cat(std::forward<Args>(_args)...);
} else {
using T = std::tuple_element_t<i, std::remove_cvref_t<PtrTuple>>;

View file

@ -22,7 +22,8 @@ namespace internal {
template <class PtrFieldTuple, class... Args>
auto flatten_ptr_field_tuple(PtrFieldTuple& _t, Args&&... _args) {
constexpr auto i = sizeof...(Args);
if constexpr (i == std::tuple_size_v<std::remove_cvref_t<PtrFieldTuple>>) {
if constexpr (i ==
std::tuple_size_v<std::remove_cvref_t<PtrFieldTuple>>) {
return std::tuple_cat(std::forward<Args>(_args)...);
} else {
using T = std::tuple_element_t<i, std::remove_cvref_t<PtrFieldTuple>>;
@ -69,7 +70,8 @@ auto to_ptr_named_tuple(T&& _t) {
} else {
using FieldNames = rfl::field_names_t<T>;
auto flattened_ptr_tuple = to_flattened_ptr_tuple(_t);
return copy_flattened_tuple_to_named_tuple<FieldNames>(flattened_ptr_tuple);
return copy_flattened_tuple_to_named_tuple<FieldNames>(
flattened_ptr_tuple);
}
}

View file

@ -16,7 +16,9 @@ consteval char to_upper() {
}
/// Transforms the field name from snake case to camel case.
template <internal::StringLiteral _name, bool _capitalize, size_t _i = 0,
template <internal::StringLiteral _name,
bool _capitalize,
size_t _i = 0,
char... chars>
consteval auto transform_snake_case() {
if constexpr (_i == _name.arr_.size()) {

View file

@ -5,9 +5,9 @@
#include <tuple>
#include <type_traits>
#include "../to_named_tuple.hpp"
#include "ptr_tuple_t.hpp"
#include "remove_ptrs_tup.hpp"
#include "../to_named_tuple.hpp"
namespace rfl {
namespace internal {

View file

@ -20,10 +20,11 @@ auto wrap_in_fields(auto&& _tuple, Fields&&... _fields) {
return std::make_tuple(std::move(_fields)...);
} else {
auto value = std::move(std::get<i>(_tuple));
using Type = std::remove_cvref_t<std::remove_pointer_t<decltype(value)>>;
using Type =
std::remove_cvref_t<std::remove_pointer_t<decltype(value)>>;
if constexpr (is_flatten_field_v<Type>) {
// The problem here is that the FieldNames are already flattened, but this
// is not, so we need to determine how many field names to skip.
// The problem here is that the FieldNames are already flattened, but
// this is not, so we need to determine how many field names to skip.
constexpr auto n_skip = std::tuple_size_v<
std::remove_cvref_t<flattened_ptr_tuple_t<typename Type::Type>>>;
return wrap_in_fields<FieldNames, j + n_skip>(

View file

@ -12,15 +12,14 @@ namespace rfl {
namespace io {
template <class T, class WriteFunction>
Result<Nothing> save_bytes(const std::string& _fname, const T& _obj,
Result<Nothing> save_bytes(const std::string& _fname,
const T& _obj,
const WriteFunction& _write) {
try {
std::ofstream output(_fname, std::ios::out | std::ios::binary);
_write(_obj, output);
output.close();
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
return Nothing {};
}

View file

@ -11,16 +11,15 @@ namespace rfl {
namespace io {
template <class T, class WriteFunction>
Result<Nothing> save_string(const std::string& _fname, const T& _obj,
Result<Nothing> save_string(const std::string& _fname,
const T& _obj,
const WriteFunction& _write) {
try {
std::ofstream outfile;
outfile.open(_fname);
_write(_obj, outfile);
outfile.close();
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
return Nothing {};
}

View file

@ -1,8 +1,6 @@
#ifndef RFL_JSON_READER_HPP_
#define RFL_JSON_READER_HPP_
#include <yyjson.h>
#include <array>
#include <concepts>
#include <exception>
@ -15,6 +13,7 @@
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <yyjson.h>
#include "../Result.hpp"
#include "../always_false.hpp"
@ -44,12 +43,12 @@ struct Reader {
using InputVarType = YYJSONInputVar;
template <class T>
static constexpr bool has_custom_constructor = (requires(InputVarType var) {
T::from_json_obj(var);
});
static constexpr bool has_custom_constructor =
(requires(InputVarType var) { T::from_json_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 {
const auto var = InputVarType(yyjson_obj_get(_obj.val_, _name.c_str()));
if (!var.val_) {
return rfl::Error("Object contains no field named '" + _name + "'.");
@ -62,22 +61,22 @@ 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 {
yyjson_val* val;
yyjson_arr_iter iter;
yyjson_arr_iter_init(_arr.val_, &iter);
while ((val = yyjson_arr_iter_next(&iter))) {
const auto err = _array_reader.read(InputVarType(val));
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 {
yyjson_obj_iter iter;
yyjson_obj_iter_init(_obj.val_, &iter);
@ -93,9 +92,7 @@ struct Reader {
rfl::Result<T> to_basic_type(const InputVarType _var) const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
const auto r = yyjson_get_str(_var.val_);
if (r == NULL) {
return rfl::Error("Could not cast to string.");
}
if (r == NULL) { return rfl::Error("Could not cast to string."); }
return std::string(r);
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
if (!yyjson_is_bool(_var.val_)) {
@ -122,7 +119,8 @@ struct Reader {
}
}
rfl::Result<InputArrayType> to_array(const InputVarType _var) const noexcept {
rfl::Result<InputArrayType> to_array(
const InputVarType _var) const noexcept {
if (!yyjson_is_arr(_var.val_)) {
return rfl::Error("Could not cast to array!");
}
@ -142,9 +140,7 @@ struct Reader {
const InputVarType _var) const noexcept {
try {
return T::from_json_obj(_var);
} catch (std::exception& e) {
return rfl::Error(e.what());
}
} catch (std::exception& e) { return rfl::Error(e.what()); }
}
};

View file

@ -1,8 +1,6 @@
#ifndef RFL_JSON_WRITER_HPP_
#define RFL_JSON_WRITER_HPP_
#include <yyjson.h>
#include <exception>
#include <map>
#include <sstream>
@ -11,6 +9,7 @@
#include <string_view>
#include <type_traits>
#include <vector>
#include <yyjson.h>
#include "../Result.hpp"
#include "../always_false.hpp"
@ -73,7 +72,8 @@ class Writer {
return OutputVarType(val);
}
OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType add_array_to_array(
const size_t _size,
OutputArrayType* _parent) const noexcept {
const auto arr = yyjson_mut_arr(doc_);
yyjson_mut_arr_add_val(_parent->val_, arr);
@ -81,7 +81,8 @@ class Writer {
}
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 {
const auto arr = yyjson_mut_arr(doc_);
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
@ -90,14 +91,16 @@ class Writer {
}
OutputObjectType add_object_to_array(
const size_t _size, OutputArrayType* _parent) const noexcept {
const size_t _size,
OutputArrayType* _parent) const noexcept {
const auto obj = yyjson_mut_obj(doc_);
yyjson_mut_arr_add_val(_parent->val_, obj);
return OutputObjectType(obj);
}
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 {
const auto obj = yyjson_mut_obj(doc_);
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
@ -106,15 +109,16 @@ class Writer {
}
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 {
const auto val = from_basic_type(_var);
yyjson_mut_arr_add_val(_parent->val_, val.val_);
return OutputVarType(val);
}
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 {
const auto val = from_basic_type(_var);
@ -129,7 +133,8 @@ class Writer {
return OutputVarType(null);
}
OutputVarType add_null_to_object(const std::string_view& _name,
OutputVarType add_null_to_object(
const std::string_view& _name,
OutputObjectType* _parent) const noexcept {
const auto null = yyjson_mut_null(doc_);
yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()),
@ -149,11 +154,14 @@ class Writer {
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
return OutputVarType(yyjson_mut_bool(doc_, _var));
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
return OutputVarType(yyjson_mut_real(doc_, static_cast<double>(_var)));
return OutputVarType(
yyjson_mut_real(doc_, static_cast<double>(_var)));
} else if constexpr (std::is_unsigned<std::remove_cvref_t<T>>()) {
return OutputVarType(yyjson_mut_uint(doc_, static_cast<uint64_t>(_var)));
return OutputVarType(
yyjson_mut_uint(doc_, static_cast<uint64_t>(_var)));
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
return OutputVarType(yyjson_mut_int(doc_, static_cast<int64_t>(_var)));
return OutputVarType(
yyjson_mut_int(doc_, static_cast<int64_t>(_var)));
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}

View file

@ -1,10 +1,9 @@
#ifndef RFL_JSON_READ_HPP_
#define RFL_JSON_READ_HPP_
#include <yyjson.h>
#include <istream>
#include <string>
#include <yyjson.h>
#include "../Processors.hpp"
#include "../internal/wrap_in_rfl_array_t.hpp"
@ -26,11 +25,10 @@ auto read(const InputVarType& _obj) {
/// Parses an object from JSON using reflection.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const std::string& _json_str) {
Result<internal::wrap_in_rfl_array_t<T>> read(
const std::string& _json_str) {
yyjson_doc* doc = yyjson_read(_json_str.c_str(), _json_str.size(), 0);
if (!doc) {
return Error("Could not parse document");
}
if (!doc) { return Error("Could not parse document"); }
yyjson_val* root = yyjson_doc_get_root(doc);
const auto r = Reader();
auto res = Parser<T, Processors<Ps...>>::read(r, InputVarType(root));

View file

@ -1,11 +1,10 @@
#ifndef RFL_JSON_SAVE_HPP_
#define RFL_JSON_SAVE_HPP_
#include <yyjson.h>
#include <fstream>
#include <iostream>
#include <string>
#include <yyjson.h>
#include "../Result.hpp"
#include "../io/save_string.hpp"
@ -15,9 +14,11 @@ namespace rfl {
namespace json {
template <class... Ps>
Result<Nothing> save(const std::string& _fname, const auto& _obj,
Result<Nothing> save(const std::string& _fname,
const auto& _obj,
const yyjson_write_flag _flag = 0) {
const auto write_func = [_flag](const auto& _obj, auto& _stream) -> auto& {
const auto write_func = [_flag](const auto& _obj,
auto& _stream) -> auto& {
return write<Ps...>(_obj, _stream, _flag);
};
return rfl::io::save_string(_fname, _obj, write_func);

View file

@ -131,11 +131,26 @@ struct Type {
rfl::Ref<Type> items;
};
using ReflectionType =
std::variant<AllOf, AnyOf, Boolean, ExclusiveMaximum, ExclusiveMinimum,
FixedSizeTypedArray, Integer, Maximum, Minimum, Number, Null,
Object, OneOf, Reference, Regex, String, StringEnum,
StringMap, Tuple, TypedArray>;
using ReflectionType = std::variant<AllOf,
AnyOf,
Boolean,
ExclusiveMaximum,
ExclusiveMinimum,
FixedSizeTypedArray,
Integer,
Maximum,
Minimum,
Number,
Null,
Object,
OneOf,
Reference,
Regex,
String,
StringEnum,
StringMap,
Tuple,
TypedArray>;
const auto& reflection() const { return value; }

View file

@ -1,12 +1,11 @@
#ifndef RFL_JSON_TOSCHEMA_HPP_
#define RFL_JSON_TOSCHEMA_HPP_
#include <yyjson.h>
#include <map>
#include <string>
#include <type_traits>
#include <variant>
#include <yyjson.h>
#include "../Literal.hpp"
#include "../Processors.hpp"
@ -32,7 +31,8 @@ inline bool is_optional(const parsing::schema::Type& _t) {
return std::visit(handle, _t.variant_);
}
inline std::string numeric_type_to_string(const parsing::schema::Type& _type) {
inline std::string numeric_type_to_string(
const parsing::schema::Type& _type) {
const auto handle_variant = [](const auto& _t) -> std::string {
using T = std::remove_cvref_t<decltype(_t)>;
using Type = parsing::schema::Type;
@ -77,17 +77,20 @@ inline schema::Type handle_validation_type(
return schema::Type {.value = schema::Type::OneOf {.oneOf = one_of}};
} else if constexpr (std::is_same<T, ValidationType::Regex>()) {
return schema::Type{.value = schema::Type::Regex{.pattern = _v.pattern_}};
return schema::Type {.value =
schema::Type::Regex {.pattern = _v.pattern_}};
} else if constexpr (std::is_same<T, ValidationType::Size>()) {
return type_to_json_schema_type(_type);
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMaximum>()) {
} else if constexpr (std::is_same<T,
ValidationType::ExclusiveMaximum>()) {
return schema::Type {.value = schema::Type::ExclusiveMaximum {
.exclusiveMaximum = _v.value_,
.type = numeric_type_to_string(_type)}};
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMinimum>()) {
} else if constexpr (std::is_same<T,
ValidationType::ExclusiveMinimum>()) {
return schema::Type {.value = schema::Type::ExclusiveMinimum {
.exclusiveMinimum = _v.value_,
.type = numeric_type_to_string(_type)}};
@ -109,8 +112,8 @@ inline schema::Type handle_validation_type(
const auto minimum = schema::Type {
.value = schema::Type::Minimum {
.minimum = _v.value_, .type = numeric_type_to_string(_type)}};
return schema::Type{.value =
schema::Type::AllOf{.allOf = {maximum, minimum}}};
return schema::Type {
.value = schema::Type::AllOf {.allOf = {maximum, minimum}}};
} else if constexpr (std::is_same<T, ValidationType::NotEqualTo>()) {
const auto excl_maximum =
@ -121,8 +124,8 @@ inline schema::Type handle_validation_type(
schema::Type {.value = schema::Type::ExclusiveMinimum {
.exclusiveMinimum = _v.value_,
.type = numeric_type_to_string(_type)}};
return schema::Type{
.value = schema::Type::AnyOf{.anyOf = {excl_maximum, excl_minimum}}};
return schema::Type {.value = schema::Type::AnyOf {
.anyOf = {excl_maximum, excl_minimum}}};
} else {
static_assert(rfl::always_false_v<T>, "Not all cases were covered.");
@ -177,32 +180,33 @@ inline schema::Type type_to_json_schema_type(
.maxContains = _t.size_}};
} else if constexpr (std::is_same<T, Type::Literal>()) {
return schema::Type{.value =
schema::Type::StringEnum{.values = _t.values_}};
return schema::Type {
.value = schema::Type::StringEnum {.values = _t.values_}};
} else if constexpr (std::is_same<T, Type::Object>()) {
auto properties = std::map<std::string, schema::Type>();
auto required = std::vector<std::string>();
for (const auto& [k, v] : _t.types_) {
properties[k] = type_to_json_schema_type(v);
if (!is_optional(v)) {
required.push_back(k);
if (!is_optional(v)) { required.push_back(k); }
}
}
return schema::Type{.value = schema::Type::Object{
.properties = properties, .required = required}};
return schema::Type {.value =
schema::Type::Object {.properties = properties,
.required = required}};
} else if constexpr (std::is_same<T, Type::Optional>()) {
return schema::Type{.value = schema::Type::AnyOf{
return schema::Type {
.value = schema::Type::AnyOf {
.anyOf = {type_to_json_schema_type(*_t.type_),
schema::Type {schema::Type::Null {}}}}};
} else if constexpr (std::is_same<T, Type::Reference>()) {
return schema::Type{
.value = schema::Type::Reference{.ref = "#/definitions/" + _t.name_}};
return schema::Type {.value = schema::Type::Reference {
.ref = "#/definitions/" + _t.name_}};
} else if constexpr (std::is_same<T, Type::StringMap>()) {
return schema::Type{.value = schema::Type::StringMap{
return schema::Type {
.value = schema::Type::StringMap {
.additionalProperties = Ref<schema::Type>::make(
type_to_json_schema_type(*_t.value_type_))}};
@ -211,7 +215,8 @@ inline schema::Type type_to_json_schema_type(
for (const auto& t : _t.types_) {
items.emplace_back(type_to_json_schema_type(t));
}
return schema::Type{.value = schema::Type::Tuple{.prefixItems = items}};
return schema::Type {.value =
schema::Type::Tuple {.prefixItems = items}};
} else if constexpr (std::is_same<T, Type::TypedArray>()) {
return schema::Type {.value = schema::Type::TypedArray {

View file

@ -1,11 +1,10 @@
#ifndef RFL_JSON_WRITE_HPP_
#define RFL_JSON_WRITE_HPP_
#include <yyjson.h>
#include <ostream>
#include <sstream>
#include <string>
#include <yyjson.h>
#include "../Processors.hpp"
#include "../parsing/Parent.hpp"
@ -23,7 +22,8 @@ std::string write(const auto& _obj, const yyjson_write_flag _flag = 0) {
using T = std::remove_cvref_t<decltype(_obj)>;
using ParentType = parsing::Parent<Writer>;
auto w = Writer(yyjson_mut_doc_new(NULL));
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
Parser<T, Processors<Ps...>>::write(w, _obj,
typename ParentType::Root {});
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
const auto json_str = std::string(json_c_str);
free((void*)json_c_str);
@ -33,12 +33,14 @@ std::string write(const auto& _obj, const yyjson_write_flag _flag = 0) {
/// Writes a JSON into an ostream.
template <class... Ps>
std::ostream& write(const auto& _obj, std::ostream& _stream,
std::ostream& write(const auto& _obj,
std::ostream& _stream,
const yyjson_write_flag _flag = 0) {
using T = std::remove_cvref_t<decltype(_obj)>;
using ParentType = parsing::Parent<Writer>;
auto w = Writer(yyjson_mut_doc_new(NULL));
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
Parser<T, Processors<Ps...>>::write(w, _obj,
typename ParentType::Root {});
const char* json_c_str = yyjson_mut_write(w.doc_, _flag, NULL);
_stream << json_c_str;
free((void*)json_c_str);

View file

@ -9,27 +9,37 @@ namespace rfl {
namespace parsing {
/// msgpack-c 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.
/// Because of that, we require all of the fields and then set them to
/// nullptr, if necessary.
template <class ProcessorsType, class... FieldTypes>
requires AreReaderAndWriter<msgpack::Reader, msgpack::Writer,
requires AreReaderAndWriter<msgpack::Reader,
msgpack::Writer,
NamedTuple<FieldTypes...>>
struct Parser<msgpack::Reader, msgpack::Writer, NamedTuple<FieldTypes...>,
struct Parser<msgpack::Reader,
msgpack::Writer,
NamedTuple<FieldTypes...>,
ProcessorsType>
: public NamedTupleParser<msgpack::Reader, msgpack::Writer,
: public NamedTupleParser<msgpack::Reader,
msgpack::Writer,
/*_ignore_empty_containers=*/false,
/*_all_required=*/true, ProcessorsType,
FieldTypes...> {
};
/*_all_required=*/true,
ProcessorsType,
FieldTypes...> {};
template <class ProcessorsType, class... Ts>
requires AreReaderAndWriter<msgpack::Reader, msgpack::Writer, std::tuple<Ts...>>
struct Parser<msgpack::Reader, msgpack::Writer, std::tuple<Ts...>,
requires AreReaderAndWriter<msgpack::Reader,
msgpack::Writer,
std::tuple<Ts...>>
struct Parser<msgpack::Reader,
msgpack::Writer,
std::tuple<Ts...>,
ProcessorsType>
: public TupleParser<msgpack::Reader, msgpack::Writer,
: public TupleParser<msgpack::Reader,
msgpack::Writer,
/*_ignore_empty_containers=*/false,
/*_all_required=*/true, ProcessorsType, Ts...> {
};
/*_all_required=*/true,
ProcessorsType,
Ts...> {};
} // namespace parsing
} // namespace rfl

View file

@ -1,13 +1,12 @@
#ifndef RFL_MSGPACK_READER_HPP_
#define RFL_MSGPACK_READER_HPP_
#include <msgpack.h>
#include <array>
#include <concepts>
#include <exception>
#include <map>
#include <memory>
#include <msgpack.h>
#include <source_location>
#include <sstream>
#include <stdexcept>
@ -30,12 +29,12 @@ struct Reader {
using InputVarType = msgpack_object;
template <class T>
static constexpr bool has_custom_constructor = (requires(InputVarType var) {
T::from_msgpack_obj(var);
});
static constexpr bool has_custom_constructor =
(requires(InputVarType var) { T::from_msgpack_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 {
for (uint32_t i = 0; i < _obj.size; ++i) {
const auto& key = _obj.ptr[i].key;
if (key.type != MSGPACK_OBJECT_STR) {
@ -44,9 +43,7 @@ struct Reader {
}
const auto current_name =
std::string_view(key.via.str.ptr, key.via.str.size);
if (_name == current_name) {
return _obj.ptr[i].val;
}
if (_name == current_name) { return _obj.ptr[i].val; }
}
return Error("No field named '" + _name + "' was found.");
}
@ -71,8 +68,8 @@ struct Reader {
return _var.via.boolean;
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>() ||
std::is_integral<std::remove_cvref_t<T>>()) {
if (type == MSGPACK_OBJECT_FLOAT32 || type == MSGPACK_OBJECT_FLOAT64 ||
type == MSGPACK_OBJECT_FLOAT) {
if (type == MSGPACK_OBJECT_FLOAT32 ||
type == MSGPACK_OBJECT_FLOAT64 || type == MSGPACK_OBJECT_FLOAT) {
return static_cast<T>(_var.via.f64);
} else if (type == MSGPACK_OBJECT_POSITIVE_INTEGER) {
return static_cast<T>(_var.via.u64);
@ -80,7 +77,8 @@ struct Reader {
return static_cast<T>(_var.via.i64);
}
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 {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
@ -104,19 +102,19 @@ 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 {
for (uint32_t i = 0; i < _arr.size; ++i) {
const auto err = _array_reader.read(_arr.ptr[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 {
for (uint32_t i = 0; i < _obj.size; ++i) {
const auto& key = _obj.ptr[i].key;
@ -136,9 +134,7 @@ struct Reader {
const InputVarType& _var) const noexcept {
try {
return T::from_msgpack_obj(_var);
} catch (std::exception& e) {
return rfl::Error(e.what());
}
} catch (std::exception& e) { return rfl::Error(e.what()); }
}
};

View file

@ -1,10 +1,9 @@
#ifndef RFL_MSGPACK_WRITER_HPP_
#define RFL_MSGPACK_WRITER_HPP_
#include <msgpack.h>
#include <exception>
#include <map>
#include <msgpack.h>
#include <sstream>
#include <stdexcept>
#include <string>
@ -54,13 +53,15 @@ class Writer {
return new_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(_size);
}
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 {
msgpack_pack_str(pk_, _name.size());
msgpack_pack_str_body(pk_, _name.data(), _name.size());
@ -68,12 +69,14 @@ class Writer {
}
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);
}
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 {
msgpack_pack_str(pk_, _name.size());
msgpack_pack_str_body(pk_, _name.data(), _name.size());
@ -87,7 +90,8 @@ class Writer {
}
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 {
msgpack_pack_str(pk_, _name.size());

View file

@ -1,9 +1,8 @@
#ifndef RFL_MSGPACK_READ_HPP_
#define RFL_MSGPACK_READ_HPP_
#include <msgpack.h>
#include <istream>
#include <msgpack.h>
#include <string>
#include "../Processors.hpp"

View file

@ -1,9 +1,8 @@
#ifndef RFL_MSGPACK_WRITE_HPP_
#define RFL_MSGPACK_WRITE_HPP_
#include <msgpack.h>
#include <cstdint>
#include <msgpack.h>
#include <ostream>
#include <sstream>
#include <string>

View file

@ -18,8 +18,8 @@ struct remove_ptr;
template <internal::StringLiteral _name, class T>
struct remove_ptr<Field<_name, T>> {
using FieldType =
Field<_name, internal::wrap_in_rfl_array_t<
using FieldType = Field<_name,
internal::wrap_in_rfl_array_t<
std::remove_cvref_t<std::remove_pointer_t<T>>>>;
};
@ -33,8 +33,8 @@ struct remove_ptrs_nt<NamedTuple<FieldTypes...>> {
};
/// Generates the named tuple that is equivalent to the struct T.
/// This is the result you would expect from calling to_named_tuple(my_struct).
/// All fields of the struct must be an rfl::Field.
/// This is the result you would expect from calling
/// to_named_tuple(my_struct). All fields of the struct must be an rfl::Field.
template <class T>
using named_tuple_t =
typename remove_ptrs_nt<internal::ptr_named_tuple_t<T>>::NamedTupleType;

View file

@ -12,10 +12,14 @@
namespace rfl {
namespace parsing {
template <class R, class W, class ProcessorsType, class OriginalClass,
template <class R,
class W,
class ProcessorsType,
class OriginalClass,
class HelperStruct>
struct CustomParser {
static Result<OriginalClass> read(const R& _r, const auto& _var) noexcept {
static Result<OriginalClass> read(const R& _r,
const auto& _var) noexcept {
const auto to_class = [](auto&& _h) -> Result<OriginalClass> {
try {
if constexpr (internal::has_to_class_method_v<HelperStruct>) {
@ -27,16 +31,15 @@ struct CustomParser {
};
return std::apply(class_from_ptrs, ptr_field_tuple);
}
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
};
return Parser<R, W, HelperStruct, ProcessorsType>::read(_r, _var).and_then(
to_class);
return Parser<R, W, HelperStruct, ProcessorsType>::read(_r, _var)
.and_then(to_class);
}
template <class P>
static auto write(const W& _w, const OriginalClass& _p,
static auto write(const W& _w,
const OriginalClass& _p,
const P& _parent) noexcept {
Parser<R, W, HelperStruct, ProcessorsType>::write(
_w, HelperStruct::from_class(_p), _parent);

View file

@ -43,9 +43,7 @@ struct FieldVariantParser {
FieldVariantReader<R, W, ProcessorsType, FieldTypes...>(
&_r, &field_variant);
auto err = _r.read_object(reader, _obj);
if (err) {
return *err;
}
if (err) { return *err; }
if (!field_variant) {
return Error(
"Could not parse: Expected the object to have "
@ -58,7 +56,8 @@ struct FieldVariantParser {
}
template <class P>
static void write(const W& _w, const std::variant<FieldTypes...>& _v,
static void write(const W& _w,
const std::variant<FieldTypes...>& _v,
const P& _parent) noexcept {
static_assert(
internal::no_duplicate_field_names<std::tuple<FieldTypes...>>(),
@ -66,7 +65,8 @@ struct FieldVariantParser {
"names.");
const auto handle = [&](const auto& _field) {
const auto named_tuple = make_named_tuple(internal::to_ptr_field(_field));
const auto named_tuple =
make_named_tuple(internal::to_ptr_field(_field));
using NamedTupleType = std::remove_cvref_t<decltype(named_tuple)>;
Parser<R, W, NamedTupleType, ProcessorsType>::write(_w, named_tuple,
_parent);
@ -79,7 +79,8 @@ struct FieldVariantParser {
std::map<std::string, schema::Type>* _definitions,
std::vector<schema::Type> _types = {}) {
using VariantType = std::variant<NamedTuple<FieldTypes>...>;
return Parser<R, W, VariantType, ProcessorsType>::to_schema(_definitions);
return Parser<R, W, VariantType, ProcessorsType>::to_schema(
_definitions);
}
};
} // namespace parsing

View file

@ -30,7 +30,9 @@ struct MockObjectReader {
};
template <class R, class T>
concept IsReader = requires(R r, std::string name,
concept IsReader = requires(
R r,
std::string name,
std::function<std::int16_t(std::string_view)> fct,
MockArrayReader<R> array_reader,
MockObjectReader<R> object_reader,
@ -60,10 +62,12 @@ concept IsReader = requires(R r, std::string name,
/// an array reader.
{ r.read_array(array_reader, arr) } -> std::same_as<std::optional<Error>>;
/// Iterates through an object and writes the key-value pairs into an object
/// reader. This is what we use to handle structs and named tuples, making it
/// a very important function.
{ r.read_object(object_reader, obj) } -> std::same_as<std::optional<Error>>;
/// Iterates through an object and writes the key-value pairs into an
/// object reader. This is what we use to handle structs and named tuples,
/// making it a very important function.
{
r.read_object(object_reader, obj)
} -> std::same_as<std::optional<Error>>;
/// Transforms var to a basic type (bool, integral,
/// floating point, std::string)
@ -72,7 +76,9 @@ concept IsReader = requires(R r, std::string name,
} -> std::same_as<rfl::Result<internal::wrap_in_rfl_array_t<T>>>;
/// Casts var as an InputArrayType.
{ r.to_array(var) } -> std::same_as<rfl::Result<typename R::InputArrayType>>;
{
r.to_array(var)
} -> std::same_as<rfl::Result<typename R::InputArrayType>>;
/// Casts var as an InputObjectType.
{

View file

@ -11,11 +11,14 @@ namespace rfl {
namespace parsing {
template <class W, class T>
concept IsWriter = requires(W w, T t, std::string_view name,
concept IsWriter = requires(W w,
T t,
std::string_view name,
std::string basic_value,
typename W::OutputArrayType arr,
typename W::OutputObjectType obj,
typename W::OutputVarType var, size_t size) {
typename W::OutputVarType var,
size_t size) {
/// Sets an empty array as the root element of the document.
/// Some serialization formats require you to pass the expected size in
/// advance. If you are not working with such a format, you can ignore the
@ -35,7 +38,9 @@ concept IsWriter = requires(W w, T t, std::string_view name,
/// Sets a basic value (bool, numeric, string) as the root element of the
/// document. Returns an OutputVarType containing the new value.
{ w.value_as_root(basic_value) } -> std::same_as<typename W::OutputVarType>;
{
w.value_as_root(basic_value)
} -> std::same_as<typename W::OutputVarType>;
/// Adds an empty array to an existing array. Returns the new
/// array for further modification.
@ -49,14 +54,16 @@ concept IsWriter = requires(W w, T t, std::string_view name,
w.add_object_to_array(size, &arr)
} -> std::same_as<typename W::OutputObjectType>;
/// Adds an empty array to an existing object. The key or name of the field is
/// signified by `name`. Returns the new array for further modification.
/// Adds an empty array to an existing object. The key or name of the
/// field is signified by `name`. Returns the new array for further
/// modification.
{
w.add_array_to_object(name, size, &obj)
} -> std::same_as<typename W::OutputArrayType>;
/// Adds an empty object to an existing object. The key or name of the field
/// is signified by `name`. Returns the new object for further modification.
/// Adds an empty object to an existing object. The key or name of the
/// field is signified by `name`. Returns the new object for further
/// modification.
{
w.add_object_to_object(name, size, &obj)
} -> std::same_as<typename W::OutputObjectType>;
@ -67,8 +74,8 @@ concept IsWriter = requires(W w, T t, std::string_view name,
w.add_value_to_array(basic_value, &arr)
} -> std::same_as<typename W::OutputVarType>;
/// Adds a basic value (bool, numeric, string) to an existing object. The key
/// or name of the field is signified by `name`. Returns an
/// Adds a basic value (bool, numeric, string) to an existing object. The
/// key or name of the field is signified by `name`. Returns an
/// OutputVarType containing the new value.
{
w.add_value_to_object(name, basic_value, &obj)
@ -85,14 +92,16 @@ concept IsWriter = requires(W w, T t, std::string_view name,
w.add_null_to_object(name, &obj)
} -> std::same_as<typename W::OutputVarType>;
/// Signifies to the writer that we do not want to add any further elements to
/// this array. Some serialization formats require this. If you are working
/// with a serialization format that doesn't, just leave the function empty.
/// Signifies to the writer that we do not want to add any further
/// elements to this array. Some serialization formats require this. If
/// you are working with a serialization format that doesn't, just leave
/// the function empty.
{ w.end_array(&arr) } -> std::same_as<void>;
/// Signifies to the writer that we do not want to add any further elements to
/// this object. Some serialization formats require this. If you are working
/// with a serialization format that doesn't, just leave the function empty.
/// Signifies to the writer that we do not want to add any further
/// elements to this object. Some serialization formats require this. If
/// you are working with a serialization format that doesn't, just leave
/// the function empty.
{ w.end_object(&obj) } -> std::same_as<void>;
};

View file

@ -28,13 +28,15 @@ struct MapParser {
using OutputObjectType = typename W::OutputObjectType;
using OutputVarType = typename W::OutputVarType;
using KeyType = std::remove_cvref_t<typename MapType::value_type::first_type>;
using KeyType =
std::remove_cvref_t<typename MapType::value_type::first_type>;
using ValueType =
std::remove_cvref_t<typename MapType::value_type::second_type>;
using ParentType = Parent<W>;
static Result<MapType> read(const R& _r, const InputVarType& _var) noexcept {
static Result<MapType> read(const R& _r,
const InputVarType& _var) noexcept {
const auto to_map = [&](auto obj) -> Result<MapType> {
return make_map(_r, obj);
};
@ -42,7 +44,9 @@ struct MapParser {
}
template <class P>
static void write(const W& _w, const MapType& _m, const P& _parent) noexcept {
static void write(const W& _w,
const MapType& _m,
const P& _parent) noexcept {
auto obj = ParentType::add_object(_w, _m.size(), _parent);
for (const auto& [k, v] : _m) {
if constexpr (internal::has_reflection_type_v<KeyType>) {
@ -52,13 +56,13 @@ struct MapParser {
std::is_floating_point_v<ReflT>) {
const auto name = std::to_string(k.reflection());
const auto new_parent = typename ParentType::Object {name, &obj};
Parser<R, W, std::remove_cvref_t<ValueType>, ProcessorsType>::write(
_w, v, new_parent);
Parser<R, W, std::remove_cvref_t<ValueType>,
ProcessorsType>::write(_w, v, new_parent);
} else {
const auto name = k.reflection();
const auto new_parent = typename ParentType::Object {name, &obj};
Parser<R, W, std::remove_cvref_t<ValueType>, ProcessorsType>::write(
_w, v, new_parent);
Parser<R, W, std::remove_cvref_t<ValueType>,
ProcessorsType>::write(_w, v, new_parent);
}
} else if constexpr (std::is_integral_v<KeyType> ||
@ -83,18 +87,15 @@ struct MapParser {
}
private:
static Result<MapType> make_map(const R& _r, const InputObjectType& _obj) {
static Result<MapType> make_map(const R& _r,
const InputObjectType& _obj) {
MapType map;
std::vector<Error> errors;
const auto map_reader =
MapReader<R, W, MapType, ProcessorsType>(&_r, &map, &errors);
const auto err = _r.read_object(map_reader, _obj);
if (err) {
return *err;
}
if (errors.size() != 0) {
return to_single_error_message(errors);
}
if (err) { return *err; }
if (errors.size() != 0) { return to_single_error_message(errors); }
return map;
}
};

View file

@ -16,7 +16,8 @@ template <class R, class W, class MapType, class ProcessorsType>
class MapReader {
private:
using InputVarType = typename R::InputVarType;
using KeyType = std::remove_cvref_t<typename MapType::value_type::first_type>;
using KeyType =
std::remove_cvref_t<typename MapType::value_type::first_type>;
using ValueType =
std::remove_cvref_t<typename MapType::value_type::second_type>;
@ -32,7 +33,8 @@ class MapReader {
if (res) {
map_->emplace(std::move(*res));
} else {
errors_->push_back(Error("Failed to parse field '" + std::string(_name) +
errors_->push_back(Error("Failed to parse field '" +
std::string(_name) +
"': " + res.error()->what()));
}
}
@ -50,9 +52,7 @@ class MapReader {
} else {
static_assert(always_false_v<T>, "Unsupported type");
}
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
}
Result<std::pair<KeyType, ValueType>> make_key(auto& _pair) const noexcept {
@ -61,9 +61,7 @@ class MapReader {
try {
return std::make_pair(KeyType(std::move(_key)),
std::move(_pair.second));
} catch (std::exception& e) {
return Error(e.what());
}
} catch (std::exception& e) { return Error(e.what()); }
};
if constexpr (std::is_integral_v<KeyType> ||
@ -86,7 +84,8 @@ class MapReader {
}
Result<std::pair<KeyType, ValueType>> get_pair(
const std::string_view& _name, const InputVarType& _var) const noexcept {
const std::string_view& _name,
const InputVarType& _var) const noexcept {
const auto to_pair = [&](ValueType&& _val) {
auto pair = std::make_pair(std::string(_name), std::move(_val));
return make_key(pair);

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