From 2e28901b3232460a5fc01275cbe785e0a261305d Mon Sep 17 00:00:00 2001 From: Pawel Kurowski Date: Sat, 18 Jul 2020 22:26:36 +0200 Subject: [PATCH] Add consstexpr TupleConverter::Size() when possible --- .../CppTools/ByteConverter/ByteConverter.h | 79 ++++++++++++++++--- .../FSecure/CppTools/ByteConverter/Utils.h | 16 ++++ 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/Src/Common/FSecure/CppTools/ByteConverter/ByteConverter.h b/Src/Common/FSecure/CppTools/ByteConverter/ByteConverter.h index 9039f96..134cfc6 100644 --- a/Src/Common/FSecure/CppTools/ByteConverter/ByteConverter.h +++ b/Src/Common/FSecure/CppTools/ByteConverter/ByteConverter.h @@ -292,14 +292,70 @@ namespace FSecure template struct TupleConverter { - /// @brief Use it to read from ByteView to tuple of types deduced from TupleTransform. - /// This is a helper method used to create dedicated logic of type reading after all data was retrieved form view as tuple. - /// @param bv. Buffer with serialized data. - /// @return tuple of retrieved data for type construction. - static auto ReadTuple(ByteView& bv) + private: + /// @brief Helper class compatible with Utils::Apply. Checks if size after serialization, of all tuple types, can be determined at compile time. + struct IsSizeConstexpr { - return bv.Read::TupleTransform(std::declval()))>(); + template + static constexpr auto Apply() + { + return ((ConverterDeduction::FunctionSize::value == ConverterDeduction::FunctionSize::compileTime) && ...); + } + }; + + /// @brief Helper class compatible with Utils::Apply. Determines size after serialization, of all tuple types. + struct GetConstexprSize + { + template + static constexpr auto Apply() + { + return ((ByteConverter::Size() + ...)); + } + }; + + public: + /// @brief Type of helper tuple returned by ByteConverter::TupleTransform. + /// @note This type will be deduced late in instantiation procedure. + /// @tparam C Type To be serialized. + template + using TupleTransformType = decltype(ByteConverter::TupleTransform(std::declval())); + + // MSVC is using late deduction of default template parameter type, and only if they are used. + // This allows definition of constexpr version of Size function using SFINAE. + // There are proposals implement same delay in clang, but it is not available yet, or possibly will never be. +#if defined (__clang__) + /// @brief Default implementation of Size method. + /// @param obj Object for serialization. + /// @return size_t. Number of bytes used after serialization. + static size_t Size([[maybe_unused]] T const& obj) + { + if constexpr (Utils::Apply>::value) + { + return Utils::Apply>::value; + } + else + { + return ByteVector::Size(ByteConverter::TupleTransform(obj)); + } } +#else + /// @brief Default implementation of Size method with compile time evaluation. + /// @return size_t. Number of bytes used after serialization. + template , std::enable_if_t::value, int> = 0> + static constexpr size_t Size() + { + return Utils::Apply::value; + } + + /// @brief Default implementation of Size method. + /// @param obj Object for serialization. + /// @return size_t. Number of bytes used after serialization. + template , std::enable_if_t::value, int> = 0> + static size_t Size(T const& obj) + { + return ByteVector::Size(ByteConverter::TupleTransform(obj)); + } +#endif /// @brief Default implementation of To method. /// Serializes data treating it as tuple generated by TupleTransform. @@ -310,12 +366,13 @@ namespace FSecure bv.Store(ByteConverter::TupleTransform(obj)); } - /// @brief Default implementation of Size method. - /// @param obj Object for serialization. - /// @return size_t. Number of bytes used after serialization. - static size_t Size(T const& obj) + /// @brief Use it to read from ByteView to tuple of types deduced from TupleTransform. + /// This is a helper method used to create dedicated logic of type reading after all data was retrieved form view as tuple. + /// @param bv. Buffer with serialized data. + /// @return tuple of retrieved data for type construction. + static auto ReadTuple(ByteView& bv) { - return ByteVector::Size(ByteConverter::TupleTransform(obj)); + return bv.Read>(); } /// @brief Default implementation of From method. diff --git a/Src/Common/FSecure/CppTools/ByteConverter/Utils.h b/Src/Common/FSecure/CppTools/ByteConverter/Utils.h index 4a7308e..baa003a 100644 --- a/Src/Common/FSecure/CppTools/ByteConverter/Utils.h +++ b/Src/Common/FSecure/CppTools/ByteConverter/Utils.h @@ -320,4 +320,20 @@ namespace FSecure::Utils } }; } + + /// @brief Constexpr helper to perform logic on tuple types. Evaluation result is assigned to value member. + /// @tparam T Class with function to be applied. Must define template constexpr auto Apply(). Tuple types will be passed by parameter pack. + /// @tparam Tpl Tuple with types on which logic will be applied. + template + struct Apply + { + private: + template + constexpr static auto ApplyImpl(std::index_sequence) + { + return T::template Apply...>(); + } + public: + constexpr static auto value = ApplyImpl(std::make_index_sequence::value>{}); + }; }