From acc9e3e0520dec09f4fcef6a9db706cf0336f0ce Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sat, 17 Oct 2026 13:26:43 +0300 Subject: [PATCH 1/3] Inline scalar and vector element parsing helpers --- include/rfl/parsing/ParserBasicType.hpp | 4 +++- include/rfl/parsing/VectorReader.hpp | 17 ++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/rfl/parsing/ParserBasicType.hpp b/include/rfl/parsing/ParserBasicType.hpp index a1413cb83..f950ff017 100644 --- a/include/rfl/parsing/ParserBasicType.hpp +++ b/include/rfl/parsing/ParserBasicType.hpp @@ -8,6 +8,7 @@ #include "../always_false.hpp" #include "../enums.hpp" #include "../from_named_tuple.hpp" +#include "../internal/always_inline.hpp" #include "../internal/has_default_val_v.hpp" #include "../internal/has_reflection_method_v.hpp" #include "../internal/has_reflection_type_v.hpp" @@ -47,7 +48,8 @@ struct ParserBasicType { * @param _var The input variable to read from. * @return A Result containing the parsed value or an error. */ - static Result read(const R& _r, const InputVarType& _var) noexcept { + static RFL_ALWAYS_INLINE Result read(const R& _r, + const InputVarType& _var) noexcept { return _r.template to_basic_type>(_var); } diff --git a/include/rfl/parsing/VectorReader.hpp b/include/rfl/parsing/VectorReader.hpp index c5a0606ff..a192517ed 100644 --- a/include/rfl/parsing/VectorReader.hpp +++ b/include/rfl/parsing/VectorReader.hpp @@ -53,15 +53,6 @@ class VectorReader { * @return An optional error. */ RFL_ALWAYS_INLINE std::optional read(const InputVarType& _var) const { - const auto parse = [this](const InputVarType& _var) { - if constexpr (is_map_like_v) { - return get_pair(_var); - } else { - return Parser, ProcessorsType>::read(*r_, - _var); - } - }; - const auto insert = [this](auto&& _var) -> std::optional { if constexpr (is_map_like_v || is_set_like_v) { vec_->insert(std::move(_var)); @@ -85,6 +76,14 @@ class VectorReader { } private: + RFL_ALWAYS_INLINE auto parse(const InputVarType& _var) const { + if constexpr (is_map_like_v) { + return get_pair(_var); + } else { + return Parser, ProcessorsType>::read(*r_, _var); + } + } + auto get_pair(const auto& _var) const { using K = std::remove_cvref_t; using V = std::remove_cvref_t; From 18dad08ee19e73aea30759d798aee45431ad66f7 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sat, 17 Oct 2026 13:26:43 +0300 Subject: [PATCH 2/3] Mark shared parser error branches as unlikely --- include/rfl/parsing/NamedTupleParser.hpp | 12 ++++++------ include/rfl/parsing/ViewReader.hpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/rfl/parsing/NamedTupleParser.hpp b/include/rfl/parsing/NamedTupleParser.hpp index 2587c4014..84c030bee 100644 --- a/include/rfl/parsing/NamedTupleParser.hpp +++ b/include/rfl/parsing/NamedTupleParser.hpp @@ -389,12 +389,12 @@ struct NamedTupleParser { const auto reader = ViewReaderType(&_r, _view, &found, &set, &errors); if constexpr (_no_field_names) { const auto err = _r.read_array(reader, _obj_or_arr); - if (err) { + if (err) [[unlikely]] { return std::make_pair(set, err); } } else { const auto err = _r.read_object(reader, _obj_or_arr); - if (err) { + if (err) [[unlikely]] { return std::make_pair(set, err); } } @@ -405,7 +405,7 @@ struct NamedTupleParser { if constexpr (internal::fail_fast_v) { return std::make_pair(set, std::move(errors).error()); } else { - if (errors.size() != 0) { + if (errors.size() != 0) [[unlikely]] { return std::make_pair(set, to_single_error_message(errors)); } return std::make_pair(set, std::optional()); @@ -419,12 +419,12 @@ struct NamedTupleParser { const auto reader = ViewReaderWithDefaultType(&_r, _view, &errors); if constexpr (_no_field_names) { const auto err = _r.read_array(reader, _obj_or_arr); - if (err) { + if (err) [[unlikely]] { return err; } } else { const auto err = _r.read_object(reader, _obj_or_arr); - if (err) { + if (err) [[unlikely]] { return err; } } @@ -438,7 +438,7 @@ struct NamedTupleParser { if constexpr (internal::fail_fast_v) { return std::move(errors).error(); } else { - if (errors.size() != 0) { + if (errors.size() != 0) [[unlikely]] { return to_single_error_message(errors); } return std::nullopt; diff --git a/include/rfl/parsing/ViewReader.hpp b/include/rfl/parsing/ViewReader.hpp index 1ae0c02c0..0ee615e92 100644 --- a/include/rfl/parsing/ViewReader.hpp +++ b/include/rfl/parsing/ViewReader.hpp @@ -105,7 +105,7 @@ class ViewReader { std::get(*_found) = true; *_already_assigned = true; auto res = Parser::read(_r, _var); - if (!res) { + if (!res) [[unlikely]] { constexpr auto name = FieldType::name(); std::stringstream stream; stream << "Failed to parse field '" << name @@ -141,7 +141,7 @@ class ViewReader { std::get<_pos>(*_found) = true; } auto res = Parser::read(_r, _var); - if (!res) { + if (!res) [[unlikely]] { std::stringstream stream; stream << "Failed to parse field '" << _current_name << "': " << res.error().what(); From 517cf6e71d9cc4db03095435eca80056252a85ef Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sun, 18 Oct 2026 23:29:23 +0300 Subject: [PATCH 3/3] Simplify container element parsing without forcing the parse helper inline --- include/rfl/parsing/VectorReader.hpp | 57 ++++++++++++---------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/include/rfl/parsing/VectorReader.hpp b/include/rfl/parsing/VectorReader.hpp index a192517ed..903e2e4a1 100644 --- a/include/rfl/parsing/VectorReader.hpp +++ b/include/rfl/parsing/VectorReader.hpp @@ -22,6 +22,18 @@ class VectorReader { using InputVarType = typename R::InputVarType; using T = typename VecType::value_type; + static constexpr auto parsed_type() { + if constexpr (is_map_like_v) { + using K = std::remove_cvref_t; + using V = std::remove_cvref_t; + return std::type_identity>{}; + } else { + return std::type_identity>{}; + } + } + + using ParsedType = typename decltype(parsed_type())::type; + public: /** * @brief Constructor. @@ -53,42 +65,21 @@ class VectorReader { * @return An optional error. */ RFL_ALWAYS_INLINE std::optional read(const InputVarType& _var) const { - const auto insert = [this](auto&& _var) -> std::optional { - if constexpr (is_map_like_v || is_set_like_v) { - vec_->insert(std::move(_var)); - } else if constexpr (is_inplace_vector_v) { - if (!vec_->try_emplace_back(std::move(_var))) { - return Error("Too many elements, capacity is " + - std::to_string(vec_->capacity()) + "."); - } - } else { - vec_->emplace_back(std::move(_var)); - } - return std::nullopt; - }; - auto res = parse(_var).transform(insert); - if (res) { - return *res; - } else { - return res.error(); + auto res = Parser::read(*r_, _var); + if (!res) { + return std::move(res).error(); } - // return parse(_var).transform(insert).error(); - } - - private: - RFL_ALWAYS_INLINE auto parse(const InputVarType& _var) const { - if constexpr (is_map_like_v) { - return get_pair(_var); + if constexpr (is_map_like_v || is_set_like_v) { + vec_->insert(std::move(*res)); + } else if constexpr (is_inplace_vector_v) { + if (!vec_->try_emplace_back(std::move(*res))) { + return Error("Too many elements, capacity is " + + std::to_string(vec_->capacity()) + "."); + } } else { - return Parser, ProcessorsType>::read(*r_, _var); + vec_->emplace_back(std::move(*res)); } - } - - auto get_pair(const auto& _var) const { - using K = std::remove_cvref_t; - using V = std::remove_cvref_t; - return Parser>, - ProcessorsType>::read(*r_, _var); + return std::nullopt; } private: