From 27229e628c4e6488270d59ef89199330185b97e0 Mon Sep 17 00:00:00 2001 From: Georgiy Lebedev Date: Mon, 15 Jan 2024 11:41:36 +0300 Subject: [PATCH] Decoder: optimize decoding of optional and variant for scalar types Currently, we always emplace an optional or variant in order to pass the value they contain forward, as a reference. This is required for complex nested types. However, if we are dealing with a scalar type, we can read its value into the optional or variant in-place. Closes #84 --- src/mpp/Dec.hpp | 34 +++++++++++++++++++++++++++++----- src/mpp/Rules.hpp | 2 ++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/mpp/Dec.hpp b/src/mpp/Dec.hpp index 79bc00d8e..f65cfbf41 100644 --- a/src/mpp/Dec.hpp +++ b/src/mpp/Dec.hpp @@ -1172,6 +1172,20 @@ bool jump_read_key(BUF& buf, T... t) return jump_find_key(val, IS, buf, t...); } +template +struct is_object_readable_by_value : std::false_type {}; + +template +struct is_object_readable_by_value::is_readable_by_value && + std::is_assignable_v(std::declval()))>, bool>::type> : std::true_type {}; + +template +constexpr bool is_object_readable_by_value_v = is_object_readable_by_value::value; + template bool jump_read_optional(BUF& buf, T... t) @@ -1184,10 +1198,15 @@ bool jump_read_optional(BUF& buf, T... t) dst.reset(); return decode_next(buf, t...); } else { - if (!dst.has_value()) - dst.emplace(); - using NEXT_PATH = path_push_t; - return decode_impl(buf, t...); + if constexpr (is_object_readable_by_value_v) { + dst = read_value(buf); + return decode_next(buf, t...); + } else { + if (!dst.has_value()) + dst.emplace(); + using NEXT_PATH = path_push_t; + return decode_impl(buf, t...); + } } } @@ -1219,7 +1238,12 @@ bool jump_read_variant(BUF& buf, T... t) auto&& dst = unwrap(path_resolve(PATH{}, t...)); using dst_t = std::remove_reference_t; static_assert(tnt::is_variant_v); - return jump_read_variant_impl<0, FAMILY, SUBRULE, PATH>(buf, t...); + if constexpr (is_object_readable_by_value()) { + dst = read_value(buf); + return decode_next(buf, t...); + } else { + return jump_read_variant_impl<0, FAMILY, SUBRULE, PATH>(buf, t...); + } } template