mirror of https://github.com/infosecn1nja/C3.git
commit
1a69856b89
|
@ -233,7 +233,7 @@ namespace FSecure
|
||||||
/// Function responsible for recursively packing data to ByteVector.
|
/// Function responsible for recursively packing data to ByteVector.
|
||||||
/// @param self. Reference to ByteVector object using TupleHandler.
|
/// @param self. Reference to ByteVector object using TupleHandler.
|
||||||
/// @param t. reference to tuple.
|
/// @param t. reference to tuple.
|
||||||
static void Write(ByteVector& self, T const& t)
|
static void Write([[maybe_unused]] ByteVector& self, [[maybe_unused]] T const& t)
|
||||||
{
|
{
|
||||||
if constexpr (N != 0)
|
if constexpr (N != 0)
|
||||||
{
|
{
|
||||||
|
@ -245,7 +245,7 @@ namespace FSecure
|
||||||
/// Function responsible for recursively calculating buffer size needed for call with tuple argument.
|
/// Function responsible for recursively calculating buffer size needed for call with tuple argument.
|
||||||
/// @param t. reference to tuple.
|
/// @param t. reference to tuple.
|
||||||
/// @return size_t number of bytes needed.
|
/// @return size_t number of bytes needed.
|
||||||
static size_t Size(T const& t)
|
static size_t Size([[maybe_unused]] T const& t)
|
||||||
{
|
{
|
||||||
if constexpr (N != 0)
|
if constexpr (N != 0)
|
||||||
return ByteVector::Size(std::get<std::tuple_size_v<T> - N>(t)) + TupleHandler<T, N - 1>::Size(t);
|
return ByteVector::Size(std::get<std::tuple_size_v<T> - N>(t)) + TupleHandler<T, N - 1>::Size(t);
|
||||||
|
@ -256,11 +256,11 @@ namespace FSecure
|
||||||
/// C++ allows cast from pair to tuple of two, but not other way around.
|
/// C++ allows cast from pair to tuple of two, but not other way around.
|
||||||
/// This is oversight, because pair is much older concept than tuple, and no proposition was made to expand old type.
|
/// This is oversight, because pair is much older concept than tuple, and no proposition was made to expand old type.
|
||||||
/// This function ensures, that TupleHandler always returns requested type, so no cast is necessary.
|
/// This function ensures, that TupleHandler always returns requested type, so no cast is necessary.
|
||||||
static T ReadExplicit(ByteView& self)
|
static auto ReadExplicit(ByteView& self)
|
||||||
{
|
{
|
||||||
auto tmp = Read(self);
|
auto tmp = Read(self);
|
||||||
if constexpr (Utils::IsPair<T>)
|
if constexpr (Utils::IsPair<T>)
|
||||||
return { std::get<0>(tmp), std::get<1>(tmp) };
|
return std::pair{ std::get<0>(tmp), std::get<1>(tmp) };
|
||||||
else
|
else
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ namespace FSecure
|
||||||
{
|
{
|
||||||
if constexpr (N != 0)
|
if constexpr (N != 0)
|
||||||
{
|
{
|
||||||
auto current = std::make_tuple(self.Read<std::tuple_element_t<std::tuple_size_v<T> - N, T>>());
|
auto current = std::make_tuple(self.Read<Utils::RemoveCVR<std::tuple_element_t<std::tuple_size_v<T> - N, T>>>());
|
||||||
auto rest = TupleHandler<T, N - 1>::Read(self);
|
auto rest = TupleHandler<T, N - 1>::Read(self);
|
||||||
return std::tuple_cat(current, rest);
|
return std::tuple_cat(current, rest);
|
||||||
}
|
}
|
||||||
|
@ -282,4 +282,175 @@ namespace FSecure
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Class providing simple way of generating ByteConverter of custom types by treating them as tuple.
|
||||||
|
/// ByteConverter can use this functionality by inheriting from TupleConverter and providing
|
||||||
|
/// public static std::tuple<...> Convert(T const&) method.
|
||||||
|
/// Use Utils::MakeConversionTuple to create efficient tuple of value or references to members.
|
||||||
|
/// ByteVector can declare its own versions of To/From/Size methods if it needs dedicated logic to serialize type.
|
||||||
|
/// @tparam T Type for serialization.
|
||||||
|
template <typename T>
|
||||||
|
struct TupleConverter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// @brief Type returned by ByteConverter<C>::Convert.
|
||||||
|
/// ByteConverter<C> specialization may not yet be defined.
|
||||||
|
/// This type must be deduced late in instantiation procedure.
|
||||||
|
/// @tparam C Type for serialization.
|
||||||
|
template <typename C>
|
||||||
|
using ConvertType = decltype(ByteConverter<C>::Convert(std::declval<C>()));
|
||||||
|
|
||||||
|
/// @brief Helper class compatible with Utils::Apply. Checks if size after serialization, of all tuple types, can be determined at compile time.
|
||||||
|
struct IsSizeConstexpr
|
||||||
|
{
|
||||||
|
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() + ...));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief This class is designed for lazy evaluation of ConvertType<T> for IsSizeConstexpr template.
|
||||||
|
/// If used for SFINAE, ConvertType will break compilation, at not defined Convert function.
|
||||||
|
/// MSVC is evaluating default template parameter when, and only if, it is used. This behavior results in successful compilation
|
||||||
|
/// Strict compilers like clang or gcc would evaluate ConvertType before correct ByteConverter specialization is provided.
|
||||||
|
/// With this template, instantiation point is delayed, until Convert method is reachable in function lookup.
|
||||||
|
/// @tparam C Type for serialization.
|
||||||
|
template <typename C>
|
||||||
|
class IsSizeConstexprLazy
|
||||||
|
{
|
||||||
|
template <typename S> static uint16_t test(std::enable_if_t<Utils::Apply<IsSizeConstexpr, ConvertType<S>>::value, int>);
|
||||||
|
template <typename S> static uint8_t test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr bool value = sizeof(test<C>(0)) == sizeof(uint16_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief Use it to convert raw data into tuple.
|
||||||
|
/// Allows splitting deserialization into two phases.
|
||||||
|
/// 1. Retrieve data as tuple. ByteView internal pointer will be correctly moved in the process.
|
||||||
|
/// 2. Create dedicated logic of transforming tuple into desired type.
|
||||||
|
/// @param bv. Buffer with serialized data.
|
||||||
|
/// @return tuple of retrieved data for type construction.
|
||||||
|
static auto Convert(ByteView& bv)
|
||||||
|
{
|
||||||
|
return bv.Read<ConvertType<T>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// From this point forward will be implemented ByteConverter standard interface methods.
|
||||||
|
|
||||||
|
/// @brief Default implementation of To method.
|
||||||
|
/// Serializes data treating it as tuple generated by Convert.
|
||||||
|
/// @param obj Object for serialization.
|
||||||
|
/// @param bv output ByteVector with already allocated memory for data.
|
||||||
|
static void To(T const& obj, ByteVector& bv)
|
||||||
|
{
|
||||||
|
bv.Store(ByteConverter<T>::Convert(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Default implementation of From method.
|
||||||
|
/// Retrieves data from view and creates new object by passing tuple as arguments for T{...} construction.
|
||||||
|
/// This implementation uses brace enclosed construction, becouse std::make_from_tuple does not support trivial types.
|
||||||
|
/// Bear in mind that construction with parentheses, and with braces, is not interchangeable.
|
||||||
|
/// @param bv. Buffer with serialized data.
|
||||||
|
/// @return constructed type.
|
||||||
|
static T From(ByteView& bv)
|
||||||
|
{
|
||||||
|
return std::apply(Utils::Construction::Braces<T>{}, Convert(bv));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Default implementation of Size method with compile time evaluation.
|
||||||
|
/// @note All template parameters are used only to determine if function should be defined.
|
||||||
|
/// @return size_t. Number of bytes used after serialization.
|
||||||
|
template <typename C = T, std::enable_if_t<IsSizeConstexprLazy<C>::value, int> = 0>
|
||||||
|
static constexpr size_t Size()
|
||||||
|
{
|
||||||
|
return Utils::Apply<GetConstexprSize, ConvertType<T>>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Default implementation of Size method.
|
||||||
|
/// @param obj Object for serialization.
|
||||||
|
/// @note All template parameters are used only to determine if function should be defined.
|
||||||
|
/// @return size_t. Number of bytes used after serialization.
|
||||||
|
template <typename C = T, std::enable_if_t<!IsSizeConstexprLazy<C>::value, int> = 0>
|
||||||
|
static size_t Size(T const& obj)
|
||||||
|
{
|
||||||
|
return ByteVector::Size(ByteConverter<T>::Convert(obj));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Class providing simple way of generating ByteConverter listing only necessary members once.
|
||||||
|
/// ByteConverter can use this functionality by inheriting from PointerTupleConverter and providing
|
||||||
|
/// public static std::tuple<T::*...> MemberPointers() method.
|
||||||
|
/// Use std::make_tuple to create return value out of member list.
|
||||||
|
/// ByteVector can declare its own versions of To/From/Size methods if it needs dedicated logic to serialize type.
|
||||||
|
/// @tparam T Type for serialization.
|
||||||
|
template <typename T>
|
||||||
|
struct PointerTupleConverter : TupleConverter<T>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// @brief Class applying pointers to members to object.
|
||||||
|
/// Compatible with std::apply.
|
||||||
|
/// Creates TupleConverter<T>::ConvertType object.
|
||||||
|
class ReferenceMembers
|
||||||
|
{
|
||||||
|
T const& m_Obj;
|
||||||
|
public:
|
||||||
|
ReferenceMembers(T const& obj) : m_Obj{ obj } {}
|
||||||
|
|
||||||
|
template <typename ... Ts>
|
||||||
|
auto operator () (Ts T::*...ts) const
|
||||||
|
{
|
||||||
|
return Utils::MakeConversionTuple(m_Obj.*ts ...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Function assigning object members with tuple of values using tuple member pointers.
|
||||||
|
/// @tparam PtrTpl Tuple of pointers to members type.
|
||||||
|
/// @tparam ValueTpl Tuple of values type.
|
||||||
|
/// @tparam Is Index sequence used to match tuples one to one.
|
||||||
|
/// @param obj Object to be assigned.
|
||||||
|
/// @param ptrTpl Tuple of pointers to members.
|
||||||
|
/// @param valueTpl Tuple of values.
|
||||||
|
template <typename PtrTpl, typename ValueTpl, size_t ...Is>
|
||||||
|
static void AssignToMembers(T& obj, PtrTpl const& ptrTpl, ValueTpl valueTpl, std::index_sequence<Is...>)
|
||||||
|
{
|
||||||
|
((obj.*(std::get<Is>(ptrTpl)) = std::move(std::get<Is>(valueTpl))), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief Default implementation of Convert method used by TupleConverter for serialization.
|
||||||
|
/// Function uses ByteConverter<T>::MemberPointers() to reference T object members.
|
||||||
|
/// @param obj object to be serialized.
|
||||||
|
/// @return TupleConverter<T>::ConvertType values to be serialized.
|
||||||
|
static auto Convert(T const& obj)
|
||||||
|
{
|
||||||
|
auto ptrTpl = ByteConverter<T>::MemberPointers();
|
||||||
|
return std::apply(ReferenceMembers{ obj }, ptrTpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Shadowed TupleConverter<T>::From initalizing only selected members, skipped ones will be default initialized.
|
||||||
|
/// @note T must have default constructor.
|
||||||
|
/// @param bv. Buffer with serialized data.
|
||||||
|
/// @return constructed type.
|
||||||
|
static T From(ByteView& bv)
|
||||||
|
{
|
||||||
|
auto ret = T{};
|
||||||
|
auto ptrTpl = ByteConverter<T>::MemberPointers();
|
||||||
|
auto valueTpl = TupleConverter<T>::Convert(bv);
|
||||||
|
AssignToMembers(ret, ptrTpl, std::move(valueTpl), std::make_index_sequence<std::tuple_size<decltype(ptrTpl)>::value>{});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,13 @@ namespace FSecure
|
||||||
static constexpr bool value = ((ConverterDeduction<Ts>::FunctionTo::value != ConverterDeduction<Ts>::FunctionTo::absent) && ...);
|
static constexpr bool value = ((ConverterDeduction<Ts>::FunctionTo::value != ConverterDeduction<Ts>::FunctionTo::absent) && ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Check if type can be concatenated
|
||||||
|
template <typename ...Ts>
|
||||||
|
struct ConcatCondition
|
||||||
|
{
|
||||||
|
static constexpr bool value = (sizeof...(Ts) > 0) && ((Utils::IsOneOf<Ts, ByteView, ByteVector>::value && ...));
|
||||||
|
};
|
||||||
|
|
||||||
/// An owning container.
|
/// An owning container.
|
||||||
class ByteVector : std::vector<std::uint8_t>
|
class ByteVector : std::vector<std::uint8_t>
|
||||||
{
|
{
|
||||||
|
@ -181,7 +188,7 @@ namespace FSecure
|
||||||
/// Does not write header with size..
|
/// Does not write header with size..
|
||||||
/// @param args. Objects to be stored.
|
/// @param args. Objects to be stored.
|
||||||
/// @return itself to allow chaining.
|
/// @return itself to allow chaining.
|
||||||
template <typename ...Ts, typename = std::enable_if_t<(sizeof...(Ts) > 0) && ((Utils::IsOneOf<Ts, ByteView, ByteVector>::value && ...))>>
|
template <typename ...Ts, typename std::enable_if_t<ConcatCondition<Ts...>::value, int> = 0>
|
||||||
ByteVector& Concat(Ts const& ...args)
|
ByteVector& Concat(Ts const& ...args)
|
||||||
{
|
{
|
||||||
auto oldSize = size();
|
auto oldSize = size();
|
||||||
|
@ -207,7 +214,7 @@ namespace FSecure
|
||||||
template <typename T, typename ...Ts, typename std::enable_if_t<WriteCondition<T, Ts...>::value, int> = 0>
|
template <typename T, typename ...Ts, typename std::enable_if_t<WriteCondition<T, Ts...>::value, int> = 0>
|
||||||
static ByteVector Create(T const& arg, Ts const& ...args)
|
static ByteVector Create(T const& arg, Ts const& ...args)
|
||||||
{
|
{
|
||||||
return ByteVector{}.Write(arg, args...);
|
return std::move(ByteVector{}.Write(arg, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the size that the argument will take in memory
|
/// Calculate the size that the argument will take in memory
|
||||||
|
@ -215,9 +222,9 @@ namespace FSecure
|
||||||
/// @param args. Rest of types that will be handled with recursion.
|
/// @param args. Rest of types that will be handled with recursion.
|
||||||
/// @return size_t number of bytes needed.
|
/// @return size_t number of bytes needed.
|
||||||
template<typename T, typename ...Ts>
|
template<typename T, typename ...Ts>
|
||||||
static size_t Size(T const& arg, Ts const& ...args)
|
static size_t Size([[maybe_unused]] T const& arg, Ts const& ...args)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof...(Ts) != 0)
|
if constexpr (sizeof...(args) != 0)
|
||||||
return Size(arg) + Size(args...);
|
return Size(arg) + Size(args...);
|
||||||
else if constexpr (ConverterDeduction<T>::FunctionSize::value == ConverterDeduction<T>::FunctionSize::compileTime)
|
else if constexpr (ConverterDeduction<T>::FunctionSize::value == ConverterDeduction<T>::FunctionSize::compileTime)
|
||||||
return ByteConverter<T>::Size();
|
return ByteConverter<T>::Size();
|
||||||
|
@ -258,6 +265,10 @@ namespace FSecure
|
||||||
/// Declaration of friendship.
|
/// Declaration of friendship.
|
||||||
template <typename , typename>
|
template <typename , typename>
|
||||||
friend struct ByteConverter;
|
friend struct ByteConverter;
|
||||||
|
|
||||||
|
/// Declaration of friendship.
|
||||||
|
template <typename>
|
||||||
|
friend struct TupleConverter;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Literals
|
namespace Literals
|
||||||
|
|
|
@ -193,24 +193,6 @@ namespace FSecure
|
||||||
/// ByteReader will modify ByteView used for it construction.
|
/// ByteReader will modify ByteView used for it construction.
|
||||||
ByteView& m_byteView;
|
ByteView& m_byteView;
|
||||||
|
|
||||||
/// Declaration of base template used for pointer to member type deduction.
|
|
||||||
template<class T>
|
|
||||||
struct SplitMemberPointer;
|
|
||||||
|
|
||||||
/// Specialization that will perform type deduction.
|
|
||||||
template<class C, class T>
|
|
||||||
struct SplitMemberPointer<T C::*> {
|
|
||||||
using type = T;
|
|
||||||
using declaringType = C;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Function used to call constructor of type T with tuple of types matching constructor arguments.
|
|
||||||
template<typename T, typename Tpl, size_t... Is>
|
|
||||||
static T TupleToConstructor(Tpl&& tpl, std::integer_sequence<size_t, Is...>)
|
|
||||||
{
|
|
||||||
return T{ std::get<Is>(std::move(tpl))... };
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Create ByteReader.
|
/// Create ByteReader.
|
||||||
/// @param bv, ByteView with data to read.
|
/// @param bv, ByteView with data to read.
|
||||||
|
@ -225,27 +207,6 @@ namespace FSecure
|
||||||
{
|
{
|
||||||
((ts = m_byteView.Read<decltype(ts)>()), ...);
|
((ts = m_byteView.Read<decltype(ts)>()), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create object by reading provided types, and passing them to object constructor.
|
|
||||||
/// @tparam T, type to be constructed.
|
|
||||||
/// @tparam Ts, types to be read from ByteView, and passed as T constructor arguments.
|
|
||||||
/// @note T is not the same as first template parameter of Create(...).
|
|
||||||
template <typename T, typename ...Ts>
|
|
||||||
auto Create() -> decltype(T{ std::declval<Ts>()... })
|
|
||||||
{
|
|
||||||
return TupleToConstructor<T>(m_byteView.Read<Ts...>(), std::make_index_sequence<sizeof...(Ts)>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Create object by reading provided types deduced from pointers to members
|
|
||||||
/// @tparam T, first pointer to member. Ensures that at least one object will be read from ByteView
|
|
||||||
/// @tparam Ts, rest of pointers to members.
|
|
||||||
/// @note T is not the same as first template parameter of Create(void).
|
|
||||||
template <typename T, typename ...Ts>
|
|
||||||
auto Create(T, Ts...) -> decltype(typename SplitMemberPointer<T>::declaringType{ std::declval<typename SplitMemberPointer<T>::type>(), std::declval<typename SplitMemberPointer<Ts>::type>()... })
|
|
||||||
{
|
|
||||||
return TupleToConstructor<typename SplitMemberPointer<T>::declaringType>(m_byteView.Read<typename SplitMemberPointer<T>::type, typename SplitMemberPointer<Ts>::type...>(), std::make_index_sequence<1 + sizeof...(Ts)>{});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#ifndef OBF
|
#ifndef OBF
|
||||||
# define OBF(x) x
|
# define OBF(x) x
|
||||||
|
@ -229,4 +230,110 @@ namespace FSecure::Utils
|
||||||
enum { value = (sizeof(test<T>(0)) - sizeof(uint8_t)) };
|
enum { value = (sizeof(test<T>(0)) - sizeof(uint8_t)) };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Namespace for internal implementation
|
||||||
|
namespace Detail
|
||||||
|
{
|
||||||
|
/// @brief Default implementation of class checking if it is worth to take reference or copy by value
|
||||||
|
/// Represents false.
|
||||||
|
template<typename T, typename Enable>
|
||||||
|
struct WorthAddingConstRefImpl : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
/// @brief Specialization of class checking if it is worth to take reference or copy by value.
|
||||||
|
/// Represents true.
|
||||||
|
template<typename T>
|
||||||
|
struct WorthAddingConstRefImpl<T,
|
||||||
|
std::enable_if_t<
|
||||||
|
!std::is_rvalue_reference_v<T> && (!std::is_trivial_v<std::remove_reference_t<T>> || (sizeof(T) > sizeof(long long)))
|
||||||
|
>
|
||||||
|
> : std::true_type{};
|
||||||
|
|
||||||
|
/// @brief Default implementation of class declaring simpler type to use based on T type.
|
||||||
|
/// Represents copy by value.
|
||||||
|
template<typename T, typename Enable>
|
||||||
|
struct AddConstRefToNonTrivialImpl
|
||||||
|
{
|
||||||
|
using type = std::remove_reference_t<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Specialization of class declaring simpler type to use based on T type.
|
||||||
|
/// Represents copy by reference.
|
||||||
|
template<typename T>
|
||||||
|
struct AddConstRefToNonTrivialImpl<T, std::enable_if_t<WorthAddingConstRefImpl<T, void>::value>>
|
||||||
|
{
|
||||||
|
using type = std::remove_reference_t<T> const&;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Class checking if it is worth to take reference or copy by value.
|
||||||
|
template<typename T>
|
||||||
|
struct WorthAddingConstRef : Detail::WorthAddingConstRefImpl<T, void> {};
|
||||||
|
|
||||||
|
/// @brief Simplified WorthAddingConstRef<T>::value.
|
||||||
|
template<typename T>
|
||||||
|
static constexpr auto WorthAddingConstRefV = WorthAddingConstRef<T>::value;
|
||||||
|
|
||||||
|
/// @brief Class declaring simpler type to use based on T type.
|
||||||
|
template<typename T>
|
||||||
|
struct AddConstRefToNonTrivial : Detail::AddConstRefToNonTrivialImpl<T, void> {};
|
||||||
|
|
||||||
|
/// @brief Simplified AddConstRefToNonTrivial<T>::type.
|
||||||
|
template<typename T>
|
||||||
|
using AddConstRefToNonTrivialT = typename AddConstRefToNonTrivial<T>::type;
|
||||||
|
|
||||||
|
/// @brief Helper allowing transformation of provided arguments to tuple of values/references that are used for serialization.
|
||||||
|
/// @param ...args arguments to be stored in tuple
|
||||||
|
/// @return tuple with references to non trivial types, and values of simple ones.
|
||||||
|
template<typename ...Args>
|
||||||
|
auto MakeConversionTuple(Args&& ...args)
|
||||||
|
{
|
||||||
|
return std::tuple<AddConstRefToNonTrivialT<Args&&>...>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construction with parentheses and with braces is not interchangeable.
|
||||||
|
/// std::make_from_tuple must use constructor and is unable to create trivial type.
|
||||||
|
/// Types implemented in this namespace, alongside with std::apply, allows us choose method used for construction.
|
||||||
|
/// For more information look at:
|
||||||
|
/// https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/aQQzL0JoXLg
|
||||||
|
namespace Construction
|
||||||
|
{
|
||||||
|
/// @brief Type used for construction with braces.
|
||||||
|
template <typename T>
|
||||||
|
struct Braces
|
||||||
|
{
|
||||||
|
template <typename ... As>
|
||||||
|
constexpr auto operator () (As&& ... as) const
|
||||||
|
{
|
||||||
|
return T{ std::forward<As>(as)... };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Type used for construction with parentheses.
|
||||||
|
template <typename T>
|
||||||
|
struct Parentheses
|
||||||
|
{
|
||||||
|
template <typename ... As>
|
||||||
|
constexpr auto operator () (As&& ... as) const
|
||||||
|
{
|
||||||
|
return T(std::forward<As>(as)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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>{});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,63 +36,35 @@ namespace FSecure
|
||||||
|
|
||||||
/// overload ByteConverter for RTL_OSVERSIONINFOEXW. szCSDVersion and wSuiteMask are omitted.
|
/// overload ByteConverter for RTL_OSVERSIONINFOEXW. szCSDVersion and wSuiteMask are omitted.
|
||||||
template<>
|
template<>
|
||||||
struct ByteConverter<RTL_OSVERSIONINFOEXW>
|
struct ByteConverter<RTL_OSVERSIONINFOEXW> : PointerTupleConverter<RTL_OSVERSIONINFOEXW>
|
||||||
{
|
{
|
||||||
/// Serialize HostInfo type to ByteVector.
|
/// Serialization of RTL_OSVERSIONINFOEXW type to/from ByteVector.
|
||||||
/// @param obj. Object to be serialized.
|
/// @param obj. Object to be serialized.
|
||||||
/// @param bv. ByteVector to be expanded.
|
static auto MemberPointers()
|
||||||
static void To(RTL_OSVERSIONINFOEXW const& obj, ByteVector& bv)
|
|
||||||
{
|
{
|
||||||
bv.Store(obj.dwOSVersionInfoSize, obj.dwMajorVersion, obj.dwMinorVersion, obj.dwBuildNumber, obj.dwPlatformId, obj.wServicePackMajor, obj.wServicePackMinor, obj.wProductType);
|
using T = RTL_OSVERSIONINFOEXW;
|
||||||
}
|
return std::make_tuple(
|
||||||
|
&T::dwOSVersionInfoSize,
|
||||||
/// Get size required after serialization.
|
&T::dwMajorVersion,
|
||||||
/// @param obj. Object to be serialized.
|
&T::dwMinorVersion,
|
||||||
/// @return size_t. Number of bytes used after serialization.
|
&T::dwBuildNumber,
|
||||||
static size_t Size()
|
&T::dwPlatformId,
|
||||||
{
|
&T::wServicePackMajor,
|
||||||
RTL_OSVERSIONINFOEXW* p = nullptr;
|
&T::wServicePackMinor,
|
||||||
return ByteVector::Size(p->dwOSVersionInfoSize, p->dwMajorVersion, p->dwMinorVersion, p->dwBuildNumber, p->dwPlatformId, p->wServicePackMajor, p->wServicePackMinor, p->wProductType);
|
&T::wProductType
|
||||||
}
|
);
|
||||||
|
|
||||||
/// Deserialize from ByteView.
|
|
||||||
/// @param bv. Buffer with serialized data.
|
|
||||||
/// @return RTL_OSVERSIONINFOEXW.
|
|
||||||
static RTL_OSVERSIONINFOEXW From(ByteView& bv)
|
|
||||||
{
|
|
||||||
RTL_OSVERSIONINFOEXW obj = {0,};
|
|
||||||
ByteReader{ bv }.Read(obj.dwOSVersionInfoSize, obj.dwMajorVersion, obj.dwMinorVersion, obj.dwBuildNumber, obj.dwPlatformId, obj.wServicePackMajor, obj.wServicePackMinor, obj.wProductType);
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// overload ByteConverter for HostInfo
|
/// overload ByteConverter for HostInfo
|
||||||
template<>
|
template<>
|
||||||
struct ByteConverter<HostInfo>
|
struct ByteConverter<HostInfo> : TupleConverter<HostInfo>
|
||||||
{
|
{
|
||||||
/// Serialize HostInfo type to ByteVector.
|
/// Serialization of HostInfo type to/from ByteVector.
|
||||||
/// @param obj. Object to be serialized.
|
/// @param obj. Object to be serialized.
|
||||||
/// @param bv. ByteVector to be expanded.
|
static auto Convert(HostInfo const& obj)
|
||||||
static void To(HostInfo const& obj, ByteVector& bv)
|
|
||||||
{
|
{
|
||||||
bv.Store(obj.m_ComputerName, obj.m_UserName, obj.m_Domain, obj.m_OsVersionInfo, obj.m_ProcessId, obj.m_IsElevated);
|
return Utils::MakeConversionTuple(obj.m_ComputerName, obj.m_UserName, obj.m_Domain, obj.m_OsVersionInfo, obj.m_ProcessId, obj.m_IsElevated);
|
||||||
}
|
|
||||||
|
|
||||||
/// Get size required after serialization.
|
|
||||||
/// @param obj. Object to be serialized.
|
|
||||||
/// @return size_t. Number of bytes used after serialization.
|
|
||||||
static size_t Size(HostInfo const& obj)
|
|
||||||
{
|
|
||||||
return ByteVector::Size(obj.m_ComputerName, obj.m_UserName, obj.m_Domain, obj.m_OsVersionInfo, obj.m_ProcessId, obj.m_IsElevated);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize from ByteView.
|
|
||||||
/// @param bv. Buffer with serialized data.
|
|
||||||
/// @return arithmetic type.
|
|
||||||
static HostInfo From(ByteView& bv)
|
|
||||||
{
|
|
||||||
using T = HostInfo;
|
|
||||||
return ByteReader{ bv }.Create(&T::m_ComputerName, &T::m_UserName, &T::m_Domain, &T::m_OsVersionInfo, &T::m_ProcessId, &T::m_IsElevated);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,21 +78,11 @@ namespace FSecure
|
||||||
{
|
{
|
||||||
/// Specialize ByteConverter for RouteId.
|
/// Specialize ByteConverter for RouteId.
|
||||||
template <>
|
template <>
|
||||||
struct ByteConverter <C3::RouteId>
|
struct ByteConverter<C3::RouteId> : TupleConverter<C3::RouteId>
|
||||||
{
|
{
|
||||||
static void To(C3::RouteId const& obj, ByteVector& bv)
|
static auto Convert(C3::RouteId const& obj)
|
||||||
{
|
{
|
||||||
bv.Store(obj.GetAgentId(), obj.GetInterfaceId());
|
return Utils::MakeConversionTuple(obj.GetAgentId(), obj.GetInterfaceId());
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static size_t Size()
|
|
||||||
{
|
|
||||||
return C3::RouteId::BinarySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static C3::RouteId From(ByteView& bv)
|
|
||||||
{
|
|
||||||
return ByteReader{ bv }.Create<C3::RouteId, decltype(std::declval<C3::RouteId>().GetAgentId()), decltype(std::declval<C3::RouteId>().GetInterfaceId())>();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue