mirror of https://github.com/infosecn1nja/C3.git
Add consstexpr TupleConverter::Size() when possible
parent
40400f3a5d
commit
2e28901b32
|
@ -292,14 +292,70 @@ namespace FSecure
|
|||
template <typename T>
|
||||
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<decltype(ByteConverter<T>::TupleTransform(std::declval<T>()))>();
|
||||
template <typename ...Ts>
|
||||
static constexpr auto Apply()
|
||||
{
|
||||
return ((ConverterDeduction<Ts>::FunctionSize::value == ConverterDeduction<Ts>::FunctionSize::compileTime) && ...);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Helper class compatible with Utils::Apply. Determines size after serialization, of all tuple types.
|
||||
struct GetConstexprSize
|
||||
{
|
||||
template <typename ...Ts>
|
||||
static constexpr auto Apply()
|
||||
{
|
||||
return ((ByteConverter<Ts>::Size() + ...));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/// @brief Type of helper tuple returned by ByteConverter<C>::TupleTransform.
|
||||
/// @note This type will be deduced late in instantiation procedure.
|
||||
/// @tparam C Type To be serialized.
|
||||
template <typename C>
|
||||
using TupleTransformType = decltype(ByteConverter<C>::TupleTransform(std::declval<C>()));
|
||||
|
||||
// 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<IsSizeConstexpr, TupleTransformType<T>>::value)
|
||||
{
|
||||
return Utils::Apply<GetConstexprSize, TupleTransformType<T>>::value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ByteVector::Size(ByteConverter<T>::TupleTransform(obj));
|
||||
}
|
||||
}
|
||||
#else
|
||||
/// @brief Default implementation of Size method with compile time evaluation.
|
||||
/// @return size_t. Number of bytes used after serialization.
|
||||
template <typename C = TupleTransformType<T>, std::enable_if_t<Utils::Apply<IsSizeConstexpr, C>::value, int> = 0>
|
||||
static constexpr size_t Size()
|
||||
{
|
||||
return Utils::Apply<GetConstexprSize, C>::value;
|
||||
}
|
||||
|
||||
/// @brief Default implementation of Size method.
|
||||
/// @param obj Object for serialization.
|
||||
/// @return size_t. Number of bytes used after serialization.
|
||||
template <typename C = TupleTransformType<T>, std::enable_if_t<!Utils::Apply<IsSizeConstexpr, C>::value, int> = 0>
|
||||
static size_t Size(T const& obj)
|
||||
{
|
||||
return ByteVector::Size(ByteConverter<T>::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<T>::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<T>::TupleTransform(obj));
|
||||
return bv.Read<TupleTransformType<T>>();
|
||||
}
|
||||
|
||||
/// @brief Default implementation of From method.
|
||||
|
|
|
@ -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<typename...> constexpr auto Apply(). Tuple types will be passed by parameter pack.
|
||||
/// @tparam Tpl Tuple with types on which logic will be applied.
|
||||
template <typename T, typename Tpl>
|
||||
struct Apply
|
||||
{
|
||||
private:
|
||||
template <size_t ...Is>
|
||||
constexpr static auto ApplyImpl(std::index_sequence<Is...>)
|
||||
{
|
||||
return T::template Apply<std::tuple_element_t<Is, Tpl>...>();
|
||||
}
|
||||
public:
|
||||
constexpr static auto value = ApplyImpl(std::make_index_sequence<std::tuple_size<Tpl>::value>{});
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue