Skip to content

Commit

Permalink
Fix codegen for unused unions (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnstairs authored Oct 25, 2023
1 parent ab66994 commit f134576
Show file tree
Hide file tree
Showing 15 changed files with 795 additions and 155 deletions.
71 changes: 71 additions & 0 deletions cpp/test/generated/binary/protocols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,17 @@ struct IsTriviallySerializable<test_model::RecordWithComputedFields> {
offsetof(__T__, array_field) < offsetof(__T__, array_field_map_dimensions) && offsetof(__T__, array_field_map_dimensions) < offsetof(__T__, dynamic_array_field) && offsetof(__T__, dynamic_array_field) < offsetof(__T__, fixed_array_field) && offsetof(__T__, fixed_array_field) < offsetof(__T__, int_field) && offsetof(__T__, int_field) < offsetof(__T__, string_field) && offsetof(__T__, string_field) < offsetof(__T__, tuple_field) && offsetof(__T__, tuple_field) < offsetof(__T__, vector_field) && offsetof(__T__, vector_field) < offsetof(__T__, vector_of_vectors_field) && offsetof(__T__, vector_of_vectors_field) < offsetof(__T__, fixed_vector_field) && offsetof(__T__, fixed_vector_field) < offsetof(__T__, optional_named_array) && offsetof(__T__, optional_named_array) < offsetof(__T__, int_float_union) && offsetof(__T__, int_float_union) < offsetof(__T__, nullable_int_float_union) && offsetof(__T__, nullable_int_float_union) < offsetof(__T__, union_with_nested_generic_union) && offsetof(__T__, union_with_nested_generic_union) < offsetof(__T__, map_field);
};

template <>
struct IsTriviallySerializable<test_model::RecordNotUsedInProtocol> {
using __T__ = test_model::RecordNotUsedInProtocol;
static constexpr bool value =
std::is_standard_layout_v<__T__> &&
IsTriviallySerializable<decltype(__T__::u1)>::value &&
IsTriviallySerializable<decltype(__T__::u2)>::value &&
(sizeof(__T__) == (sizeof(__T__::u1) + sizeof(__T__::u2))) &&
offsetof(__T__, u1) < offsetof(__T__, u2);
};

template <>
struct IsTriviallySerializable<test_model::RecordWithKeywordFields> {
using __T__ = test_model::RecordWithKeywordFields;
Expand Down Expand Up @@ -1539,6 +1550,66 @@ template<typename T0, yardl::binary::Reader<T0> ReadT0, typename T1, yardl::bina
yardl::binary::ReadMap<std::string, std::string, yardl::binary::ReadString, yardl::binary::ReadString>(stream, value.map_field);
}

template<typename T, yardl::binary::Writer<T> WriteT, typename U, yardl::binary::Writer<U> WriteU, typename V, yardl::binary::Writer<V> WriteV>
[[maybe_unused]] void WriteGenericUnion3(yardl::binary::CodedOutputStream& stream, test_model::GenericUnion3<T, U, V> const& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::GenericUnion3<T, U, V>>::value) {
yardl::binary::WriteTriviallySerializable(stream, value);
return;
}

WriteUnion<T, WriteT, U, WriteU, V, WriteV>(stream, value);
}

template<typename T, yardl::binary::Reader<T> ReadT, typename U, yardl::binary::Reader<U> ReadU, typename V, yardl::binary::Reader<V> ReadV>
[[maybe_unused]] void ReadGenericUnion3(yardl::binary::CodedInputStream& stream, test_model::GenericUnion3<T, U, V>& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::GenericUnion3<T, U, V>>::value) {
yardl::binary::ReadTriviallySerializable(stream, value);
return;
}

ReadUnion<T, ReadT, U, ReadU, V, ReadV>(stream, value);
}

template<typename U, yardl::binary::Writer<U> WriteU, typename V, yardl::binary::Writer<V> WriteV, typename W, yardl::binary::Writer<W> WriteW>
[[maybe_unused]] void WriteGenericUnion3Alternate(yardl::binary::CodedOutputStream& stream, test_model::GenericUnion3Alternate<U, V, W> const& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::GenericUnion3Alternate<U, V, W>>::value) {
yardl::binary::WriteTriviallySerializable(stream, value);
return;
}

WriteUnion<U, WriteU, V, WriteV, W, WriteW>(stream, value);
}

template<typename U, yardl::binary::Reader<U> ReadU, typename V, yardl::binary::Reader<V> ReadV, typename W, yardl::binary::Reader<W> ReadW>
[[maybe_unused]] void ReadGenericUnion3Alternate(yardl::binary::CodedInputStream& stream, test_model::GenericUnion3Alternate<U, V, W>& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::GenericUnion3Alternate<U, V, W>>::value) {
yardl::binary::ReadTriviallySerializable(stream, value);
return;
}

ReadUnion<U, ReadU, V, ReadV, W, ReadW>(stream, value);
}

[[maybe_unused]] void WriteRecordNotUsedInProtocol(yardl::binary::CodedOutputStream& stream, test_model::RecordNotUsedInProtocol const& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::RecordNotUsedInProtocol>::value) {
yardl::binary::WriteTriviallySerializable(stream, value);
return;
}

test_model::binary::WriteGenericUnion3<int32_t, yardl::binary::WriteInteger, float, yardl::binary::WriteFloatingPoint, std::string, yardl::binary::WriteString>(stream, value.u1);
test_model::binary::WriteGenericUnion3Alternate<int32_t, yardl::binary::WriteInteger, float, yardl::binary::WriteFloatingPoint, std::string, yardl::binary::WriteString>(stream, value.u2);
}

[[maybe_unused]] void ReadRecordNotUsedInProtocol(yardl::binary::CodedInputStream& stream, test_model::RecordNotUsedInProtocol& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::RecordNotUsedInProtocol>::value) {
yardl::binary::ReadTriviallySerializable(stream, value);
return;
}

test_model::binary::ReadGenericUnion3<int32_t, yardl::binary::ReadInteger, float, yardl::binary::ReadFloatingPoint, std::string, yardl::binary::ReadString>(stream, value.u1);
test_model::binary::ReadGenericUnion3Alternate<int32_t, yardl::binary::ReadInteger, float, yardl::binary::ReadFloatingPoint, std::string, yardl::binary::ReadString>(stream, value.u2);
}

[[maybe_unused]] void WriteArrayWithKeywordDimensionNames(yardl::binary::CodedOutputStream& stream, test_model::ArrayWithKeywordDimensionNames const& value) {
if constexpr (yardl::binary::IsTriviallySerializable<test_model::ArrayWithKeywordDimensionNames>::value) {
yardl::binary::WriteTriviallySerializable(stream, value);
Expand Down
139 changes: 139 additions & 0 deletions cpp/test/generated/hdf5/protocols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,121 @@ H5::CompType InnerUnion2Ddl(bool nullable, H5::DataType const& t0, std::string c
rtn.insertMember(tag1, HOFFSET(UnionType, value1_), t1);
return rtn;
}

template <typename TInner0, typename TOuter0, typename TInner1, typename TOuter1, typename TInner2, typename TOuter2>
class InnerUnion3 {
public:
InnerUnion3() : type_index_(-1) {}
InnerUnion3(std::variant<TOuter0, TOuter1, TOuter2> const& v) : type_index_(static_cast<int8_t>(v.index())) {
Init(v);
}

InnerUnion3(std::variant<std::monostate, TOuter0, TOuter1, TOuter2> const& v) : type_index_(static_cast<int8_t>(v.index()) - 1) {
Init(v);
}

InnerUnion3(InnerUnion3 const& v) = delete;

InnerUnion3 operator=(InnerUnion3 const&) = delete;

~InnerUnion3() {
switch (type_index_) {
case 0:
value0_.~TInner0();
break;
case 1:
value1_.~TInner1();
break;
case 2:
value2_.~TInner2();
break;
}
}

void ToOuter(std::variant<TOuter0, TOuter1, TOuter2>& o) const {
ToOuterImpl(o);
}

void ToOuter(std::variant<std::monostate, TOuter0, TOuter1, TOuter2>& o) const {
ToOuterImpl(o);
}

int8_t type_index_;
union {
char empty0_[sizeof(TInner0)]{};
TInner0 value0_;
};
union {
char empty1_[sizeof(TInner1)]{};
TInner1 value1_;
};
union {
char empty2_[sizeof(TInner2)]{};
TInner2 value2_;
};

private:
template <typename T>
void Init(T const& v) {
constexpr size_t offset = GetOuterVariantOffset<std::remove_const_t<std::remove_reference_t<decltype(v)>>>();
switch (type_index_) {
case 0:
new (&value0_) TInner0(std::get<0 + offset>(v));
return;
case 1:
new (&value1_) TInner1(std::get<1 + offset>(v));
return;
case 2:
new (&value2_) TInner2(std::get<2 + offset>(v));
return;
}
}

template <typename TVariant>
void ToOuterImpl(TVariant& o) const {
constexpr size_t offset = GetOuterVariantOffset<TVariant>();
switch (type_index_) {
case -1:
if constexpr (offset == 1) {
o.template emplace<0>(std::monostate{});
return;
}
case 0:
o.template emplace<0 + offset>();
yardl::hdf5::ToOuter(value0_, std::get<0 + offset>(o));
return;
case 1:
o.template emplace<1 + offset>();
yardl::hdf5::ToOuter(value1_, std::get<1 + offset>(o));
return;
case 2:
o.template emplace<2 + offset>();
yardl::hdf5::ToOuter(value2_, std::get<2 + offset>(o));
return;
}
throw std::runtime_error("unrecognized type variant type index " + std::to_string(type_index_));
}

template <typename TVariant>
static constexpr size_t GetOuterVariantOffset() {
constexpr bool has_monostate = std::is_same_v<std::monostate, std::variant_alternative_t<0, TVariant>>;
if constexpr (has_monostate) {
return 1;
}
return 0;
}
};

template <typename TInner0, typename TOuter0, typename TInner1, typename TOuter1, typename TInner2, typename TOuter2>
H5::CompType InnerUnion3Ddl(bool nullable, H5::DataType const& t0, std::string const& tag0, H5::DataType const& t1, std::string const& tag1, H5::DataType const& t2, std::string const& tag2) {
using UnionType = ::InnerUnion3<TInner0, TOuter0, TInner1, TOuter1, TInner2, TOuter2>;
H5::CompType rtn(sizeof(UnionType));
rtn.insertMember("$type", HOFFSET(UnionType, type_index_), yardl::hdf5::UnionTypeEnumDdl(nullable, tag0, tag1, tag2));
rtn.insertMember(tag0, HOFFSET(UnionType, value0_), t0);
rtn.insertMember(tag1, HOFFSET(UnionType, value1_), t1);
rtn.insertMember(tag2, HOFFSET(UnionType, value2_), t2);
return rtn;
}
}

namespace test_model::hdf5 {
Expand Down Expand Up @@ -624,6 +739,22 @@ struct _Inner_RecordWithComputedFields {
yardl::hdf5::InnerMap<yardl::hdf5::InnerVlenString, std::string, yardl::hdf5::InnerVlenString, std::string> map_field;
};

struct _Inner_RecordNotUsedInProtocol {
_Inner_RecordNotUsedInProtocol() {}
_Inner_RecordNotUsedInProtocol(test_model::RecordNotUsedInProtocol const& o)
: u1(o.u1),
u2(o.u2) {
}

void ToOuter (test_model::RecordNotUsedInProtocol& o) const {
yardl::hdf5::ToOuter(u1, o.u1);
yardl::hdf5::ToOuter(u2, o.u2);
}

::InnerUnion3<int32_t, int32_t, float, float, yardl::hdf5::InnerVlenString, std::string> u1;
::InnerUnion3<int32_t, int32_t, float, float, yardl::hdf5::InnerVlenString, std::string> u2;
};

struct _Inner_RecordWithKeywordFields {
_Inner_RecordWithKeywordFields() {}
_Inner_RecordWithKeywordFields(test_model::RecordWithKeywordFields const& o)
Expand Down Expand Up @@ -941,6 +1072,14 @@ template <typename _T0_Inner, typename T0, typename _T1_Inner, typename T1>
return t;
}

[[maybe_unused]] H5::CompType GetRecordNotUsedInProtocolHdf5Ddl() {
using RecordType = test_model::hdf5::_Inner_RecordNotUsedInProtocol;
H5::CompType t(sizeof(RecordType));
t.insertMember("u1", HOFFSET(RecordType, u1), ::InnerUnion3Ddl<int32_t, int32_t, float, float, yardl::hdf5::InnerVlenString, std::string>(false, H5::PredType::NATIVE_INT32, "T", H5::PredType::NATIVE_FLOAT, "U", yardl::hdf5::InnerVlenStringDdl(), "V"));
t.insertMember("u2", HOFFSET(RecordType, u2), ::InnerUnion3Ddl<int32_t, int32_t, float, float, yardl::hdf5::InnerVlenString, std::string>(false, H5::PredType::NATIVE_INT32, "U", H5::PredType::NATIVE_FLOAT, "V", yardl::hdf5::InnerVlenStringDdl(), "W"));
return t;
}

[[maybe_unused]] H5::CompType GetRecordWithKeywordFieldsHdf5Ddl() {
using RecordType = test_model::hdf5::_Inner_RecordWithKeywordFields;
H5::CompType t(sizeof(RecordType));
Expand Down
77 changes: 77 additions & 0 deletions cpp/test/generated/model.json
Original file line number Diff line number Diff line change
Expand Up @@ -2469,6 +2469,83 @@
]
}
},
{
"alias": {
"name": "GenericUnion3",
"typeParameters": [
"T",
"U",
"V"
],
"type": [
{
"tag": "T",
"type": "T"
},
{
"tag": "U",
"type": "U"
},
{
"tag": "V",
"type": "V"
}
]
}
},
{
"alias": {
"name": "GenericUnion3Alternate",
"typeParameters": [
"U",
"V",
"W"
],
"type": [
{
"tag": "U",
"type": "U"
},
{
"tag": "V",
"type": "V"
},
{
"tag": "W",
"type": "W"
}
]
}
},
{
"record": {
"name": "RecordNotUsedInProtocol",
"fields": [
{
"name": "u1",
"type": {
"name": "TestModel.GenericUnion3",
"typeArguments": [
"int32",
"float32",
"string"
]
}
},
{
"name": "u2",
"type": {
"name": "TestModel.GenericUnion3Alternate",
"typeArguments": [
"int32",
"float32",
"string"
]
}
}
]
}
},
{
"alias": {
"name": "ArrayWithKeywordDimensionNames",
Expand Down
Loading

0 comments on commit f134576

Please sign in to comment.