diff --git a/include/ylt/struct_pack/endian_wrapper.hpp b/include/ylt/struct_pack/endian_wrapper.hpp index 051faed42..ff36c70d5 100644 --- a/include/ylt/struct_pack/endian_wrapper.hpp +++ b/include/ylt/struct_pack/endian_wrapper.hpp @@ -289,7 +289,8 @@ STRUCT_PACK_INLINE void write(Writer& writer, const T& t) { std::uint64_t len = t.size(); detail::write_wrapper(writer, (char*)&len); if constexpr (detail::continuous_container && - detail::is_little_endian_copyable) { + detail::is_little_endian_copyable && + std::is_fundamental_v) { write_bytes_array(writer, (const char*)t.data(), len * sizeof(t[0])); } else { @@ -353,7 +354,7 @@ STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T* t, template STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) { if constexpr (std::is_fundamental_v) { - if (!detail::read_wrapper(reader, (char*)&t)) { + if SP_UNLIKELY (!detail::read_wrapper(reader, (char*)&t)) { return struct_pack::errc::no_buffer_space; } else { @@ -364,7 +365,12 @@ STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) { if constexpr (std::is_fundamental_v< std::remove_reference_t> && detail::is_little_endian_copyable) { - return read_bytes_array(reader, (char*)t.data(), sizeof(T)); + if SP_UNLIKELY (!read_bytes_array(reader, (char*)t.data(), sizeof(T))) { + return struct_pack::errc::no_buffer_space; + } + else { + return {}; + } } else { struct_pack::errc ec; @@ -395,15 +401,16 @@ STRUCT_PACK_INLINE struct_pack::errc read(Reader& reader, T& t) { if SP_UNLIKELY (!reader.check(mem_size)) { return struct_pack::errc::no_buffer_space; } - detail::resize(t, mem_size); - if (!read_bytes_array(reader, (char*)t.data(), mem_size)) { + detail::resize(t, sz); + if SP_UNLIKELY (!read_bytes_array(reader, (char*)t.data(), mem_size)) { return struct_pack::errc::no_buffer_space; } return struct_pack::errc{}; } else { + t.clear(); for (std::size_t i = 0; i < sz; ++i) { - t.emplace_back(); + t.push_back(typename T::value_type{}); ec = read(reader, t.back()); if SP_UNLIKELY (ec != struct_pack::errc{}) { return ec; @@ -420,7 +427,7 @@ template struct_pack::errc read(Reader& reader, T* t, std::size_t length) { if constexpr (std::is_fundamental_v) { if constexpr (detail::is_little_endian_copyable) { - if (!read_bytes_array(reader, (char*)t, sizeof(T) * length)) { + if SP_UNLIKELY (!read_bytes_array(reader, (char*)t, sizeof(T) * length)) { return struct_pack::errc::no_buffer_space; } else { diff --git a/src/struct_pack/tests/test_user_defined_type.cpp b/src/struct_pack/tests/test_user_defined_type.cpp index 51e1effcb..3f1bc0066 100644 --- a/src/struct_pack/tests/test_user_defined_type.cpp +++ b/src/struct_pack/tests/test_user_defined_type.cpp @@ -3,11 +3,15 @@ #include "doctest.h" #include "ylt/struct_pack.hpp" +#include "ylt/struct_pack/endian_wrapper.hpp" #include "ylt/struct_pack/error_code.hpp" #include "ylt/struct_pack/type_id.hpp" namespace my_name_space { struct array2D { + std::string name = "Hello"; + std::vector> values = {{-1, 2, 3}}; + std::array values2 = {1.1, 2.3, 4.5}; unsigned int x; unsigned int y; float* p; @@ -15,30 +19,46 @@ struct array2D { p = (float*)calloc(1ull * x * y, sizeof(float)); } array2D(const array2D&) = delete; - array2D(array2D&& o) : x(o.x), y(o.y), p(o.p) { o.p = nullptr; }; + array2D(array2D&& o) + : x(o.x), + y(o.y), + p(o.p), + values(std::move(o.values)), + values2(o.values2) { + o.p = nullptr; + }; array2D& operator=(const array2D&) = delete; array2D& operator=(array2D&& o) { x = o.x; y = o.y; p = o.p; + values = o.values; + values2 = o.values2; o.p = nullptr; return *this; } float& operator()(std::size_t i, std::size_t j) { return p[i * y + j]; } bool operator==(const array2D& o) const { return x == o.x && y == o.y && - memcmp(p, o.p, 1ull * x * y * sizeof(float)) == 0; + memcmp(p, o.p, 1ull * x * y * sizeof(float)) == 0 && + values == o.values && values2 == o.values2; } array2D() : x(0), y(0), p(nullptr) {} ~array2D() { free(p); } }; std::size_t sp_get_needed_size(const array2D& ar) { - return 2 * struct_pack::get_write_size(ar.x) + + return struct_pack::get_write_size(ar.name) + + struct_pack::get_write_size(ar.values) + + struct_pack::get_write_size(ar.values2) + + 2 * struct_pack::get_write_size(ar.x) + struct_pack::get_write_size(ar.p, 1ull * ar.x * ar.y); } template void sp_serialize_to(Writer& writer, const array2D& ar) { + struct_pack::write(writer, ar.name); + struct_pack::write(writer, ar.values); + struct_pack::write(writer, ar.values2); struct_pack::write(writer, ar.x); struct_pack::write(writer, ar.y); struct_pack::write(writer, ar.p, 1ull * ar.x * ar.y); @@ -46,6 +66,17 @@ void sp_serialize_to(Writer& writer, const array2D& ar) { template struct_pack::errc sp_deserialize_to(Reader& reader, array2D& ar) { + if (auto ec = struct_pack::read(reader, ar.name); ec != struct_pack::errc{}) { + return ec; + } + if (auto ec = struct_pack::read(reader, ar.values); + ec != struct_pack::errc{}) { + return ec; + } + if (auto ec = struct_pack::read(reader, ar.values2); + ec != struct_pack::errc{}) { + return ec; + } if (auto ec = struct_pack::read(reader, ar.x); ec != struct_pack::errc{}) { return ec; } @@ -69,6 +100,17 @@ struct_pack::errc sp_deserialize_to(Reader& reader, array2D& ar) { template struct_pack::errc sp_deserialize_to_with_skip(Reader& reader, array2D& ar) { + if (auto ec = struct_pack::read(reader, ar.name); ec != struct_pack::errc{}) { + return ec; + } + if (auto ec = struct_pack::read(reader, ar.values); + ec != struct_pack::errc{}) { + return ec; + } + if (auto ec = struct_pack::read(reader, ar.values2); + ec != struct_pack::errc{}) { + return ec; + } if (auto ec = struct_pack::read(reader, ar.x); ec != struct_pack::errc{}) { return ec; } @@ -92,7 +134,7 @@ TEST_CASE("test user-defined_type") { auto result = struct_pack::deserialize(buffer); CHECK(result.has_value()); auto& ar2 = result.value(); - CHECK(ar == result.value()); + CHECK(ar == ar2); } TEST_CASE("test user-defined_type nested") { @@ -104,7 +146,8 @@ TEST_CASE("test user-defined_type nested") { auto buffer = struct_pack::serialize(ar); auto result = struct_pack::deserialize(buffer); CHECK(result.has_value()); - CHECK(ar == result); + auto& ar2 = result.value(); + CHECK(ar == ar2); } TEST_CASE("test user-defined_type get_field") {