Skip to content

Commit

Permalink
[struct_pack] remove concept of trivial_class_t/non_trivial_class_t (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
poor-circle authored Sep 19, 2023
1 parent ad3abef commit 97b98d7
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 139 deletions.
27 changes: 9 additions & 18 deletions include/ylt/struct_pack/struct_pack_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,8 @@ enum class type_id {
circle_flag = 251,
// end helper with user defined type ID
type_end_flag_with_id = 252,
trivial_class_t = 253,
// struct type
non_trivial_class_t = 254,
// class type
struct_t = 253,
// end helper
type_end_flag = 255,
};
Expand Down Expand Up @@ -579,13 +578,10 @@ constexpr type_id get_type_id() {
return type_id::expected_t;
}
else if constexpr (is_trivial_tuple<T> || pair<T>) {
return type_id::trivial_class_t;
}
else if constexpr (tuple<T>) {
return type_id::non_trivial_class_t;
return type_id::struct_t;
}
else if constexpr (std::is_class_v<T>) {
return type_id::trivial_class_t;
return type_id::struct_t;
}
else {
static_assert(!sizeof(T), "not supported type");
Expand Down Expand Up @@ -952,8 +948,7 @@ constexpr decltype(auto) get_type_literal() {
else {
constexpr auto id = get_type_id<Arg>();
constexpr auto begin = string_literal<char, 1>{{static_cast<char>(id)}};
if constexpr (id == type_id::non_trivial_class_t ||
id == type_id::trivial_class_t) {
if constexpr (id == type_id::struct_t) {
using Args = decltype(get_types<Arg>());
constexpr auto end = get_type_end_flag<Arg>();
constexpr auto body = get_type_literal<Args, Arg, ParentArgs...>(
Expand Down Expand Up @@ -1063,8 +1058,7 @@ constexpr decltype(auto) get_types_literal() {
}
else {
constexpr auto root_id = get_type_id<remove_cvref_t<T>>();
if constexpr (root_id == type_id::non_trivial_class_t ||
root_id == type_id::trivial_class_t) {
if constexpr (root_id == type_id::struct_t) {
constexpr auto end = get_type_end_flag<remove_cvref_t<T>>();
constexpr auto begin =
string_literal<char, 1>{{static_cast<char>(root_id)}};
Expand Down Expand Up @@ -1133,8 +1127,7 @@ constexpr bool check_if_compatible_element_exist_impl_helper() {
return true;
}
else {
if constexpr (id == type_id::non_trivial_class_t ||
id == type_id::trivial_class_t) {
if constexpr (id == type_id::struct_t) {
using subArgs = decltype(get_types<T>());
return check_if_compatible_element_exist_impl<version, subArgs, T,
ParentArgs...>(
Expand Down Expand Up @@ -1367,8 +1360,7 @@ constexpr std::size_t calculate_compatible_version_size() {
sz = 1;
}
else {
if constexpr (id == type_id::non_trivial_class_t ||
id == type_id::trivial_class_t) {
if constexpr (id == type_id::struct_t) {
using subArgs = decltype(get_types<T>());
return calculate_compatible_version_size<subArgs, T, ParentArgs...>(
std::make_index_sequence<std::tuple_size_v<subArgs>>());
Expand Down Expand Up @@ -1452,8 +1444,7 @@ constexpr void get_compatible_version_numbers(Buffer &buffer, std::size_t &sz) {
return;
}
else {
if constexpr (id == type_id::non_trivial_class_t ||
id == type_id::trivial_class_t) {
if constexpr (id == type_id::struct_t) {
using subArgs = decltype(get_types<T>());
get_compatible_version_numbers<Buffer, subArgs, T, ParentArgs...>(
buffer, sz, std::make_index_sequence<std::tuple_size_v<subArgs>>());
Expand Down
23 changes: 15 additions & 8 deletions src/struct_pack/tests/test_compile_time_calculate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,18 +285,25 @@ TEST_CASE("type calculate") {
serialize(tuplet::tuple<int, std::string>{})));
}
{
static_assert(get_type_code<std::tuple<int, std::string>>() !=
static_assert(get_type_code<std::tuple<int, float>>() !=
get_type_code<std::pair<int, float>>(),
"tuple is not trival copyable, we got different layout");
CHECK(!deserialize<std::pair<int, float>>(
serialize(std::tuple<int, float>{})));
}
{
static_assert(get_type_code<std::tuple<int, std::string>>() ==
get_type_code<person>(),
"different class accord and trival_class"
"concept should get different MD5");
CHECK(!deserialize<std::tuple<int, std::string>>(serialize(person{})));
"same type should "
"get same MD5");
CHECK(deserialize<std::tuple<int, std::string>>(serialize(person{})));
}
{
static_assert(get_type_code<std::pair<int, std::string>>() !=
static_assert(get_type_code<std::pair<int, std::string>>() ==
get_type_code<std::tuple<int, std::string>>(),
"different class accord and trival_class concept should "
"get different MD5");
CHECK(!deserialize<std::pair<int, std::string>>(
"same type should "
"get same MD5");
CHECK(deserialize<std::pair<int, std::string>>(
serialize(std::tuple<int, std::string>{})));
}
{
Expand Down
34 changes: 17 additions & 17 deletions src/struct_pack/tests/test_data_struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,11 +516,11 @@ TEST_CASE("test unique_ptr") {
auto literal = struct_pack::get_type_literal<my_list>();
std::string_view sv{literal.data(), literal.size()};
using struct_pack::detail::type_id;
CHECK(sv ==
std::string{(char)type_id::trivial_class_t, (char)type_id::optional_t,
(char)type_id::circle_flag, (char)129,
(char)type_id::string_t, (char)type_id::char_8_t,
(char)type_id::int32_t, (char)type_id::type_end_flag});
CHECK(sv == std::string{(char)type_id::struct_t, (char)type_id::optional_t,
(char)type_id::circle_flag, (char)129,
(char)type_id::string_t, (char)type_id::char_8_t,
(char)type_id::int32_t,
(char)type_id::type_end_flag});
CHECK(result == list_head);
}
SUBCASE("test list(unique_ptr)") {
Expand All @@ -542,11 +542,11 @@ TEST_CASE("test unique_ptr") {
auto literal = struct_pack::get_type_literal<std::unique_ptr<my_list>>();
std::string_view sv{literal.data(), literal.size()};
using struct_pack::detail::type_id;
CHECK(sv ==
std::string{(char)type_id::optional_t, (char)type_id::trivial_class_t,
(char)type_id::circle_flag, (char)129,
(char)type_id::string_t, (char)type_id::char_8_t,
(char)type_id::int32_t, (char)type_id::type_end_flag});
CHECK(sv == std::string{(char)type_id::optional_t, (char)type_id::struct_t,
(char)type_id::circle_flag, (char)129,
(char)type_id::string_t, (char)type_id::char_8_t,
(char)type_id::int32_t,
(char)type_id::type_end_flag});
CHECK(*result.value() == *result.value());
}
SUBCASE("test list2") {
Expand All @@ -568,20 +568,20 @@ TEST_CASE("test unique_ptr") {
auto literal = struct_pack::get_type_literal<std::unique_ptr<my_list2>>();
std::string_view sv{literal.data(), literal.size()};
using struct_pack::detail::type_id;
CHECK(sv == std::string{
(char)type_id::optional_t, (char)type_id::trivial_class_t,
(char)type_id::trivial_class_t, (char)type_id::circle_flag,
(char)130, (char)type_id::string_t, (char)type_id::char_8_t,
(char)type_id::int32_t, (char)type_id::type_end_flag,
(char)type_id::type_end_flag});
CHECK(sv == std::string{(char)type_id::optional_t, (char)type_id::struct_t,
(char)type_id::struct_t, (char)type_id::circle_flag,
(char)130, (char)type_id::string_t,
(char)type_id::char_8_t, (char)type_id::int32_t,
(char)type_id::type_end_flag,
(char)type_id::type_end_flag});
CHECK(*result.value() == *result.value());
}
SUBCASE("test tree") {
auto literal = struct_pack::get_type_literal<my_tree>();
auto sv = std::string_view{literal.data(), literal.size()};
using struct_pack::detail::type_id;
CHECK(sv == std::string{
(char)type_id::trivial_class_t, (char)type_id::optional_t,
(char)type_id::struct_t, (char)type_id::optional_t,
(char)type_id::circle_flag, (char)129,
(char)type_id::optional_t, (char)type_id::circle_flag,
(char)129, (char)type_id::string_t, (char)type_id::char_8_t,
Expand Down
25 changes: 20 additions & 5 deletions src/struct_pack/tests/test_serialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,23 @@ TEST_CASE("testing exceptions") {
CHECK(ret3.error() == struct_pack::errc::no_buffer_space);
}
}

TEST_CASE("testing serialize/deserialize varadic params") {
using namespace std::string_literals;
TEST_CASE("testing serialize/deserialize variadic params") {
{
person p{24, "Betty"};
auto buffer = struct_pack::serialize(p);
auto res = struct_pack::deserialize<int, std::string>(buffer);
CHECK(res);
CHECK(std::get<0>(res.value()) == 24);
CHECK(std::get<1>(res.value()) == "Betty");
}
{
person p{24, "Betty"};
auto buffer = struct_pack::serialize(24, "Betty"s);
auto res = struct_pack::deserialize<person>(buffer);
CHECK(res);
CHECK(res.value() == p);
}
{
auto ret = struct_pack::serialize(1, 2, 3, 4, 5);
auto res = struct_pack::deserialize<std::tuple<int, int, int, int, int>>(
Expand Down Expand Up @@ -570,18 +585,18 @@ TEST_CASE("test get type code") {
auto str = get_type_literal<int, int, short>();
static_assert(str.size() == 5);
string_literal<char, 5> val{
{(char)-2, 1, 1, 7, (char)-1}}; //{'1','1','7'};
{(char)-3, 1, 1, 7, (char)-1}}; //{'1','1','7'};
CHECK(str == val);

auto str1 = get_type_literal<int64_t, uint64_t>();
static_assert(str1.size() == 4);
string_literal<char, 4> val1{{(char)-2, 3, 4, (char)-1}}; //{'3','4'};
string_literal<char, 4> val1{{(char)-3, 3, 4, (char)-1}}; //{'3','4'};
CHECK(str1 == val1);

auto str2 =
get_type_literal<int64_t, uint64_t, struct_pack::compatible<int32_t>>();
static_assert(str2.size() == 4);
string_literal<char, 4> val2{{(char)-2, 3, 4, (char)-1}};
string_literal<char, 4> val2{{(char)-3, 3, 4, (char)-1}};
CHECK(str2 == val2);
}
}
Expand Down
46 changes: 5 additions & 41 deletions website/docs/en/struct_pack/struct_pack_type_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,48 +216,10 @@ The class needs to provide: `size()`,`flip()`,`set()`,`reset()`,`count()`,and th

## Struct

`struct_pack` supports `struct`. Up to **64** fields are supported and nested fields are supported too. All members
should be of valid `struct_pack` type. There are two kinds of `struct`:
`struct_pack` supports `struct` type. Up to **64** fields are supported and nested fields are supported too. All members
should be of valid `struct_pack` type.

### struct/class/std::pair/tuplet::tuple

For example:

```cpp
struct person {
int age;
std::string name;
};
```
and
```cpp
struct person2 {
std::string name;
int age;
};
STRUCT_PACK_REFL(person2,age,name)
```
and
```cpp
std::pair<int,std::string>
```
and
```cpp
tuplet::tuple<int,std::string>
```

Those types are same type in struct_pack.

### std::tuple

For historical reasons, `std::tuple<T...>` have a different memory layout than ordinary structs, and for optimization reasons we distinguish them from ordinary structs in the type system. For example:

For instance:

```cpp
std::tuple<int,std::string>
```
are different types with `person` in struct_pack.
struct type could be `struct/class/std::tuple/tuplet::tuple/std::pair`


### trivial struct
Expand Down Expand Up @@ -309,6 +271,8 @@ STRUCT_PACK_REFL(bar,a,b,c);
static_assert(struct_pack::get_type_code<foo>()!=struct_pack::get_type_code<bar>());
```

the `std::tuple` is not trivial struct too.

## Compatible Type

This refers to `struct_pack::compatible<T, version_number>`. This is a special data type kind of identical to `std::optional` in cpp. In `struct_pack` it is dedicated for the forward/backward compatibility purpose.
Expand Down
53 changes: 3 additions & 50 deletions website/docs/zh/struct_pack/struct_pack_type_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,59 +221,11 @@ concept unique_ptr = requires(Type ptr) {

struct_pack支持结构体类型。结构体内可以包含最多64个字段,并允许结构体嵌套。结构体中的任何成员都必须是struct_pack的合法类型。

struct_pack将结构体分为两种:

### struct/class/std::pair/tuplet::tuple

例如:

```cpp
struct person {
int age;
std::string name;
};
```
```cpp
struct person2 {
std::string name;
int age;
};
STRUCT_PACK_REFL(person2,age,name)
```
```cpp
std::pair<int,std::string>
```
以及
```cpp
tuplet::tuple<int,std::string>
```
在 struct_pack中被视作相同的类型。

### std::tuple

由于历史原因,其内存布局和普通的struct不同,因此我们在类型系统中将其视作不同的类型。

例如:

```cpp
struct person {
int age;
std::string name;
};
```
```cpp
std::tuple<int,std::string>
```

这两者是不同的类型。
struct_pack的结构体类型可以为:struct/class/std::pair/tuplet::tuple/std::tuple

### 平凡结构体

假如一个类型是`struct/class/std::pair/tuplet::tuple`,且其所有的成员字段都是平凡字段,并且该类型未使用`STRUCT_PACK_REFL`宏注册,则该类型被视为平凡结构体类型
假如一个结构体类型是`struct/class/std::pair/tuplet::tuple`,且其所有的成员字段都是平凡字段,并且该类型未使用`STRUCT_PACK_REFL`宏注册,则该结构体被视为平凡结构体类型

平凡字段是下面几种类型中的一种:
1. 基本类型
Expand Down Expand Up @@ -320,6 +272,7 @@ STRUCT_PACK_REFL(bar,a,b,c);
static_assert(struct_pack::get_type_code<foo>()!=struct_pack::get_type_code<bar>());
```

此外,std::tuple也一定不是平凡结构体。

## 兼容类型

Expand Down

0 comments on commit 97b98d7

Please sign in to comment.