Skip to content

Commit

Permalink
Decoder: optimize decoding of optional and variant for scalar types
Browse files Browse the repository at this point in the history
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
  • Loading branch information
CuriousGeorgiy committed Jan 24, 2024
1 parent 3c2e477 commit 27229e6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/mpp/Dec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,20 @@ bool jump_read_key(BUF& buf, T... t)
return jump_find_key<PAIRS, FAMILY, PATH>(val, IS, buf, t...);
}

template<compact::Family FAMILY, size_t SUBRULE,
class DST, class BUF, class = void>
struct is_object_readable_by_value : std::false_type {};

template<compact::Family FAMILY, size_t SUBRULE,
class DST, class BUF>
struct is_object_readable_by_value<FAMILY, SUBRULE, DST, BUF,
typename std::enable_if_t<rule_by_family_t<FAMILY>::is_readable_by_value &&
std::is_assignable_v<DST, decltype(read_value<FAMILY, SUBRULE>(std::declval<BUF>()))>, bool>::type> : std::true_type {};

template<compact::Family FAMILY, size_t SUBRULE,
class DST, class BUF>
constexpr bool is_object_readable_by_value_v = is_object_readable_by_value<FAMILY, SUBRULE, DST, BUF>::value;

template <compact::Family FAMILY, size_t SUBRULE,
class PATH, class BUF, class... T>
bool jump_read_optional(BUF& buf, T... t)
Expand All @@ -1184,10 +1198,15 @@ bool jump_read_optional(BUF& buf, T... t)
dst.reset();
return decode_next<PATH>(buf, t...);
} else {
if (!dst.has_value())
dst.emplace();
using NEXT_PATH = path_push_t<PATH, PIT_OPTIONAL>;
return decode_impl<NEXT_PATH>(buf, t...);
if constexpr (is_object_readable_by_value_v<FAMILY, SUBRULE, dst_t, BUF>) {
dst = read_value<FAMILY, SUBRULE>(buf);
return decode_next<PATH>(buf, t...);
} else {
if (!dst.has_value())
dst.emplace();
using NEXT_PATH = path_push_t<PATH, PIT_OPTIONAL>;
return decode_impl<NEXT_PATH>(buf, t...);
}
}
}

Expand Down Expand Up @@ -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<decltype(dst)>;
static_assert(tnt::is_variant_v<dst_t>);
return jump_read_variant_impl<0, FAMILY, SUBRULE, PATH>(buf, t...);
if constexpr (is_object_readable_by_value<FAMILY, SUBRULE, dst_t, BUF>()) {
dst = read_value<FAMILY, SUBRULE>(buf);
return decode_next<PATH>(buf, t...);
} else {
return jump_read_variant_impl<0, FAMILY, SUBRULE, PATH>(buf, t...);
}
}

template <compact::Family FAMILY, size_t SUBRULE,
Expand Down
2 changes: 2 additions & 0 deletions src/mpp/Rules.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ struct BaseRule {
static constexpr uint32_t children_multiplier =
FAMILY == compact::MP_ARR ? 1 :
FAMILY == compact::MP_MAP ? 2 : 0;
// The encoded object can be read by value.
static constexpr bool is_readable_by_value = !has_data && !has_ext && !has_children;
// The rule has simplex form.
static constexpr bool has_simplex = FAMILY == compact::MP_NIL ||
FAMILY == compact::MP_IGNR ||
Expand Down

0 comments on commit 27229e6

Please sign in to comment.