Skip to content

Commit

Permalink
Array concept was not generalized enough to avoid treating as aggrega…
Browse files Browse the repository at this point in the history
…te in endian aware case and not working well with self referencing concept.
  • Loading branch information
eyalz800 committed May 8, 2023
1 parent d01dc49 commit b5ff1d4
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 20 deletions.
39 changes: 36 additions & 3 deletions test/src/test_stdarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ TEST(stdarray, string)
TEST(stdarray, large_array)
{
auto [data, in, out] = zpp::bits::data_in_out();
std::array<int, 0x1000> a1 = {1,2,3,4};
std::array<int, 1000> a1 = {1,2,3,4};
out(a1).or_throw();

std::array<int, 0x1000> a2{};
std::array<int, 1000> a2{};
in(a2).or_throw();

for (std::size_t i = 0; i < std::extent_v<decltype(a1)>; ++i) {
Expand All @@ -64,7 +64,7 @@ TEST(stdarray, large_array_in_struct)
auto [data, in, out] = zpp::bits::data_in_out();
struct a
{
std::array<int, 0x1000> a1 = {1,2,3,4};
std::array<int, 1000> a1 = {1,2,3,4};
};

a a1 = {1,2,3,4};
Expand All @@ -78,4 +78,37 @@ TEST(stdarray, large_array_in_struct)
}
}

TEST(stdarray, large_array_endian)
{
auto [data, in, out] =
zpp::bits::data_in_out(zpp::bits::endian::swapped{});
std::array<int, 1000> a1 = {1, 2, 3, 4};
out(a1).or_throw();

std::array<int, 1000> a2{};
in(a2).or_throw();

for (std::size_t i = 0; i < std::extent_v<decltype(a1)>; ++i) {
EXPECT_EQ(a1[i], a2[i]);
}
}

TEST(stdarray, large_array_in_struct_endian)
{
auto [data, in, out] =
zpp::bits::data_in_out(zpp::bits::endian::swapped{});
struct a
{
std::array<int, 1000> a1 = {1,2,3,4};
};

a a1 = {1,2,3,4};
out(a1).or_throw();

a a2;
in(a2).or_throw();

for (std::size_t i = 0; i < std::extent_v<decltype(a::a1)>; ++i) {
EXPECT_EQ(a1.a1[i], a2.a1[i]);
}
}
38 changes: 21 additions & 17 deletions zpp_bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ template <typename Type>
concept by_protocol = has_protocol<Type> && !has_explicit_serialize<Type>;

template <typename Type>
concept array = std::is_array_v<std::remove_cvref_t<Type>>;
concept basic_array = std::is_array_v<std::remove_cvref_t<Type>>;

template <typename Type>
concept unspecialized =
Expand Down Expand Up @@ -891,6 +891,16 @@ concept has_fixed_nonzero_size = requires
std::remove_cvref_t<Type>{}.size()>::value != 0;
};

template <typename Type>
concept array =
basic_array<Type> ||
(container<Type> && has_fixed_nonzero_size<Type> && requires {
requires Type {
}
.size() * sizeof(typename Type::value_type) == sizeof(Type);
Type{}.data();
});

} // namespace concepts

template <typename CharType, std::size_t Size>
Expand Down Expand Up @@ -1258,14 +1268,9 @@ constexpr auto access::byte_serializable()
0)>::value == 0;
}) {
return false;
} else if constexpr (concepts::container<type> &&
concepts::has_fixed_nonzero_size<type> &&
requires {
type{}.size() * sizeof(typename type::value_type) ==
sizeof(type);
type{}.data();
}) {
return byte_serializable<typename type::value_type>();
} else if constexpr (concepts::array<type>) {
return byte_serializable<
std::remove_cvref_t<decltype(std::declval<type>()[0])>>();
} else if constexpr (members_count > 0) {
return visit_members_types<type>(
byte_serializable_visitor<type>{})();
Expand Down Expand Up @@ -1325,15 +1330,9 @@ constexpr auto access::endian_independent_byte_serializable()
0)>::value == 0;
}) {
return false;
} else if constexpr (concepts::container<type> &&
concepts::has_fixed_nonzero_size<type> &&
requires {
type{}.size() * sizeof(typename type::value_type) ==
sizeof(type);
type{}.data();
}) {
} else if constexpr (concepts::array<type>) {
return endian_independent_byte_serializable<
typename type::value_type>();
std::remove_cvref_t<decltype(std::declval<type>()[0])>>();
} else if constexpr (members_count > 0) {
return visit_members_types<type>(
endian_independent_byte_serializable_visitor<type>{})();
Expand Down Expand Up @@ -1385,6 +1384,11 @@ constexpr auto access::self_referencing()
return false;
} else if constexpr (members_count == 0) {
return false;
} else if constexpr (concepts::array<type>) {
return self_referencing<
std::remove_cvref_t<decltype(std::declval<type>()[0])>,
self,
Visited...>();
} else {
return visit_members_types<type>(
self_referencing_visitor<type, self, Visited...>{})();
Expand Down

0 comments on commit b5ff1d4

Please sign in to comment.