diff --git a/Src/Common/MWR/CppTools/ByteVector.h b/Src/Common/MWR/CppTools/ByteVector.h index a75108b..36e9671 100644 --- a/Src/Common/MWR/CppTools/ByteVector.h +++ b/Src/Common/MWR/CppTools/ByteVector.h @@ -8,6 +8,52 @@ namespace MWR class ByteView; class ByteVector; + /// Empty template of class that can convert data from and to byte form. + /// @tparam T. Custom type that will work with byte containers using this converter type. + /// Specialize this class to add methods: + /// static ByteVector To(T const&); + /// Used to write data. + /// static T From(ByteView&); + /// Used to retrieve data. + /// Function must move ByteView& argument to position after the data that was retrieved. + /// static size_t Size(T const&); + /// Used to calculate size that type will need to be stored in ByteVector. + /// This function is not mandatory. If not provided function `To` will be called twice. + /// Once to calculate size for ByteVector allocation, and a second time to copy data. + template + struct ByteConverter {}; + + /// Example code of specializing ByteConverter for custom type A. + //struct A + //{ + // uint16_t m_a, m_b; + + // A(uint16_t a, uint16_t b) : m_a(a), m_b(b) {} + //}; + + //namespace MWR + //{ + // template <> + // struct ByteConverter + // { + // static ByteVector To(A const& a) + // { + // return ByteVector::Create(a.m_a, a.m_b); + // } + + // static size_t Size(A const& a) + // { + // return 2 * sizeof(uint16_t); + // } + + // static A From(ByteView& bv) + // { + // auto [a, b] = bv.Read(); + // return A(a, b); + // } + // }; + //} + /// Idiom for detecting tuple types. template constexpr bool IsTuple = false; @@ -25,6 +71,17 @@ namespace MWR template using CanStoreType = MWR::Utils::CanApply; + /// Check if MWR namespace has function to get size of type T when it is stored to ByteVector. + template + class GotByteSize + { + template static uint8_t test(decltype(MWR::ByteConverter::Size(std::declval()))); + template static uint16_t test(...); + + public: + enum { value = sizeof(test(0)) == sizeof(uint8_t) }; + }; + /// An owning container. class ByteVector : std::vector { @@ -217,6 +274,16 @@ namespace MWR return *this; } + /// Store custom type. + /// tparam T. Type to be stored. There must exsist MWR::ToBytes(T const&) method avalible to store custom type. + /// @return itself to allow chaining. + template::To(std::declval())), MWR::ByteVector >, int> = 0> + ByteVector & Store(bool unused, T const& arg) + { + Concat(MWR::ByteConverter::To(arg)); + return *this; + } + /// Store all arguments at the end of ByteVector. /// @param storeSize if true four byte header will be added to types in T that does not have size defined at compile time. /// @tparam T. Parameter pack to be written. Types are deduced from function call. @@ -279,6 +346,24 @@ namespace MWR return sizeof(T); } + /// Calculate the size that the argument will take in memory + /// tparam T. Type to be stored. There must exsist MWR::ByteConverter::To(T const&) function and MWR::ByteConverter::Size(T const&) + /// @return size_t number of bytes needed. + template::To(std::declval())), ByteVector> && GotByteSize::value, int> = 0> + static size_t CalculateStoreSize(bool unused, T const& arg) + { + return MWR::ByteConverter::Size(arg); + } + + /// Calculate the size that the argument will take in memory + /// tparam T. Type to be stored. There must exsist MWR::ByteConverter::To(T const&) method avalible to store custom type. + /// @return size_t number of bytes needed. + template::To(std::declval())), ByteVector> && !GotByteSize::value, int> = 0> + static size_t CalculateStoreSize(bool unused, T const& arg) + { + return MWR::ByteConverter::To(arg).size(); + } + /// Calculate the size that the arguments will take in memory. This function is responsible for unwrapping variadic arguments calls. /// @param storeSizeHeader. If true function writes 4 bytes header with size for types that have variable buffer length. /// @param args. arguments to be stored. diff --git a/Src/Common/MWR/CppTools/ByteView.h b/Src/Common/MWR/CppTools/ByteView.h index 0f17626..fe04766 100644 --- a/Src/Common/MWR/CppTools/ByteView.h +++ b/Src/Common/MWR/CppTools/ByteView.h @@ -219,6 +219,15 @@ namespace MWR return retVal; } + /// Read custom type and remove it from ByteView. + /// @tparam T. Type to return; + /// @returns T. + template + std::enable_if_t < std::is_same_v::From(std::declval())), T > , T > Read() + { + return ByteConverter::From(*this); + } + /// Read tuple type. /// @tparam T. Tuple type to return; /// @returns T. Owning container with the read bytes.