Merge pull request 'Update SerializeAdapter' (#513) from KSat/fsfw:mueller/serializeif-update into development

Reviewed-on: fsfw/fsfw#513
This commit is contained in:
Steffen Gaisser 2021-11-29 14:37:40 +01:00
commit bf31248a50
2 changed files with 429 additions and 268 deletions

View File

@ -7,7 +7,7 @@
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
/** /**
* @brief These adapters provides an interface to use the SerializeIF functions * @brief These adapters provides an interface to use the SerializeIF functions
* with arbitrary template objects to facilitate and simplify the * with arbitrary template objects to facilitate and simplify the
* serialization of classes with different multiple different data types * serialization of classes with different multiple different data types
@ -20,174 +20,250 @@
*/ */
class SerializeAdapter { class SerializeAdapter {
public: public:
/*** /***
* This function can be used to serialize a trivial copy-able type or a * @brief Serialize a trivial copy-able type or a child of SerializeIF.
* child of SerializeIF. * @details
* The right template to be called is determined in the function itself. * The right template to be called is determined in the function itself.
* For objects of non trivial copy-able type this function is almost never * For objects of non trivial copy-able type this function is almost never
* called by the user directly. Instead helpers for specific types like * called by the user directly. Instead helpers for specific types like
* SerialArrayListAdapter or SerialLinkedListAdapter is the right choice here. * SerialArrayListAdapter or SerialLinkedListAdapter are the right choice here.
* *
* @param[in] object Object to serialize, the used type is deduced from this pointer * @param[in] object: Object to serialize, the used type is deduced from this pointer
* @param[in/out] buffer Buffer to serialize into. Will be moved by the function. * @param[in/out] buffer: Pointer to the buffer to serialize into. Buffer position will be
* @param[in/out] size Size of current written buffer. Will be incremented by the function. * incremented by the function.
* @param[in] maxSize Max size of Buffer * @param[in/out] size: Pointer to size of current written buffer.
* @param[in] streamEndianness Endianness of serialized element as in according to SerializeIF::Endianness * SIze will be incremented by the function.
* @return * @param[in] maxSize: Max size of Buffer
* - @c BUFFER_TOO_SHORT The given buffer in is too short * @param[in] streamEndianness: Endianness of serialized element as in according to
* - @c RETURN_FAILED Generic Error * SerializeIF::Endianness
* - @c RETURN_OK Successful serialization * @return
*/ * - @c BUFFER_TOO_SHORT The given buffer in is too short
template<typename T> * - @c RETURN_FAILED Generic Error
static ReturnValue_t serialize(const T *object, uint8_t **buffer, * - @c RETURN_OK Successful serialization
size_t *size, size_t maxSize, */
SerializeIF::Endianness streamEndianness) { template<typename T>
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter; static ReturnValue_t serialize(const T *object, uint8_t **buffer,
return adapter.serialize(object, buffer, size, maxSize, size_t *size, size_t maxSize,
streamEndianness); SerializeIF::Endianness streamEndianness) {
} InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter;
/** return adapter.serialize(object, buffer, size, maxSize,
* Function to return the serialized size of the object in the pointer. streamEndianness);
* May be a trivially copy-able object or a Child of SerializeIF }
*
* @param object Pointer to Object /***
* @return Serialized size of object * This function can be used to serialize a trivial copy-able type or a child of SerializeIF.
*/ * The right template to be called is determined in the function itself.
template<typename T> * For objects of non trivial copy-able type this function is almost never
static size_t getSerializedSize(const T *object){ * called by the user directly. Instead helpers for specific types like
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter; * SerialArrayListAdapter or SerialLinkedListAdapter are the right choice here.
return adapter.getSerializedSize(object); *
} * @param[in] object: Object to serialize, the used type is deduced from this pointer
/** * @param[in/out] buffer: Buffer to serialize into.
* @brief * @param[out] serSize: Serialized size
* Deserializes a object from a given buffer of given size. * @param[in] maxSize: Max size of buffer
* Object Must be trivially copy-able or a child of SerializeIF. * @param[in] streamEndianness: Endianness of serialized element as in according to
* * SerializeIF::Endianness
* @details * @return
* Buffer will be moved to the current read location. Size will be decreased by the function. * - @c BUFFER_TOO_SHORT The given buffer in is too short
* * - @c RETURN_FAILED Generic Error
* @param[in/out] buffer Buffer to deSerialize from. Will be moved by the function. * - @c RETURN_OK Successful serialization
* @param[in/out] size Remaining size of the buffer to read from. Will be decreased by function. */
* @param[in] streamEndianness Endianness as in according to SerializeIF::Endianness template<typename T>
* @return static ReturnValue_t serialize(const T *object, uint8_t* const buffer, size_t* serSize,
* - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object size_t maxSize, SerializeIF::Endianness streamEndianness) {
* - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected if(object == nullptr or buffer == nullptr) {
* - @c RETURN_FAILED Generic Error return HasReturnvaluesIF::RETURN_FAILED;
* - @c RETURN_OK Successful deserialization }
*/ InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter;
template<typename T> uint8_t** tempPtr = const_cast<uint8_t**>(&buffer);
static ReturnValue_t deSerialize(T *object, const uint8_t **buffer, size_t tmpSize = 0;
size_t *size, SerializeIF::Endianness streamEndianness) { ReturnValue_t result = adapter.serialize(object, tempPtr, &tmpSize, maxSize,
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter; streamEndianness);
return adapter.deSerialize(object, buffer, size, streamEndianness); if(serSize != nullptr) {
} *serSize = tmpSize;
}
return result;
}
/**
* @brief Function to return the serialized size of the object in the pointer.
* @details
* May be a trivially copy-able object or a child of SerializeIF.
*
* @param object Pointer to Object
* @return Serialized size of object
*/
template<typename T>
static size_t getSerializedSize(const T *object){
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter;
return adapter.getSerializedSize(object);
}
/**
* @brief Deserializes a object from a given buffer of given size.
*
* @details
* Object Must be trivially copy-able or a child of SerializeIF.
* Buffer will be moved to the current read location. Size will be decreased by the function.
*
* @param[in] object: Pointer to object to deserialize
* @param[in/out] buffer: Pointer to the buffer to deSerialize from. Buffer position will be
* incremented by the function
* @param[in/out] size: Pointer to remaining size of the buffer to read from.
* Will be decreased by function.
* @param[in] streamEndianness: Endianness as in according to SerializeIF::Endianness
* @return
* - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object
* - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected
* - @c RETURN_FAILED Generic Error
* - @c RETURN_OK Successful deserialization
*/
template<typename T>
static ReturnValue_t deSerialize(T *object, const uint8_t **buffer,
size_t *size, SerializeIF::Endianness streamEndianness) {
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter;
return adapter.deSerialize(object, buffer, size, streamEndianness);
}
/**
* @brief Deserializes a object from a given buffer of given size.
*
* @details
* Object Must be trivially copy-able or a child of SerializeIF.
*
* @param[in] object: Pointer to object to deserialize
* @param[in] buffer: Buffer to deSerialize from
* @param[out] deserSize: Deserialized length
* @param[in] streamEndianness: Endianness as in according to SerializeIF::Endianness
* @return
* - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object
* - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected
* - @c RETURN_FAILED Generic Error
* - @c RETURN_OK Successful deserialization
*/
template<typename T>
static ReturnValue_t deSerialize(T *object, const uint8_t* buffer,
size_t* deserSize, SerializeIF::Endianness streamEndianness) {
if(object == nullptr or buffer == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
InternalSerializeAdapter<T, std::is_base_of<SerializeIF, T>::value> adapter;
const uint8_t** tempPtr = &buffer;
size_t maxVal = -1;
ReturnValue_t result = adapter.deSerialize(object, tempPtr, &maxVal, streamEndianness);
if(deserSize != nullptr) {
*deserSize = -1 - maxVal;
}
return result;
}
private: private:
/** /**
* Internal template to deduce the right function calls at compile time * Internal template to deduce the right function calls at compile time
*/ */
template<typename T, bool> class InternalSerializeAdapter; template<typename T, bool> class InternalSerializeAdapter;
/** /**
* Template to be used if T is not a child of SerializeIF * Template to be used if T is not a child of SerializeIF
* *
* @tparam T T must be trivially_copyable * @tparam T T must be trivially_copyable
*/ */
template<typename T> template<typename T>
class InternalSerializeAdapter<T, false> { class InternalSerializeAdapter<T, false> {
static_assert (std::is_trivially_copyable<T>::value, static_assert (std::is_trivially_copyable<T>::value,
"If a type needs to be serialized it must be a child of " "If a type needs to be serialized it must be a child of "
"SerializeIF or trivially copy-able"); "SerializeIF or trivially copy-able");
public: public:
static ReturnValue_t serialize(const T *object, uint8_t **buffer, static ReturnValue_t serialize(const T *object, uint8_t **buffer,
size_t *size, size_t max_size, size_t *size, size_t max_size,
SerializeIF::Endianness streamEndianness) { SerializeIF::Endianness streamEndianness) {
size_t ignoredSize = 0; size_t ignoredSize = 0;
if (size == nullptr) { if (size == nullptr) {
size = &ignoredSize; size = &ignoredSize;
} }
// Check remaining size is large enough and check integer // Check remaining size is large enough and check integer
// overflow of *size // overflow of *size
size_t newSize = sizeof(T) + *size; size_t newSize = sizeof(T) + *size;
if ((newSize <= max_size) and (newSize > *size)) { if ((newSize <= max_size) and (newSize > *size)) {
T tmp; T tmp;
switch (streamEndianness) { switch (streamEndianness) {
case SerializeIF::Endianness::BIG: case SerializeIF::Endianness::BIG:
tmp = EndianConverter::convertBigEndian<T>(*object); tmp = EndianConverter::convertBigEndian<T>(*object);
break; break;
case SerializeIF::Endianness::LITTLE: case SerializeIF::Endianness::LITTLE:
tmp = EndianConverter::convertLittleEndian<T>(*object); tmp = EndianConverter::convertLittleEndian<T>(*object);
break; break;
default: default:
case SerializeIF::Endianness::MACHINE: case SerializeIF::Endianness::MACHINE:
tmp = *object; tmp = *object;
break; break;
} }
std::memcpy(*buffer, &tmp, sizeof(T)); std::memcpy(*buffer, &tmp, sizeof(T));
*size += sizeof(T); *size += sizeof(T);
(*buffer) += sizeof(T); (*buffer) += sizeof(T);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return SerializeIF::BUFFER_TOO_SHORT; return SerializeIF::BUFFER_TOO_SHORT;
} }
} }
ReturnValue_t deSerialize(T *object, const uint8_t **buffer, ReturnValue_t deSerialize(T *object, const uint8_t **buffer,
size_t *size, SerializeIF::Endianness streamEndianness) { size_t *size, SerializeIF::Endianness streamEndianness) {
T tmp; T tmp;
if (*size >= sizeof(T)) { if (*size >= sizeof(T)) {
*size -= sizeof(T); *size -= sizeof(T);
std::memcpy(&tmp, *buffer, sizeof(T)); std::memcpy(&tmp, *buffer, sizeof(T));
switch (streamEndianness) { switch (streamEndianness) {
case SerializeIF::Endianness::BIG: case SerializeIF::Endianness::BIG:
*object = EndianConverter::convertBigEndian<T>(tmp); *object = EndianConverter::convertBigEndian<T>(tmp);
break; break;
case SerializeIF::Endianness::LITTLE: case SerializeIF::Endianness::LITTLE:
*object = EndianConverter::convertLittleEndian<T>(tmp); *object = EndianConverter::convertLittleEndian<T>(tmp);
break; break;
default: default:
case SerializeIF::Endianness::MACHINE: case SerializeIF::Endianness::MACHINE:
*object = tmp; *object = tmp;
break; break;
} }
*buffer += sizeof(T); *buffer += sizeof(T);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return SerializeIF::STREAM_TOO_SHORT; return SerializeIF::STREAM_TOO_SHORT;
} }
} }
uint32_t getSerializedSize(const T *object) { uint32_t getSerializedSize(const T *object) {
return sizeof(T); return sizeof(T);
} }
}; };
/** /**
* Template for objects that inherit from SerializeIF * Template for objects that inherit from SerializeIF
* *
* @tparam T A child of SerializeIF * @tparam T A child of SerializeIF
*/ */
template<typename T> template<typename T>
class InternalSerializeAdapter<T, true> { class InternalSerializeAdapter<T, true> {
public: public:
ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size, ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size,
size_t max_size, size_t max_size,
SerializeIF::Endianness streamEndianness) const { SerializeIF::Endianness streamEndianness) const {
size_t ignoredSize = 0; size_t ignoredSize = 0;
if (size == nullptr) { if (size == nullptr) {
size = &ignoredSize; size = &ignoredSize;
} }
return object->serialize(buffer, size, max_size, streamEndianness); return object->serialize(buffer, size, max_size, streamEndianness);
} }
size_t getSerializedSize(const T *object) const { size_t getSerializedSize(const T *object) const {
return object->getSerializedSize(); return object->getSerializedSize();
} }
ReturnValue_t deSerialize(T *object, const uint8_t **buffer, ReturnValue_t deSerialize(T *object, const uint8_t **buffer,
size_t *size, SerializeIF::Endianness streamEndianness) { size_t *size, SerializeIF::Endianness streamEndianness) {
return object->deSerialize(buffer, size, streamEndianness); return object->deSerialize(buffer, size, streamEndianness);
} }
}; };
}; };
#endif /* _FSFW_SERIALIZE_SERIALIZEADAPTER_H_ */ #endif /* _FSFW_SERIALIZE_SERIALIZEADAPTER_H_ */

View File

@ -3,128 +3,213 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp> #include <catch2/catch_approx.hpp>
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <array> #include <array>
static bool test_value_bool = true; static bool testBool = true;
static uint8_t tv_uint8 {5}; static uint8_t tvUint8 {5};
static uint16_t tv_uint16 {283}; static uint16_t tvUint16 {283};
static uint32_t tv_uint32 {929221}; static uint32_t tvUint32 {929221};
static uint64_t tv_uint64 {2929329429}; static uint64_t tvUint64 {2929329429};
static int8_t tv_int8 {-16}; static int8_t tvInt8 {-16};
static int16_t tv_int16 {-829}; static int16_t tvInt16 {-829};
static int32_t tv_int32 {-2312}; static int32_t tvInt32 {-2312};
static float tv_float {8.2149214}; static float tvFloat {8.2149214};
static float tv_sfloat = {-922.2321321}; static float tvSfloat = {-922.2321321};
static double tv_double {9.2132142141e8}; static double tvDouble {9.2132142141e8};
static double tv_sdouble {-2.2421e19}; static double tvSdouble {-2.2421e19};
static std::array<uint8_t, 512> test_array; static std::array<uint8_t, 512> TEST_ARRAY;
TEST_CASE( "Serialization size tests", "[TestSerialization]") { TEST_CASE( "Serialization size tests", "[SerSizeTest]") {
//REQUIRE(unitTestClass.test_autoserialization() == 0); //REQUIRE(unitTestClass.test_autoserialization() == 0);
REQUIRE(SerializeAdapter::getSerializedSize(&test_value_bool) == REQUIRE(SerializeAdapter::getSerializedSize(&testBool) ==
sizeof(test_value_bool)); sizeof(testBool));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint8) == REQUIRE(SerializeAdapter::getSerializedSize(&tvUint8) ==
sizeof(tv_uint8)); sizeof(tvUint8));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint16) == REQUIRE(SerializeAdapter::getSerializedSize(&tvUint16) ==
sizeof(tv_uint16)); sizeof(tvUint16));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint32 ) == REQUIRE(SerializeAdapter::getSerializedSize(&tvUint32 ) ==
sizeof(tv_uint32)); sizeof(tvUint32));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_uint64) == REQUIRE(SerializeAdapter::getSerializedSize(&tvUint64) ==
sizeof(tv_uint64)); sizeof(tvUint64));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int8) == REQUIRE(SerializeAdapter::getSerializedSize(&tvInt8) ==
sizeof(tv_int8)); sizeof(tvInt8));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int16) == REQUIRE(SerializeAdapter::getSerializedSize(&tvInt16) ==
sizeof(tv_int16)); sizeof(tvInt16));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_int32) == REQUIRE(SerializeAdapter::getSerializedSize(&tvInt32) ==
sizeof(tv_int32)); sizeof(tvInt32));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_float) == REQUIRE(SerializeAdapter::getSerializedSize(&tvFloat) ==
sizeof(tv_float)); sizeof(tvFloat));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_sfloat) == REQUIRE(SerializeAdapter::getSerializedSize(&tvSfloat) ==
sizeof(tv_sfloat )); sizeof(tvSfloat ));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_double) == REQUIRE(SerializeAdapter::getSerializedSize(&tvDouble) ==
sizeof(tv_double)); sizeof(tvDouble));
REQUIRE(SerializeAdapter::getSerializedSize(&tv_sdouble) == REQUIRE(SerializeAdapter::getSerializedSize(&tvSdouble) ==
sizeof(tv_sdouble)); sizeof(tvSdouble));
} }
TEST_CASE("Auto Serialize Adapter", "[SerAdapter]") {
size_t serializedSize = 0;
uint8_t * pArray = TEST_ARRAY.data();
TEST_CASE("Auto Serialize Adapter testing", "[single-file]") { SECTION("SerDe") {
size_t serialized_size = 0; size_t deserSize = 0;
uint8_t * p_array = test_array.data(); SerializeAdapter::serialize(&testBool, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 1);
REQUIRE(TEST_ARRAY[0] == true);
bool readBack = false;
SerializeAdapter::deSerialize(&readBack, TEST_ARRAY.data(), &deserSize,
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 1);
REQUIRE(readBack == true);
SerializeAdapter::serialize(&tvUint8, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 1);
REQUIRE(TEST_ARRAY[0] == 5);
uint8_t readBackUint8 = 0;
uint8_t* const testPtr = TEST_ARRAY.data();
uint8_t* const shouldStayConst = testPtr;
SerializeAdapter::deSerialize(&readBackUint8, testPtr, &deserSize,
SerializeIF::Endianness::MACHINE);
REQUIRE(testPtr == shouldStayConst);
REQUIRE(deserSize == 1);
REQUIRE(readBackUint8 == 5);
SerializeAdapter::serialize(&tvUint16, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 2);
deserSize = 0;
uint16_t readBackUint16 = 0;
SerializeAdapter::deSerialize(&readBackUint16, TEST_ARRAY.data(), &deserSize,
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 2);
REQUIRE(readBackUint16 == 283);
SECTION("Serializing...") { SerializeAdapter::serialize(&tvUint32, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeAdapter::serialize(&test_value_bool, &p_array, SerializeIF::Endianness::MACHINE);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); REQUIRE(deserSize == 4);
SerializeAdapter::serialize(&tv_uint8, &p_array, uint32_t readBackUint32 = 0;
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); deserSize = 0;
SerializeAdapter::serialize(&tv_uint16, &p_array, SerializeAdapter::deSerialize(&readBackUint32, TEST_ARRAY.data(), &deserSize,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_uint32, &p_array, REQUIRE(deserSize == 4);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); REQUIRE(readBackUint32 == 929221);
SerializeAdapter::serialize(&tv_int8, &p_array,
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); SerializeAdapter::serialize(&tvInt16, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeAdapter::serialize(&tv_int16, &p_array, SerializeIF::Endianness::MACHINE);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); REQUIRE(deserSize == 2);
SerializeAdapter::serialize(&tv_int32, &p_array, int16_t readBackInt16 = 0;
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); SerializeAdapter::deSerialize(&readBackInt16, TEST_ARRAY.data(), &deserSize,
SerializeAdapter::serialize(&tv_uint64, &p_array, SerializeIF::Endianness::MACHINE);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); REQUIRE(readBackInt16 == -829);
SerializeAdapter::serialize(&tv_float, &p_array, REQUIRE(deserSize == 2);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_double, &p_array, SerializeAdapter::serialize(&tvFloat, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tv_sfloat, &p_array, float readBackFloat = 0.0;
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); SerializeAdapter::deSerialize(&readBackFloat, TEST_ARRAY.data(), &deserSize,
SerializeAdapter::serialize(&tv_sdouble, &p_array, SerializeIF::Endianness::MACHINE);
&serialized_size, test_array.size(), SerializeIF::Endianness::MACHINE); REQUIRE(readBackFloat == Catch::Approx(8.214921));
REQUIRE (serialized_size == 47);
SerializeAdapter::serialize(&tvSdouble, TEST_ARRAY.data(), &deserSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
double readBackSignedDouble = 0.0;
SerializeAdapter::deSerialize(&readBackSignedDouble, TEST_ARRAY.data(), &deserSize,
SerializeIF::Endianness::MACHINE);
REQUIRE(readBackSignedDouble == Catch::Approx(-2.2421e19));
uint8_t testBuf[4] = {1, 2, 3, 4};
SerialBufferAdapter<uint8_t> bufferAdapter(testBuf, sizeof(testBuf));
SerializeAdapter::serialize(&bufferAdapter, TEST_ARRAY.data(), &deserSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 4);
for(uint8_t idx = 0; idx < 4; idx++) {
REQUIRE(TEST_ARRAY[idx] == idx + 1);
}
deserSize = 0;
testBuf[0] = 0;
testBuf[1] = 12;
SerializeAdapter::deSerialize(&bufferAdapter, TEST_ARRAY.data(), &deserSize,
SerializeIF::Endianness::MACHINE);
REQUIRE(deserSize == 4);
for(uint8_t idx = 0; idx < 4; idx++) {
REQUIRE(testBuf[idx] == idx + 1);
}
}
SECTION("Serialize incrementing") {
SerializeAdapter::serialize(&testBool, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvUint8, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvUint16, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvUint32, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvInt8, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvInt16, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvInt32, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvUint64, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvFloat, &pArray, &serializedSize,
TEST_ARRAY.size(), SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvDouble, &pArray, &serializedSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvSfloat, &pArray, &serializedSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
SerializeAdapter::serialize(&tvSdouble, &pArray, &serializedSize, TEST_ARRAY.size(),
SerializeIF::Endianness::MACHINE);
REQUIRE (serializedSize == 47);
} }
SECTION("Deserializing") { SECTION("Deserialize decrementing") {
p_array = test_array.data(); pArray = TEST_ARRAY.data();
size_t remaining_size = serialized_size; size_t remaining_size = serializedSize;
SerializeAdapter::deSerialize(&test_value_bool, SerializeAdapter::deSerialize(&testBool, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_uint8, SerializeAdapter::deSerialize(&tvUint8, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_uint16, SerializeAdapter::deSerialize(&tvUint16, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_uint32, SerializeAdapter::deSerialize(&tvUint32, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_int8, SerializeAdapter::deSerialize(&tvInt8, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_int16, SerializeAdapter::deSerialize(&tvInt16, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_int32, SerializeAdapter::deSerialize(&tvInt32, const_cast<const uint8_t**>(&pArray),
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_uint64, SerializeAdapter::deSerialize(&tvUint64,
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); const_cast<const uint8_t**>(&pArray), &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_float, SerializeAdapter::deSerialize(&tvFloat,
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); const_cast<const uint8_t**>(&pArray), &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_double, SerializeAdapter::deSerialize(&tvDouble,
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); const_cast<const uint8_t**>(&pArray), &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_sfloat, SerializeAdapter::deSerialize(&tvSfloat,
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); const_cast<const uint8_t**>(&pArray), &remaining_size, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&tv_sdouble, SerializeAdapter::deSerialize(&tvSdouble,
const_cast<const uint8_t**>(&p_array), &remaining_size, SerializeIF::Endianness::MACHINE); const_cast<const uint8_t**>(&pArray), &remaining_size, SerializeIF::Endianness::MACHINE);
REQUIRE(test_value_bool == true); REQUIRE(testBool == true);
REQUIRE(tv_uint8 == 5); REQUIRE(tvUint8 == 5);
REQUIRE(tv_uint16 == 283); REQUIRE(tvUint16 == 283);
REQUIRE(tv_uint32 == 929221); REQUIRE(tvUint32 == 929221);
REQUIRE(tv_uint64 == 2929329429); REQUIRE(tvUint64 == 2929329429);
REQUIRE(tv_int8 == -16); REQUIRE(tvInt8 == -16);
REQUIRE(tv_int16 == -829); REQUIRE(tvInt16 == -829);
REQUIRE(tv_int32 == -2312); REQUIRE(tvInt32 == -2312);
REQUIRE(tv_float == Catch::Approx(8.214921)); REQUIRE(tvFloat == Catch::Approx(8.214921));
REQUIRE(tv_double == Catch::Approx(9.2132142141e8)); REQUIRE(tvDouble == Catch::Approx(9.2132142141e8));
REQUIRE(tv_sfloat == Catch::Approx(-922.2321321)); REQUIRE(tvSfloat == Catch::Approx(-922.2321321));
REQUIRE(tv_sdouble == Catch::Approx(-2.2421e19)); REQUIRE(tvSdouble == Catch::Approx(-2.2421e19));
} }
} }