diff --git a/cpp/test/generated/binary/protocols.cc b/cpp/test/generated/binary/protocols.cc index 07133bad..5fc3efc9 100644 --- a/cpp/test/generated/binary/protocols.cc +++ b/cpp/test/generated/binary/protocols.cc @@ -375,8 +375,9 @@ struct IsTriviallySerializable { std::is_standard_layout_v<__T__> && IsTriviallySerializable::value && IsTriviallySerializable::value && - (sizeof(__T__) == (sizeof(__T__::set_1) + sizeof(__T__::set_2))) && - offsetof(__T__, set_1) < offsetof(__T__, set_2); + IsTriviallySerializable::value && + (sizeof(__T__) == (sizeof(__T__::set_1) + sizeof(__T__::set_2) + sizeof(__T__::set_3))) && + offsetof(__T__, set_1) < offsetof(__T__, set_2) && offsetof(__T__, set_2) < offsetof(__T__, set_3); }; template <> @@ -1775,6 +1776,7 @@ namespace { yardl::binary::WriteMap(stream, value.set_1); yardl::binary::WriteMap(stream, value.set_2); + yardl::binary::WriteMap, yardl::binary::WriteString, WriteUnion>(stream, value.set_3); } [[maybe_unused]] void ReadRecordWithMaps(yardl::binary::CodedInputStream& stream, test_model::RecordWithMaps& value) { @@ -1785,6 +1787,7 @@ namespace { yardl::binary::ReadMap(stream, value.set_1); yardl::binary::ReadMap(stream, value.set_2); + yardl::binary::ReadMap, yardl::binary::ReadString, ReadUnion>(stream, value.set_3); } [[maybe_unused]] void WriteFruits(yardl::binary::CodedOutputStream& stream, test_model::Fruits const& value) { @@ -3989,6 +3992,10 @@ void UnionsWriter::WriteMonosotateOrIntOrSimpleRecordImpl(std::variant(stream_, value); } +void UnionsWriter::WriteVectorOfUnionsImpl(std::vector> const& value) { + yardl::binary::WriteVector, WriteUnion>(stream_, value); +} + void UnionsWriter::WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) { basic_types::binary::WriteRecordWithUnions(stream_, value); } @@ -4013,6 +4020,10 @@ void UnionsReader::ReadMonosotateOrIntOrSimpleRecordImpl(std::variant(stream_, value); } +void UnionsReader::ReadVectorOfUnionsImpl(std::vector>& value) { + yardl::binary::ReadVector, ReadUnion>(stream_, value); +} + void UnionsReader::ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) { basic_types::binary::ReadRecordWithUnions(stream_, value); } diff --git a/cpp/test/generated/binary/protocols.h b/cpp/test/generated/binary/protocols.h index 03d51c5a..bac9ff8b 100644 --- a/cpp/test/generated/binary/protocols.h +++ b/cpp/test/generated/binary/protocols.h @@ -1001,6 +1001,7 @@ class UnionsWriter : public test_model::UnionsWriterBase, yardl::binary::BinaryW void WriteIntOrSimpleRecordImpl(std::variant const& value) override; void WriteIntOrRecordWithVlensImpl(std::variant const& value) override; void WriteMonosotateOrIntOrSimpleRecordImpl(std::variant const& value) override; + void WriteVectorOfUnionsImpl(std::vector> const& value) override; void WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) override; void CloseImpl() override; @@ -1022,6 +1023,7 @@ class UnionsReader : public test_model::UnionsReaderBase, yardl::binary::BinaryR void ReadIntOrSimpleRecordImpl(std::variant& value) override; void ReadIntOrRecordWithVlensImpl(std::variant& value) override; void ReadMonosotateOrIntOrSimpleRecordImpl(std::variant& value) override; + void ReadVectorOfUnionsImpl(std::vector>& value) override; void ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) override; void CloseImpl() override; diff --git a/cpp/test/generated/hdf5/protocols.cc b/cpp/test/generated/hdf5/protocols.cc index 3c747fa0..58d2006d 100644 --- a/cpp/test/generated/hdf5/protocols.cc +++ b/cpp/test/generated/hdf5/protocols.cc @@ -903,16 +903,19 @@ struct _Inner_RecordWithMaps { _Inner_RecordWithMaps() {} _Inner_RecordWithMaps(test_model::RecordWithMaps const& o) : set_1(o.set_1), - set_2(o.set_2) { + set_2(o.set_2), + set_3(o.set_3) { } void ToOuter (test_model::RecordWithMaps& o) const { yardl::hdf5::ToOuter(set_1, o.set_1); yardl::hdf5::ToOuter(set_2, o.set_2); + yardl::hdf5::ToOuter(set_3, o.set_3); } yardl::hdf5::InnerMap set_1; yardl::hdf5::InnerMap set_2; + yardl::hdf5::InnerMap, std::variant> set_3; }; template @@ -1581,6 +1584,7 @@ struct _Inner_RecordWithOptionalDate { H5::CompType t(sizeof(RecordType)); t.insertMember("set1", HOFFSET(RecordType, set_1), yardl::hdf5::InnerMapDdl(H5::PredType::NATIVE_UINT32, H5::PredType::NATIVE_UINT32)); t.insertMember("set2", HOFFSET(RecordType, set_2), yardl::hdf5::InnerMapDdl(H5::PredType::NATIVE_INT32, H5::PredType::NATIVE_HBOOL)); + t.insertMember("set3", HOFFSET(RecordType, set_3), yardl::hdf5::InnerMapDdl>(yardl::hdf5::InnerVlenStringDdl(), ::InnerUnion2Ddl(false, yardl::hdf5::InnerVlenStringDdl(), "string", H5::PredType::NATIVE_INT32, "int32"))); return t; } @@ -3040,6 +3044,10 @@ void UnionsWriter::WriteMonosotateOrIntOrSimpleRecordImpl(std::variant, std::variant>(group_, "monosotateOrIntOrSimpleRecord", ::InnerUnion2Ddl(true, H5::PredType::NATIVE_INT32, "int32", test_model::hdf5::GetSimpleRecordHdf5Ddl(), "SimpleRecord"), value); } +void UnionsWriter::WriteVectorOfUnionsImpl(std::vector> const& value) { + yardl::hdf5::WriteScalarDataset, std::variant>, std::vector>>(group_, "vectorOfUnions", yardl::hdf5::InnerVlenDdl(::InnerUnion2Ddl(false, yardl::hdf5::InnerVlenStringDdl(), "string", H5::PredType::NATIVE_INT32, "int32")), value); +} + void UnionsWriter::WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) { yardl::hdf5::WriteScalarDataset(group_, "recordWithUnions", basic_types::hdf5::GetRecordWithUnionsHdf5Ddl(), value); } @@ -3060,6 +3068,10 @@ void UnionsReader::ReadMonosotateOrIntOrSimpleRecordImpl(std::variant, std::variant>(group_, "monosotateOrIntOrSimpleRecord", ::InnerUnion2Ddl(true, H5::PredType::NATIVE_INT32, "int32", test_model::hdf5::GetSimpleRecordHdf5Ddl(), "SimpleRecord"), value); } +void UnionsReader::ReadVectorOfUnionsImpl(std::vector>& value) { + yardl::hdf5::ReadScalarDataset, std::variant>, std::vector>>(group_, "vectorOfUnions", yardl::hdf5::InnerVlenDdl(::InnerUnion2Ddl(false, yardl::hdf5::InnerVlenStringDdl(), "string", H5::PredType::NATIVE_INT32, "int32")), value); +} + void UnionsReader::ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) { yardl::hdf5::ReadScalarDataset(group_, "recordWithUnions", basic_types::hdf5::GetRecordWithUnionsHdf5Ddl(), value); } diff --git a/cpp/test/generated/hdf5/protocols.h b/cpp/test/generated/hdf5/protocols.h index 2d01eeb9..58658ea9 100644 --- a/cpp/test/generated/hdf5/protocols.h +++ b/cpp/test/generated/hdf5/protocols.h @@ -773,6 +773,8 @@ class UnionsWriter : public test_model::UnionsWriterBase, public yardl::hdf5::Hd void WriteMonosotateOrIntOrSimpleRecordImpl(std::variant const& value) override; + void WriteVectorOfUnionsImpl(std::vector> const& value) override; + void WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) override; private: @@ -789,6 +791,8 @@ class UnionsReader : public test_model::UnionsReaderBase, public yardl::hdf5::Hd void ReadMonosotateOrIntOrSimpleRecordImpl(std::variant& value) override; + void ReadVectorOfUnionsImpl(std::vector>& value) override; + void ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) override; private: diff --git a/cpp/test/generated/mocks.cc b/cpp/test/generated/mocks.cc index d7a389db..4bef75d9 100644 --- a/cpp/test/generated/mocks.cc +++ b/cpp/test/generated/mocks.cc @@ -2730,6 +2730,22 @@ class MockUnionsWriter : public UnionsWriterBase { WriteMonosotateOrIntOrSimpleRecordImpl_expected_values_.push(value); } + void WriteVectorOfUnionsImpl (std::vector> const& value) override { + if (WriteVectorOfUnionsImpl_expected_values_.empty()) { + throw std::runtime_error("Unexpected call to WriteVectorOfUnionsImpl"); + } + if (WriteVectorOfUnionsImpl_expected_values_.front() != value) { + throw std::runtime_error("Unexpected argument value for call to WriteVectorOfUnionsImpl"); + } + WriteVectorOfUnionsImpl_expected_values_.pop(); + } + + std::queue>> WriteVectorOfUnionsImpl_expected_values_; + + void ExpectWriteVectorOfUnionsImpl (std::vector> const& value) { + WriteVectorOfUnionsImpl_expected_values_.push(value); + } + void WriteRecordWithUnionsImpl (basic_types::RecordWithUnions const& value) override { if (WriteRecordWithUnionsImpl_expected_values_.empty()) { throw std::runtime_error("Unexpected call to WriteRecordWithUnionsImpl"); @@ -2756,6 +2772,9 @@ class MockUnionsWriter : public UnionsWriterBase { if (!WriteMonosotateOrIntOrSimpleRecordImpl_expected_values_.empty()) { throw std::runtime_error("Expected call to WriteMonosotateOrIntOrSimpleRecordImpl was not received"); } + if (!WriteVectorOfUnionsImpl_expected_values_.empty()) { + throw std::runtime_error("Expected call to WriteVectorOfUnionsImpl was not received"); + } if (!WriteRecordWithUnionsImpl_expected_values_.empty()) { throw std::runtime_error("Expected call to WriteRecordWithUnionsImpl was not received"); } @@ -2789,6 +2808,11 @@ class TestUnionsWriterBase : public UnionsWriterBase { mock_writer_.ExpectWriteMonosotateOrIntOrSimpleRecordImpl(value); } + void WriteVectorOfUnionsImpl(std::vector> const& value) override { + writer_->WriteVectorOfUnions(value); + mock_writer_.ExpectWriteVectorOfUnionsImpl(value); + } + void WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) override { writer_->WriteRecordWithUnions(value); mock_writer_.ExpectWriteRecordWithUnionsImpl(value); diff --git a/cpp/test/generated/model.json b/cpp/test/generated/model.json index 7313faed..53365d7a 100644 --- a/cpp/test/generated/model.json +++ b/cpp/test/generated/model.json @@ -1458,6 +1458,24 @@ "values": "bool" } } + }, + { + "name": "set3", + "type": { + "map": { + "keys": "string", + "values": [ + { + "tag": "string", + "type": "string" + }, + { + "tag": "int32", + "type": "int32" + } + ] + } + } } ] } @@ -5097,6 +5115,23 @@ } ] }, + { + "name": "vectorOfUnions", + "type": { + "vector": { + "items": [ + { + "tag": "string", + "type": "string" + }, + { + "tag": "int32", + "type": "int32" + } + ] + } + } + }, { "name": "recordWithUnions", "type": "BasicTypes.RecordWithUnions" diff --git a/cpp/test/generated/ndjson/protocols.cc b/cpp/test/generated/ndjson/protocols.cc index 329aedee..d37346a5 100644 --- a/cpp/test/generated/ndjson/protocols.cc +++ b/cpp/test/generated/ndjson/protocols.cc @@ -435,6 +435,25 @@ struct adl_serializer, int32_t>> { } }; +template <> +struct adl_serializer> { + static void to_json(ordered_json& j, std::variant const& value) { + std::visit([&j](auto const& v) {j = v;}, value); + } + + static void from_json(ordered_json const& j, std::variant& value) { + if ((j.is_string())) { + value = j.get(); + return; + } + if ((j.is_number())) { + value = j.get(); + return; + } + throw std::runtime_error("Invalid union value"); + } +}; + template <> struct adl_serializer> { static void to_json(ordered_json& j, std::variant const& value) { @@ -769,25 +788,6 @@ struct adl_serializer -struct adl_serializer> { - static void to_json(ordered_json& j, std::variant const& value) { - std::visit([&j](auto const& v) {j = v;}, value); - } - - static void from_json(ordered_json const& j, std::variant& value) { - if ((j.is_string())) { - value = j.get(); - return; - } - if ((j.is_number())) { - value = j.get(); - return; - } - throw std::runtime_error("Invalid union value"); - } -}; - template <> struct adl_serializer> { static void to_json(ordered_json& j, std::variant const& value) { @@ -1983,6 +1983,9 @@ void to_json(ordered_json& j, test_model::RecordWithMaps const& value) { if (yardl::ndjson::ShouldSerializeFieldValue(value.set_2)) { j.push_back({"set2", value.set_2}); } + if (yardl::ndjson::ShouldSerializeFieldValue(value.set_3)) { + j.push_back({"set3", value.set_3}); + } } void from_json(ordered_json const& j, test_model::RecordWithMaps& value) { @@ -1992,6 +1995,9 @@ void from_json(ordered_json const& j, test_model::RecordWithMaps& value) { if (auto it = j.find("set2"); it != j.end()) { it->get_to(value.set_2); } + if (auto it = j.find("set3"); it != j.end()) { + it->get_to(value.set_3); + } } namespace { @@ -3643,6 +3649,10 @@ void UnionsWriter::WriteMonosotateOrIntOrSimpleRecordImpl(std::variant> const& value) { + ordered_json json_value = value; + yardl::ndjson::WriteProtocolValue(stream_, "vectorOfUnions", json_value);} + void UnionsWriter::WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) { ordered_json json_value = value; yardl::ndjson::WriteProtocolValue(stream_, "recordWithUnions", json_value);} @@ -3667,6 +3677,10 @@ void UnionsReader::ReadMonosotateOrIntOrSimpleRecordImpl(std::variant>& value) { + yardl::ndjson::ReadProtocolValue(stream_, line_, "vectorOfUnions", true, unused_step_, value); +} + void UnionsReader::ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) { yardl::ndjson::ReadProtocolValue(stream_, line_, "recordWithUnions", true, unused_step_, value); } diff --git a/cpp/test/generated/ndjson/protocols.h b/cpp/test/generated/ndjson/protocols.h index 962b71bb..0bc2ad4b 100644 --- a/cpp/test/generated/ndjson/protocols.h +++ b/cpp/test/generated/ndjson/protocols.h @@ -909,6 +909,7 @@ class UnionsWriter : public test_model::UnionsWriterBase, yardl::ndjson::NDJsonW void WriteIntOrSimpleRecordImpl(std::variant const& value) override; void WriteIntOrRecordWithVlensImpl(std::variant const& value) override; void WriteMonosotateOrIntOrSimpleRecordImpl(std::variant const& value) override; + void WriteVectorOfUnionsImpl(std::vector> const& value) override; void WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) override; void CloseImpl() override; }; @@ -928,6 +929,7 @@ class UnionsReader : public test_model::UnionsReaderBase, yardl::ndjson::NDJsonR void ReadIntOrSimpleRecordImpl(std::variant& value) override; void ReadIntOrRecordWithVlensImpl(std::variant& value) override; void ReadMonosotateOrIntOrSimpleRecordImpl(std::variant& value) override; + void ReadVectorOfUnionsImpl(std::vector>& value) override; void ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) override; void CloseImpl() override; }; diff --git a/cpp/test/generated/protocols.cc b/cpp/test/generated/protocols.cc index aea91948..5c7f7622 100644 --- a/cpp/test/generated/protocols.cc +++ b/cpp/test/generated/protocols.cc @@ -4030,7 +4030,7 @@ void MapsReaderBaseInvalidState(uint8_t attempted, uint8_t current) { } // namespace -std::string MapsWriterBase::schema_ = R"({"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}}]}]})"; +std::string MapsWriterBase::schema_ = R"({"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}},{"name":"set3","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}}]}]})"; std::vector MapsWriterBase::previous_schemas_ = { }; @@ -4192,15 +4192,17 @@ void UnionsWriterBaseInvalidState(uint8_t attempted, [[maybe_unused]] bool end, case 0: expected_method = "WriteIntOrSimpleRecord()"; break; case 1: expected_method = "WriteIntOrRecordWithVlens()"; break; case 2: expected_method = "WriteMonosotateOrIntOrSimpleRecord()"; break; - case 3: expected_method = "WriteRecordWithUnions()"; break; + case 3: expected_method = "WriteVectorOfUnions()"; break; + case 4: expected_method = "WriteRecordWithUnions()"; break; } std::string attempted_method; switch (attempted) { case 0: attempted_method = "WriteIntOrSimpleRecord()"; break; case 1: attempted_method = "WriteIntOrRecordWithVlens()"; break; case 2: attempted_method = "WriteMonosotateOrIntOrSimpleRecord()"; break; - case 3: attempted_method = "WriteRecordWithUnions()"; break; - case 4: attempted_method = "Close()"; break; + case 3: attempted_method = "WriteVectorOfUnions()"; break; + case 4: attempted_method = "WriteRecordWithUnions()"; break; + case 5: attempted_method = "Close()"; break; } throw std::runtime_error("Expected call to " + expected_method + " but received call to " + attempted_method + " instead."); } @@ -4211,8 +4213,9 @@ void UnionsReaderBaseInvalidState(uint8_t attempted, uint8_t current) { case 0: return "ReadIntOrSimpleRecord()"; case 1: return "ReadIntOrRecordWithVlens()"; case 2: return "ReadMonosotateOrIntOrSimpleRecord()"; - case 3: return "ReadRecordWithUnions()"; - case 4: return "Close()"; + case 3: return "ReadVectorOfUnions()"; + case 4: return "ReadRecordWithUnions()"; + case 5: return "Close()"; default: return ""; } }; @@ -4221,7 +4224,7 @@ void UnionsReaderBaseInvalidState(uint8_t attempted, uint8_t current) { } // namespace -std::string UnionsWriterBase::schema_ = R"({"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]})"; +std::string UnionsWriterBase::schema_ = R"({"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"vectorOfUnions","type":{"vector":{"items":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]})"; std::vector UnionsWriterBase::previous_schemas_ = { }; @@ -4260,20 +4263,29 @@ void UnionsWriterBase::WriteMonosotateOrIntOrSimpleRecord(std::variant> const& value) { if (unlikely(state_ != 3)) { UnionsWriterBaseInvalidState(3, false, state_); } - WriteRecordWithUnionsImpl(value); + WriteVectorOfUnionsImpl(value); state_ = 4; } -void UnionsWriterBase::Close() { +void UnionsWriterBase::WriteRecordWithUnions(basic_types::RecordWithUnions const& value) { if (unlikely(state_ != 4)) { UnionsWriterBaseInvalidState(4, false, state_); } + WriteRecordWithUnionsImpl(value); + state_ = 5; +} + +void UnionsWriterBase::Close() { + if (unlikely(state_ != 5)) { + UnionsWriterBaseInvalidState(5, false, state_); + } + CloseImpl(); } @@ -4314,20 +4326,29 @@ void UnionsReaderBase::ReadMonosotateOrIntOrSimpleRecord(std::variant>& value) { if (unlikely(state_ != 6)) { UnionsReaderBaseInvalidState(6, state_); } - ReadRecordWithUnionsImpl(value); + ReadVectorOfUnionsImpl(value); state_ = 8; } -void UnionsReaderBase::Close() { - if (!skip_completed_check_ && unlikely(state_ != 8)) { +void UnionsReaderBase::ReadRecordWithUnions(basic_types::RecordWithUnions& value) { + if (unlikely(state_ != 8)) { UnionsReaderBaseInvalidState(8, state_); } + ReadRecordWithUnionsImpl(value); + state_ = 10; +} + +void UnionsReaderBase::Close() { + if (!skip_completed_check_ && unlikely(state_ != 10)) { + UnionsReaderBaseInvalidState(10, state_); + } + CloseImpl(); } void UnionsReaderBase::CopyTo(UnionsWriterBase& writer) { @@ -4346,6 +4367,11 @@ void UnionsReaderBase::CopyTo(UnionsWriterBase& writer) { ReadMonosotateOrIntOrSimpleRecord(value); writer.WriteMonosotateOrIntOrSimpleRecord(value); } + { + std::vector> value; + ReadVectorOfUnions(value); + writer.WriteVectorOfUnions(value); + } { basic_types::RecordWithUnions value; ReadRecordWithUnions(value); diff --git a/cpp/test/generated/protocols.h b/cpp/test/generated/protocols.h index e1a6b38b..7d1bc420 100644 --- a/cpp/test/generated/protocols.h +++ b/cpp/test/generated/protocols.h @@ -1912,6 +1912,9 @@ class UnionsWriterBase { void WriteMonosotateOrIntOrSimpleRecord(std::variant const& value); // Ordinal 3. + void WriteVectorOfUnions(std::vector> const& value); + + // Ordinal 4. void WriteRecordWithUnions(basic_types::RecordWithUnions const& value); // Optionaly close this writer before destructing. Validates that all steps were completed. @@ -1926,6 +1929,7 @@ class UnionsWriterBase { virtual void WriteIntOrSimpleRecordImpl(std::variant const& value) = 0; virtual void WriteIntOrRecordWithVlensImpl(std::variant const& value) = 0; virtual void WriteMonosotateOrIntOrSimpleRecordImpl(std::variant const& value) = 0; + virtual void WriteVectorOfUnionsImpl(std::vector> const& value) = 0; virtual void WriteRecordWithUnionsImpl(basic_types::RecordWithUnions const& value) = 0; virtual void CloseImpl() {} @@ -1956,6 +1960,9 @@ class UnionsReaderBase { void ReadMonosotateOrIntOrSimpleRecord(std::variant& value); // Ordinal 3. + void ReadVectorOfUnions(std::vector>& value); + + // Ordinal 4. void ReadRecordWithUnions(basic_types::RecordWithUnions& value); // Optionaly close this writer before destructing. Validates that all steps were completely read. @@ -1969,6 +1976,7 @@ class UnionsReaderBase { virtual void ReadIntOrSimpleRecordImpl(std::variant& value) = 0; virtual void ReadIntOrRecordWithVlensImpl(std::variant& value) = 0; virtual void ReadMonosotateOrIntOrSimpleRecordImpl(std::variant& value) = 0; + virtual void ReadVectorOfUnionsImpl(std::vector>& value) = 0; virtual void ReadRecordWithUnionsImpl(basic_types::RecordWithUnions& value) = 0; virtual void CloseImpl() {} static std::string schema_; diff --git a/cpp/test/generated/types.h b/cpp/test/generated/types.h index 0675febd..97ce429b 100644 --- a/cpp/test/generated/types.h +++ b/cpp/test/generated/types.h @@ -592,10 +592,12 @@ using NamedNDArray = yardl::NDArray; struct RecordWithMaps { std::unordered_map set_1{}; std::unordered_map set_2{}; + std::unordered_map> set_3{}; bool operator==(const RecordWithMaps& other) const { return set_1 == other.set_1 && - set_2 == other.set_2; + set_2 == other.set_2 && + set_3 == other.set_3; } bool operator!=(const RecordWithMaps& other) const { diff --git a/cpp/test/roundtrip_test.cc b/cpp/test/roundtrip_test.cc index fd4253b0..ae1a4678 100644 --- a/cpp/test/roundtrip_test.cc +++ b/cpp/test/roundtrip_test.cc @@ -380,6 +380,7 @@ TEST_P(RoundTripTests, Unions_FirstOption) { tw->WriteIntOrSimpleRecord({2}); tw->WriteIntOrRecordWithVlens({2}); tw->WriteMonosotateOrIntOrSimpleRecord({}); + tw->WriteVectorOfUnions({}); tw->WriteRecordWithUnions({std::monostate{}}); tw->Close(); @@ -396,6 +397,7 @@ TEST_P(RoundTripTests, Unions_SecondOption) { 12, }); tw->WriteMonosotateOrIntOrSimpleRecord({6}); + tw->WriteVectorOfUnions({3, "hello", 4}); tw->WriteRecordWithUnions({77}); tw->Close(); diff --git a/matlab/generated/+test_model/+binary/RecordWithMapsSerializer.m b/matlab/generated/+test_model/+binary/RecordWithMapsSerializer.m index 96fe45e5..f46e3c76 100644 --- a/matlab/generated/+test_model/+binary/RecordWithMapsSerializer.m +++ b/matlab/generated/+test_model/+binary/RecordWithMapsSerializer.m @@ -5,6 +5,7 @@ function self = RecordWithMapsSerializer() field_serializers{1} = yardl.binary.MapSerializer(yardl.binary.Uint32Serializer, yardl.binary.Uint32Serializer); field_serializers{2} = yardl.binary.MapSerializer(yardl.binary.Int32Serializer, yardl.binary.BoolSerializer); + field_serializers{3} = yardl.binary.MapSerializer(yardl.binary.StringSerializer, yardl.binary.UnionSerializer('test_model.StringOrInt32', {yardl.binary.StringSerializer, yardl.binary.Int32Serializer}, {@test_model.StringOrInt32.String, @test_model.StringOrInt32.Int32})); self@yardl.binary.RecordSerializer('test_model.RecordWithMaps', field_serializers); end @@ -14,12 +15,12 @@ function write(self, outstream, value) outstream (1,1) yardl.binary.CodedOutputStream value (1,1) test_model.RecordWithMaps end - self.write_(outstream, value.set_1, value.set_2); + self.write_(outstream, value.set_1, value.set_2, value.set_3); end function value = read(self, instream) fields = self.read_(instream); - value = test_model.RecordWithMaps(set_1=fields{1}, set_2=fields{2}); + value = test_model.RecordWithMaps(set_1=fields{1}, set_2=fields{2}, set_3=fields{3}); end end end diff --git a/matlab/generated/+test_model/+binary/UnionsReader.m b/matlab/generated/+test_model/+binary/UnionsReader.m index 984a88f9..750f579a 100644 --- a/matlab/generated/+test_model/+binary/UnionsReader.m +++ b/matlab/generated/+test_model/+binary/UnionsReader.m @@ -6,6 +6,7 @@ int_or_simple_record_serializer int_or_record_with_vlens_serializer monosotate_or_int_or_simple_record_serializer + vector_of_unions_serializer record_with_unions_serializer end @@ -20,6 +21,7 @@ self.int_or_simple_record_serializer = yardl.binary.UnionSerializer('test_model.Int32OrSimpleRecord', {yardl.binary.Int32Serializer, test_model.binary.SimpleRecordSerializer()}, {@test_model.Int32OrSimpleRecord.Int32, @test_model.Int32OrSimpleRecord.SimpleRecord}); self.int_or_record_with_vlens_serializer = yardl.binary.UnionSerializer('test_model.Int32OrRecordWithVlens', {yardl.binary.Int32Serializer, test_model.binary.RecordWithVlensSerializer()}, {@test_model.Int32OrRecordWithVlens.Int32, @test_model.Int32OrRecordWithVlens.RecordWithVlens}); self.monosotate_or_int_or_simple_record_serializer = yardl.binary.UnionSerializer('test_model.Int32OrSimpleRecord', {yardl.binary.NoneSerializer, yardl.binary.Int32Serializer, test_model.binary.SimpleRecordSerializer()}, {yardl.None, @test_model.Int32OrSimpleRecord.Int32, @test_model.Int32OrSimpleRecord.SimpleRecord}); + self.vector_of_unions_serializer = yardl.binary.VectorSerializer(yardl.binary.UnionSerializer('test_model.StringOrInt32', {yardl.binary.StringSerializer, yardl.binary.Int32Serializer}, {@test_model.StringOrInt32.String, @test_model.StringOrInt32.Int32})); self.record_with_unions_serializer = basic_types.binary.RecordWithUnionsSerializer(); end end @@ -37,6 +39,10 @@ value = self.monosotate_or_int_or_simple_record_serializer.read(self.stream_); end + function value = read_vector_of_unions_(self) + value = self.vector_of_unions_serializer.read(self.stream_); + end + function value = read_record_with_unions_(self) value = self.record_with_unions_serializer.read(self.stream_); end diff --git a/matlab/generated/+test_model/+binary/UnionsWriter.m b/matlab/generated/+test_model/+binary/UnionsWriter.m index dc1addc0..f45a5db7 100644 --- a/matlab/generated/+test_model/+binary/UnionsWriter.m +++ b/matlab/generated/+test_model/+binary/UnionsWriter.m @@ -6,6 +6,7 @@ int_or_simple_record_serializer int_or_record_with_vlens_serializer monosotate_or_int_or_simple_record_serializer + vector_of_unions_serializer record_with_unions_serializer end @@ -16,6 +17,7 @@ self.int_or_simple_record_serializer = yardl.binary.UnionSerializer('test_model.Int32OrSimpleRecord', {yardl.binary.Int32Serializer, test_model.binary.SimpleRecordSerializer()}, {@test_model.Int32OrSimpleRecord.Int32, @test_model.Int32OrSimpleRecord.SimpleRecord}); self.int_or_record_with_vlens_serializer = yardl.binary.UnionSerializer('test_model.Int32OrRecordWithVlens', {yardl.binary.Int32Serializer, test_model.binary.RecordWithVlensSerializer()}, {@test_model.Int32OrRecordWithVlens.Int32, @test_model.Int32OrRecordWithVlens.RecordWithVlens}); self.monosotate_or_int_or_simple_record_serializer = yardl.binary.UnionSerializer('test_model.Int32OrSimpleRecord', {yardl.binary.NoneSerializer, yardl.binary.Int32Serializer, test_model.binary.SimpleRecordSerializer()}, {yardl.None, @test_model.Int32OrSimpleRecord.Int32, @test_model.Int32OrSimpleRecord.SimpleRecord}); + self.vector_of_unions_serializer = yardl.binary.VectorSerializer(yardl.binary.UnionSerializer('test_model.StringOrInt32', {yardl.binary.StringSerializer, yardl.binary.Int32Serializer}, {@test_model.StringOrInt32.String, @test_model.StringOrInt32.Int32})); self.record_with_unions_serializer = basic_types.binary.RecordWithUnionsSerializer(); end end @@ -33,6 +35,10 @@ function write_monosotate_or_int_or_simple_record_(self, value) self.monosotate_or_int_or_simple_record_serializer.write(self.stream_, value); end + function write_vector_of_unions_(self, value) + self.vector_of_unions_serializer.write(self.stream_, value); + end + function write_record_with_unions_(self, value) self.record_with_unions_serializer.write(self.stream_, value); end diff --git a/matlab/generated/+test_model/+testing/MockUnionsWriter.m b/matlab/generated/+test_model/+testing/MockUnionsWriter.m index 0914a301..74ee4222 100644 --- a/matlab/generated/+test_model/+testing/MockUnionsWriter.m +++ b/matlab/generated/+test_model/+testing/MockUnionsWriter.m @@ -6,6 +6,7 @@ expected_int_or_simple_record expected_int_or_record_with_vlens expected_monosotate_or_int_or_simple_record + expected_vector_of_unions expected_record_with_unions end @@ -15,6 +16,7 @@ self.expected_int_or_simple_record = yardl.None; self.expected_int_or_record_with_vlens = yardl.None; self.expected_monosotate_or_int_or_simple_record = yardl.None; + self.expected_vector_of_unions = yardl.None; self.expected_record_with_unions = yardl.None; end @@ -30,6 +32,10 @@ function expect_write_monosotate_or_int_or_simple_record_(self, value) self.expected_monosotate_or_int_or_simple_record = yardl.Optional(value); end + function expect_write_vector_of_unions_(self, value) + self.expected_vector_of_unions = yardl.Optional(value); + end + function expect_write_record_with_unions_(self, value) self.expected_record_with_unions = yardl.Optional(value); end @@ -38,6 +44,7 @@ function verify(self) self.testCase_.verifyEqual(self.expected_int_or_simple_record, yardl.None, "Expected call to write_int_or_simple_record_ was not received"); self.testCase_.verifyEqual(self.expected_int_or_record_with_vlens, yardl.None, "Expected call to write_int_or_record_with_vlens_ was not received"); self.testCase_.verifyEqual(self.expected_monosotate_or_int_or_simple_record, yardl.None, "Expected call to write_monosotate_or_int_or_simple_record_ was not received"); + self.testCase_.verifyEqual(self.expected_vector_of_unions, yardl.None, "Expected call to write_vector_of_unions_ was not received"); self.testCase_.verifyEqual(self.expected_record_with_unions, yardl.None, "Expected call to write_record_with_unions_ was not received"); end end @@ -61,6 +68,12 @@ function write_monosotate_or_int_or_simple_record_(self, value) self.expected_monosotate_or_int_or_simple_record = yardl.None; end + function write_vector_of_unions_(self, value) + self.testCase_.verifyTrue(self.expected_vector_of_unions.has_value(), "Unexpected call to write_vector_of_unions_"); + self.testCase_.verifyEqual(value, self.expected_vector_of_unions.value, "Unexpected argument value for call to write_vector_of_unions_"); + self.expected_vector_of_unions = yardl.None; + end + function write_record_with_unions_(self, value) self.testCase_.verifyTrue(self.expected_record_with_unions.has_value(), "Unexpected call to write_record_with_unions_"); self.testCase_.verifyEqual(value, self.expected_record_with_unions.value, "Unexpected argument value for call to write_record_with_unions_"); diff --git a/matlab/generated/+test_model/+testing/TestUnionsWriter.m b/matlab/generated/+test_model/+testing/TestUnionsWriter.m index e4018521..dfb0cbb7 100644 --- a/matlab/generated/+test_model/+testing/TestUnionsWriter.m +++ b/matlab/generated/+test_model/+testing/TestUnionsWriter.m @@ -45,6 +45,11 @@ function write_monosotate_or_int_or_simple_record_(self, value) self.mock_writer_.expect_write_monosotate_or_int_or_simple_record_(value); end + function write_vector_of_unions_(self, value) + self.writer_.write_vector_of_unions(value); + self.mock_writer_.expect_write_vector_of_unions_(value); + end + function write_record_with_unions_(self, value) self.writer_.write_record_with_unions(value); self.mock_writer_.expect_write_record_with_unions_(value); diff --git a/matlab/generated/+test_model/MapsWriterBase.m b/matlab/generated/+test_model/MapsWriterBase.m index da6e0678..54f4d568 100644 --- a/matlab/generated/+test_model/MapsWriterBase.m +++ b/matlab/generated/+test_model/MapsWriterBase.m @@ -72,7 +72,7 @@ function write_records(self, value) methods (Static) function res = schema() - res = string('{"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}}]}]}'); + res = string('{"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}},{"name":"set3","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}}]}]}'); end end diff --git a/matlab/generated/+test_model/RecordWithMaps.m b/matlab/generated/+test_model/RecordWithMaps.m index a75af92d..29e7d9d8 100644 --- a/matlab/generated/+test_model/RecordWithMaps.m +++ b/matlab/generated/+test_model/RecordWithMaps.m @@ -4,6 +4,7 @@ properties set_1 set_2 + set_3 end methods @@ -11,16 +12,19 @@ arguments kwargs.set_1 = yardl.Map; kwargs.set_2 = yardl.Map; + kwargs.set_3 = yardl.Map; end self.set_1 = kwargs.set_1; self.set_2 = kwargs.set_2; + self.set_3 = kwargs.set_3; end function res = eq(self, other) res = ... isa(other, "test_model.RecordWithMaps") && ... isequal({self.set_1}, {other.set_1}) && ... - isequal({self.set_2}, {other.set_2}); + isequal({self.set_2}, {other.set_2}) && ... + isequal({self.set_3}, {other.set_3}); end function res = ne(self, other) diff --git a/matlab/generated/+test_model/UnionsReaderBase.m b/matlab/generated/+test_model/UnionsReaderBase.m index 4e48229f..de8c13fb 100644 --- a/matlab/generated/+test_model/UnionsReaderBase.m +++ b/matlab/generated/+test_model/UnionsReaderBase.m @@ -17,7 +17,7 @@ function close(self) self.close_(); - if ~self.skip_completed_check_ && self.state_ ~= 4 + if ~self.skip_completed_check_ && self.state_ ~= 5 expected_method = self.state_to_method_name_(self.state_); throw(yardl.ProtocolError("Protocol reader closed before all data was consumed. Expected call to '%s'.", expected_method)); end @@ -54,19 +54,30 @@ function close(self) end % Ordinal 3 - function value = read_record_with_unions(self) + function value = read_vector_of_unions(self) if self.state_ ~= 3 self.raise_unexpected_state_(3); end - value = self.read_record_with_unions_(); + value = self.read_vector_of_unions_(); self.state_ = 4; end + % Ordinal 4 + function value = read_record_with_unions(self) + if self.state_ ~= 4 + self.raise_unexpected_state_(4); + end + + value = self.read_record_with_unions_(); + self.state_ = 5; + end + function copy_to(self, writer) writer.write_int_or_simple_record(self.read_int_or_simple_record()); writer.write_int_or_record_with_vlens(self.read_int_or_record_with_vlens()); writer.write_monosotate_or_int_or_simple_record(self.read_monosotate_or_int_or_simple_record()); + writer.write_vector_of_unions(self.read_vector_of_unions()); writer.write_record_with_unions(self.read_record_with_unions()); end end @@ -81,6 +92,7 @@ function copy_to(self, writer) read_int_or_simple_record_(self) read_int_or_record_with_vlens_(self) read_monosotate_or_int_or_simple_record_(self) + read_vector_of_unions_(self) read_record_with_unions_(self) close_(self) @@ -101,6 +113,8 @@ function raise_unexpected_state_(self, actual) elseif state == 2 name = "read_monosotate_or_int_or_simple_record"; elseif state == 3 + name = "read_vector_of_unions"; + elseif state == 4 name = "read_record_with_unions"; else name = ""; diff --git a/matlab/generated/+test_model/UnionsWriterBase.m b/matlab/generated/+test_model/UnionsWriterBase.m index 893da943..09f34a09 100644 --- a/matlab/generated/+test_model/UnionsWriterBase.m +++ b/matlab/generated/+test_model/UnionsWriterBase.m @@ -13,7 +13,7 @@ function close(self) self.close_(); - if self.state_ ~= 4 + if self.state_ ~= 5 expected_method = self.state_to_method_name_(self.state_); throw(yardl.ProtocolError("Protocol writer closed before all steps were called. Expected call to '%s'.", expected_method)); end @@ -50,19 +50,29 @@ function write_monosotate_or_int_or_simple_record(self, value) end % Ordinal 3 - function write_record_with_unions(self, value) + function write_vector_of_unions(self, value) if self.state_ ~= 3 self.raise_unexpected_state_(3); end - self.write_record_with_unions_(value); + self.write_vector_of_unions_(value); self.state_ = 4; end + + % Ordinal 4 + function write_record_with_unions(self, value) + if self.state_ ~= 4 + self.raise_unexpected_state_(4); + end + + self.write_record_with_unions_(value); + self.state_ = 5; + end end methods (Static) function res = schema() - res = string('{"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]}'); + res = string('{"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"vectorOfUnions","type":{"vector":{"items":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]}'); end end @@ -70,6 +80,7 @@ function write_record_with_unions(self, value) write_int_or_simple_record_(self, value) write_int_or_record_with_vlens_(self, value) write_monosotate_or_int_or_simple_record_(self, value) + write_vector_of_unions_(self, value) write_record_with_unions_(self, value) end_stream_(self) @@ -91,6 +102,8 @@ function raise_unexpected_state_(self, actual) elseif state == 2 name = "write_monosotate_or_int_or_simple_record"; elseif state == 3 + name = "write_vector_of_unions"; + elseif state == 4 name = "write_record_with_unions"; else name = ''; diff --git a/matlab/test/RoundTripTest.m b/matlab/test/RoundTripTest.m index d9587507..f822b20f 100644 --- a/matlab/test/RoundTripTest.m +++ b/matlab/test/RoundTripTest.m @@ -335,6 +335,7 @@ function testUnions(testCase, format) w.write_int_or_simple_record(test_model.Int32OrSimpleRecord.Int32(1)); w.write_int_or_record_with_vlens(test_model.Int32OrRecordWithVlens.Int32(2)); w.write_monosotate_or_int_or_simple_record(yardl.None); + w.write_vector_of_unions(zeros(0, "test_model.StringOrInt32")); w.write_record_with_unions(basic_types.RecordWithUnions()); w.close(); @@ -342,6 +343,11 @@ function testUnions(testCase, format) w.write_int_or_simple_record(test_model.Int32OrSimpleRecord.SimpleRecord(test_model.SimpleRecord(x=1, y=2, z=3))); w.write_int_or_record_with_vlens(test_model.Int32OrRecordWithVlens.RecordWithVlens(test_model.RecordWithVlens(a=[test_model.SimpleRecord(x=1, y=2, z=3)], b=12, c=13))); w.write_monosotate_or_int_or_simple_record(test_model.Int32OrSimpleRecord.Int32(6)); + w.write_vector_of_unions([ + test_model.StringOrInt32.Int32(3), ... + test_model.StringOrInt32.String("hello"), ... + test_model.StringOrInt32.Int32(4) ... + ]); w.write_record_with_unions(basic_types.RecordWithUnions(... null_or_int_or_string= basic_types.Int32OrString.Int32(7), ... date_or_datetime= basic_types.TimeOrDatetime.Datetime(yardl.DateTime.from_components(2025, 3, 4, 12, 34, 56, 0)), ... diff --git a/models/test/unittests.yml b/models/test/unittests.yml index d4269b93..7cd2f4a6 100644 --- a/models/test/unittests.yml +++ b/models/test/unittests.yml @@ -313,6 +313,9 @@ RecordWithMaps: !record fields: set1: uint->uint set2: int->bool + set3: !map + keys: string + values: [string, int] Maps: !protocol sequence: @@ -329,6 +332,8 @@ Unions: !protocol intOrSimpleRecord: [int, SimpleRecord] intOrRecordWithVlens: [int, RecordWithVlens] monosotateOrIntOrSimpleRecord: [null, int, SimpleRecord] + vectorOfUnions: !vector + items: [string, int] recordWithUnions: BasicTypes.RecordWithUnions StreamsOfUnions: !protocol diff --git a/python/test_model/binary.py b/python/test_model/binary.py index 37868588..0c6afe9b 100644 --- a/python/test_model/binary.py +++ b/python/test_model/binary.py @@ -823,6 +823,9 @@ def _write_int_or_record_with_vlens(self, value: Int32OrRecordWithVlens) -> None def _write_monosotate_or_int_or_simple_record(self, value: typing.Optional[Int32OrSimpleRecord]) -> None: _binary.UnionSerializer(Int32OrSimpleRecord, [None, (Int32OrSimpleRecord.Int32, _binary.int32_serializer), (Int32OrSimpleRecord.SimpleRecord, SimpleRecordSerializer())]).write(self._stream, value) + def _write_vector_of_unions(self, value: list[StringOrInt32]) -> None: + _binary.VectorSerializer(_binary.UnionSerializer(StringOrInt32, [(StringOrInt32.String, _binary.string_serializer), (StringOrInt32.Int32, _binary.int32_serializer)])).write(self._stream, value) + def _write_record_with_unions(self, value: basic_types.RecordWithUnions) -> None: basic_types.binary.RecordWithUnionsSerializer().write(self._stream, value) @@ -844,6 +847,9 @@ def _read_int_or_record_with_vlens(self) -> Int32OrRecordWithVlens: def _read_monosotate_or_int_or_simple_record(self) -> typing.Optional[Int32OrSimpleRecord]: return _binary.UnionSerializer(Int32OrSimpleRecord, [None, (Int32OrSimpleRecord.Int32, _binary.int32_serializer), (Int32OrSimpleRecord.SimpleRecord, SimpleRecordSerializer())]).read(self._stream) + def _read_vector_of_unions(self) -> list[StringOrInt32]: + return _binary.VectorSerializer(_binary.UnionSerializer(StringOrInt32, [(StringOrInt32.String, _binary.string_serializer), (StringOrInt32.Int32, _binary.int32_serializer)])).read(self._stream) + def _read_record_with_unions(self) -> basic_types.RecordWithUnions: return basic_types.binary.RecordWithUnionsSerializer().read(self._stream) @@ -1726,20 +1732,20 @@ def read(self, stream: _binary.CodedInputStream) -> RecordWithUnionsOfContainers class RecordWithMapsSerializer(_binary.RecordSerializer[RecordWithMaps]): def __init__(self) -> None: - super().__init__([("set_1", _binary.MapSerializer(_binary.uint32_serializer, _binary.uint32_serializer)), ("set_2", _binary.MapSerializer(_binary.int32_serializer, _binary.bool_serializer))]) + super().__init__([("set_1", _binary.MapSerializer(_binary.uint32_serializer, _binary.uint32_serializer)), ("set_2", _binary.MapSerializer(_binary.int32_serializer, _binary.bool_serializer)), ("set_3", _binary.MapSerializer(_binary.string_serializer, _binary.UnionSerializer(StringOrInt32, [(StringOrInt32.String, _binary.string_serializer), (StringOrInt32.Int32, _binary.int32_serializer)])))]) def write(self, stream: _binary.CodedOutputStream, value: RecordWithMaps) -> None: if isinstance(value, np.void): self.write_numpy(stream, value) return - self._write(stream, value.set_1, value.set_2) + self._write(stream, value.set_1, value.set_2, value.set_3) def write_numpy(self, stream: _binary.CodedOutputStream, value: np.void) -> None: - self._write(stream, value['set_1'], value['set_2']) + self._write(stream, value['set_1'], value['set_2'], value['set_3']) def read(self, stream: _binary.CodedInputStream) -> RecordWithMaps: field_values = self._read(stream) - return RecordWithMaps(set_1=field_values[0], set_2=field_values[1]) + return RecordWithMaps(set_1=field_values[0], set_2=field_values[1], set_3=field_values[2]) class RecordWithNoDefaultEnumSerializer(_binary.RecordSerializer[RecordWithNoDefaultEnum]): diff --git a/python/test_model/ndjson.py b/python/test_model/ndjson.py index f30da178..a0a02387 100644 --- a/python/test_model/ndjson.py +++ b/python/test_model/ndjson.py @@ -1395,9 +1395,11 @@ class RecordWithMapsConverter(_ndjson.JsonConverter[RecordWithMaps, np.void]): def __init__(self) -> None: self._set_1_converter = _ndjson.MapConverter(_ndjson.uint32_converter, _ndjson.uint32_converter) self._set_2_converter = _ndjson.MapConverter(_ndjson.int32_converter, _ndjson.bool_converter) + self._set_3_converter = _ndjson.MapConverter(_ndjson.string_converter, _ndjson.UnionConverter(StringOrInt32, [(StringOrInt32.String, _ndjson.string_converter, [str]), (StringOrInt32.Int32, _ndjson.int32_converter, [int, float])], True)) super().__init__(np.dtype([ ("set_1", self._set_1_converter.overall_dtype()), ("set_2", self._set_2_converter.overall_dtype()), + ("set_3", self._set_3_converter.overall_dtype()), ])) def to_json(self, value: RecordWithMaps) -> object: @@ -1407,6 +1409,7 @@ def to_json(self, value: RecordWithMaps) -> object: json_object["set1"] = self._set_1_converter.to_json(value.set_1) json_object["set2"] = self._set_2_converter.to_json(value.set_2) + json_object["set3"] = self._set_3_converter.to_json(value.set_3) return json_object def numpy_to_json(self, value: np.void) -> object: @@ -1416,6 +1419,7 @@ def numpy_to_json(self, value: np.void) -> object: json_object["set1"] = self._set_1_converter.numpy_to_json(value["set_1"]) json_object["set2"] = self._set_2_converter.numpy_to_json(value["set_2"]) + json_object["set3"] = self._set_3_converter.numpy_to_json(value["set_3"]) return json_object def from_json(self, json_object: object) -> RecordWithMaps: @@ -1424,6 +1428,7 @@ def from_json(self, json_object: object) -> RecordWithMaps: return RecordWithMaps( set_1=self._set_1_converter.from_json(json_object["set1"],), set_2=self._set_2_converter.from_json(json_object["set2"],), + set_3=self._set_3_converter.from_json(json_object["set3"],), ) def from_json_to_numpy(self, json_object: object) -> np.void: @@ -1432,6 +1437,7 @@ def from_json_to_numpy(self, json_object: object) -> np.void: return ( self._set_1_converter.from_json_to_numpy(json_object["set1"]), self._set_2_converter.from_json_to_numpy(json_object["set2"]), + self._set_3_converter.from_json_to_numpy(json_object["set3"]), ) # type:ignore @@ -3690,6 +3696,11 @@ def _write_monosotate_or_int_or_simple_record(self, value: typing.Optional[Int32 json_value = converter.to_json(value) self._write_json_line({"monosotateOrIntOrSimpleRecord": json_value}) + def _write_vector_of_unions(self, value: list[StringOrInt32]) -> None: + converter = _ndjson.VectorConverter(_ndjson.UnionConverter(StringOrInt32, [(StringOrInt32.String, _ndjson.string_converter, [str]), (StringOrInt32.Int32, _ndjson.int32_converter, [int, float])], True)) + json_value = converter.to_json(value) + self._write_json_line({"vectorOfUnions": json_value}) + def _write_record_with_unions(self, value: basic_types.RecordWithUnions) -> None: converter = basic_types.ndjson.RecordWithUnionsConverter() json_value = converter.to_json(value) @@ -3719,6 +3730,11 @@ def _read_monosotate_or_int_or_simple_record(self) -> typing.Optional[Int32OrSim converter = _ndjson.UnionConverter(Int32OrSimpleRecord, [None, (Int32OrSimpleRecord.Int32, _ndjson.int32_converter, [int, float]), (Int32OrSimpleRecord.SimpleRecord, SimpleRecordConverter(), [dict])], True) return converter.from_json(json_object) + def _read_vector_of_unions(self) -> list[StringOrInt32]: + json_object = self._read_json_line("vectorOfUnions", True) + converter = _ndjson.VectorConverter(_ndjson.UnionConverter(StringOrInt32, [(StringOrInt32.String, _ndjson.string_converter, [str]), (StringOrInt32.Int32, _ndjson.int32_converter, [int, float])], True)) + return converter.from_json(json_object) + def _read_record_with_unions(self) -> basic_types.RecordWithUnions: json_object = self._read_json_line("recordWithUnions", True) converter = basic_types.ndjson.RecordWithUnionsConverter() diff --git a/python/test_model/protocols.py b/python/test_model/protocols.py index d2b0a5af..c1edc8b0 100644 --- a/python/test_model/protocols.py +++ b/python/test_model/protocols.py @@ -4123,7 +4123,7 @@ class MapsWriterBase(abc.ABC): def __init__(self) -> None: self._state = 0 - schema = r"""{"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}}]}]}""" + schema = r"""{"protocol":{"name":"Maps","sequence":[{"name":"stringToInt","type":{"map":{"keys":"string","values":"int32"}}},{"name":"intToString","type":{"map":{"keys":"int32","values":"string"}}},{"name":"stringToUnion","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"aliasedGeneric","type":{"name":"BasicTypes.AliasedMap","typeArguments":["string","int32"]}},{"name":"records","type":{"vector":{"items":"TestModel.RecordWithMaps"}}}]},"types":[{"name":"AliasedMap","typeParameters":["K","V"],"type":{"map":{"keys":"K","values":"V"}}},{"name":"RecordWithMaps","fields":[{"name":"set1","type":{"map":{"keys":"uint32","values":"uint32"}}},{"name":"set2","type":{"map":{"keys":"int32","values":"bool"}}},{"name":"set3","type":{"map":{"keys":"string","values":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}}]}]}""" def close(self) -> None: self._close() @@ -4378,11 +4378,11 @@ class UnionsWriterBase(abc.ABC): def __init__(self) -> None: self._state = 0 - schema = r"""{"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]}""" + schema = r"""{"protocol":{"name":"Unions","sequence":[{"name":"intOrSimpleRecord","type":[{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"intOrRecordWithVlens","type":[{"tag":"int32","type":"int32"},{"tag":"RecordWithVlens","type":"TestModel.RecordWithVlens"}]},{"name":"monosotateOrIntOrSimpleRecord","type":[null,{"tag":"int32","type":"int32"},{"tag":"SimpleRecord","type":"TestModel.SimpleRecord"}]},{"name":"vectorOfUnions","type":{"vector":{"items":[{"tag":"string","type":"string"},{"tag":"int32","type":"int32"}]}}},{"name":"recordWithUnions","type":"BasicTypes.RecordWithUnions"}]},"types":[{"name":"DaysOfWeek","values":[{"symbol":"monday","value":1},{"symbol":"tuesday","value":2},{"symbol":"wednesday","value":4},{"symbol":"thursday","value":8},{"symbol":"friday","value":16},{"symbol":"saturday","value":32},{"symbol":"sunday","value":64}]},{"name":"Fruits","values":[{"symbol":"apple","value":1},{"symbol":"banana","value":2},{"symbol":"pear","value":3}]},{"name":"GenericNullableUnion2","typeParameters":["T1","T2"],"type":[null,{"tag":"T1","type":"T1"},{"tag":"T2","type":"T2"}]},{"name":"RecordWithString","fields":[{"name":"i","type":"string"}]},{"name":"RecordWithUnions","fields":[{"name":"nullOrIntOrString","type":[null,{"tag":"int32","type":"int32"},{"tag":"string","type":"string"}]},{"name":"dateOrDatetime","type":[{"tag":"time","type":"time"},{"tag":"datetime","type":"datetime"}]},{"name":"nullOrFruitsOrDaysOfWeek","type":{"name":"BasicTypes.GenericNullableUnion2","typeArguments":["BasicTypes.Fruits","BasicTypes.DaysOfWeek"]}},{"name":"recordOrInt","type":[{"tag":"RecordWithString","type":"BasicTypes.RecordWithString"},{"tag":"int32","type":"int32"}]}]},{"name":"RecordWithVlens","fields":[{"name":"a","type":{"vector":{"items":"TestModel.SimpleRecord"}}},{"name":"b","type":"int32"},{"name":"c","type":"int32"}]},{"name":"SimpleRecord","fields":[{"name":"x","type":"int32"},{"name":"y","type":"int32"},{"name":"z","type":"int32"}]}]}""" def close(self) -> None: self._close() - if self._state != 8: + if self._state != 10: expected_method = self._state_to_method_name((self._state + 1) & ~1) raise ProtocolError(f"Protocol writer closed before all steps were called. Expected to call to '{expected_method}'.") @@ -4423,15 +4423,24 @@ def write_monosotate_or_int_or_simple_record(self, value: typing.Optional[Int32O self._write_monosotate_or_int_or_simple_record(value) self._state = 6 - def write_record_with_unions(self, value: basic_types.RecordWithUnions) -> None: + def write_vector_of_unions(self, value: list[StringOrInt32]) -> None: """Ordinal 3""" if self._state != 6: self._raise_unexpected_state(6) - self._write_record_with_unions(value) + self._write_vector_of_unions(value) self._state = 8 + def write_record_with_unions(self, value: basic_types.RecordWithUnions) -> None: + """Ordinal 4""" + + if self._state != 8: + self._raise_unexpected_state(8) + + self._write_record_with_unions(value) + self._state = 10 + @abc.abstractmethod def _write_int_or_simple_record(self, value: Int32OrSimpleRecord) -> None: raise NotImplementedError() @@ -4444,6 +4453,10 @@ def _write_int_or_record_with_vlens(self, value: Int32OrRecordWithVlens) -> None def _write_monosotate_or_int_or_simple_record(self, value: typing.Optional[Int32OrSimpleRecord]) -> None: raise NotImplementedError() + @abc.abstractmethod + def _write_vector_of_unions(self, value: list[StringOrInt32]) -> None: + raise NotImplementedError() + @abc.abstractmethod def _write_record_with_unions(self, value: basic_types.RecordWithUnions) -> None: raise NotImplementedError() @@ -4469,6 +4482,8 @@ def _state_to_method_name(self, state: int) -> str: if state == 4: return 'write_monosotate_or_int_or_simple_record' if state == 6: + return 'write_vector_of_unions' + if state == 8: return 'write_record_with_unions' return "" @@ -4482,7 +4497,7 @@ def __init__(self, skip_completed_check: bool = False) -> None: def close(self) -> None: self._close() - if not self._skip_completed_check and self._state != 8: + if not self._skip_completed_check and self._state != 10: if self._state % 2 == 1: previous_method = self._state_to_method_name(self._state - 1) raise ProtocolError(f"Protocol reader closed before all data was consumed. The iterable returned by '{previous_method}' was not fully consumed.") @@ -4537,20 +4552,31 @@ def read_monosotate_or_int_or_simple_record(self) -> typing.Optional[Int32OrSimp self._state = 6 return value - def read_record_with_unions(self) -> basic_types.RecordWithUnions: + def read_vector_of_unions(self) -> list[StringOrInt32]: """Ordinal 3""" if self._state != 6: self._raise_unexpected_state(6) - value = self._read_record_with_unions() + value = self._read_vector_of_unions() self._state = 8 return value + def read_record_with_unions(self) -> basic_types.RecordWithUnions: + """Ordinal 4""" + + if self._state != 8: + self._raise_unexpected_state(8) + + value = self._read_record_with_unions() + self._state = 10 + return value + def copy_to(self, writer: UnionsWriterBase) -> None: writer.write_int_or_simple_record(self.read_int_or_simple_record()) writer.write_int_or_record_with_vlens(self.read_int_or_record_with_vlens()) writer.write_monosotate_or_int_or_simple_record(self.read_monosotate_or_int_or_simple_record()) + writer.write_vector_of_unions(self.read_vector_of_unions()) writer.write_record_with_unions(self.read_record_with_unions()) @abc.abstractmethod @@ -4565,6 +4591,10 @@ def _read_int_or_record_with_vlens(self) -> Int32OrRecordWithVlens: def _read_monosotate_or_int_or_simple_record(self) -> typing.Optional[Int32OrSimpleRecord]: raise NotImplementedError() + @abc.abstractmethod + def _read_vector_of_unions(self) -> list[StringOrInt32]: + raise NotImplementedError() + @abc.abstractmethod def _read_record_with_unions(self) -> basic_types.RecordWithUnions: raise NotImplementedError() @@ -4591,6 +4621,8 @@ def _state_to_method_name(self, state: int) -> str: if state == 4: return 'read_monosotate_or_int_or_simple_record' if state == 6: + return 'read_vector_of_unions' + if state == 8: return 'read_record_with_unions' return "" diff --git a/python/test_model/types.py b/python/test_model/types.py index e7020360..46abef0d 100644 --- a/python/test_model/types.py +++ b/python/test_model/types.py @@ -889,29 +889,44 @@ def __repr__(self) -> str: NamedNDArray = npt.NDArray[np.int32] +class StringOrInt32: + String: typing.ClassVar[type["StringOrInt32UnionCase[str]"]] + Int32: typing.ClassVar[type["StringOrInt32UnionCase[yardl.Int32]"]] + +class StringOrInt32UnionCase(StringOrInt32, yardl.UnionCase[_T]): + pass + +StringOrInt32.String = type("StringOrInt32.String", (StringOrInt32UnionCase,), {"index": 0, "tag": "string"}) +StringOrInt32.Int32 = type("StringOrInt32.Int32", (StringOrInt32UnionCase,), {"index": 1, "tag": "int32"}) +del StringOrInt32UnionCase + class RecordWithMaps: set_1: dict[yardl.UInt32, yardl.UInt32] set_2: dict[yardl.Int32, bool] + set_3: dict[str, StringOrInt32] def __init__(self, *, set_1: typing.Optional[dict[yardl.UInt32, yardl.UInt32]] = None, set_2: typing.Optional[dict[yardl.Int32, bool]] = None, + set_3: typing.Optional[dict[str, StringOrInt32]] = None, ): self.set_1 = set_1 if set_1 is not None else {} self.set_2 = set_2 if set_2 is not None else {} + self.set_3 = set_3 if set_3 is not None else {} def __eq__(self, other: object) -> bool: return ( isinstance(other, RecordWithMaps) and self.set_1 == other.set_1 and self.set_2 == other.set_2 + and self.set_3 == other.set_3 ) def __str__(self) -> str: - return f"RecordWithMaps(set_1={self.set_1}, set_2={self.set_2})" + return f"RecordWithMaps(set_1={self.set_1}, set_2={self.set_2}, set_3={self.set_3})" def __repr__(self) -> str: - return f"RecordWithMaps(set_1={repr(self.set_1)}, set_2={repr(self.set_2)})" + return f"RecordWithMaps(set_1={repr(self.set_1)}, set_2={repr(self.set_2)}, set_3={repr(self.set_3)})" Fruits = basic_types.Fruits @@ -2056,17 +2071,6 @@ class AcquisitionOrImageUnionCase(AcquisitionOrImage, yardl.UnionCase[_T]): AcquisitionOrImage.Image = type("AcquisitionOrImage.Image", (AcquisitionOrImageUnionCase,), {"index": 1, "tag": "image"}) del AcquisitionOrImageUnionCase -class StringOrInt32: - String: typing.ClassVar[type["StringOrInt32UnionCase[str]"]] - Int32: typing.ClassVar[type["StringOrInt32UnionCase[yardl.Int32]"]] - -class StringOrInt32UnionCase(StringOrInt32, yardl.UnionCase[_T]): - pass - -StringOrInt32.String = type("StringOrInt32.String", (StringOrInt32UnionCase,), {"index": 0, "tag": "string"}) -StringOrInt32.Int32 = type("StringOrInt32.Int32", (StringOrInt32UnionCase,), {"index": 1, "tag": "int32"}) -del StringOrInt32UnionCase - class Int32OrSimpleRecord: Int32: typing.ClassVar[type["Int32OrSimpleRecordUnionCase[yardl.Int32]"]] SimpleRecord: typing.ClassVar[type["Int32OrSimpleRecordUnionCase[SimpleRecord]"]] @@ -2175,7 +2179,10 @@ def _mk_get_dtype(): dtype_map.setdefault(ArrayOrScalar, np.dtype(np.object_)) dtype_map.setdefault(ArrayOrScalar.Array, np.dtype(np.object_)) dtype_map.setdefault(ArrayOrScalar.Scalar, np.dtype(np.int32)) - dtype_map.setdefault(RecordWithMaps, np.dtype([('set_1', np.dtype(np.object_)), ('set_2', np.dtype(np.object_))], align=True)) + dtype_map.setdefault(RecordWithMaps, np.dtype([('set_1', np.dtype(np.object_)), ('set_2', np.dtype(np.object_)), ('set_3', np.dtype(np.object_))], align=True)) + dtype_map.setdefault(StringOrInt32, np.dtype(np.object_)) + dtype_map.setdefault(StringOrInt32.String, np.dtype(np.object_)) + dtype_map.setdefault(StringOrInt32.Int32, np.dtype(np.int32)) dtype_map.setdefault(Fruits, get_dtype(basic_types.Fruits)) dtype_map.setdefault(UInt64Enum, np.dtype(np.uint64)) dtype_map.setdefault(Int64Enum, np.dtype(np.int64)) @@ -2237,9 +2244,6 @@ def _mk_get_dtype(): dtype_map.setdefault(AcquisitionOrImage, np.dtype(np.object_)) dtype_map.setdefault(AcquisitionOrImage.Acquisition, get_dtype(SimpleAcquisition)) dtype_map.setdefault(AcquisitionOrImage.Image, np.dtype(np.object_)) - dtype_map.setdefault(StringOrInt32, np.dtype(np.object_)) - dtype_map.setdefault(StringOrInt32.String, np.dtype(np.object_)) - dtype_map.setdefault(StringOrInt32.Int32, np.dtype(np.int32)) dtype_map.setdefault(Int32OrSimpleRecord, np.dtype(np.object_)) dtype_map.setdefault(Int32OrSimpleRecord.Int32, np.dtype(np.int32)) dtype_map.setdefault(Int32OrSimpleRecord.SimpleRecord, get_dtype(SimpleRecord)) diff --git a/python/tests/test_protocol_roundtrip.py b/python/tests/test_protocol_roundtrip.py index 44d5d152..e07b58a2 100644 --- a/python/tests/test_protocol_roundtrip.py +++ b/python/tests/test_protocol_roundtrip.py @@ -549,6 +549,7 @@ def test_unions(format: Format): w.write_int_or_simple_record(tm.Int32OrSimpleRecord.Int32(1)) w.write_int_or_record_with_vlens(tm.Int32OrRecordWithVlens.Int32(2)) w.write_monosotate_or_int_or_simple_record(None) + w.write_vector_of_unions([]) w.write_record_with_unions(tm.basic_types.RecordWithUnions()) # second option @@ -562,6 +563,13 @@ def test_unions(format: Format): ) ) w.write_monosotate_or_int_or_simple_record(tm.Int32OrSimpleRecord.Int32(6)) + w.write_vector_of_unions( + [ + tm.StringOrInt32.Int32(3), + tm.StringOrInt32.String("hello"), + tm.StringOrInt32.Int32(4), + ] + ) w.write_record_with_unions( tm.basic_types.RecordWithUnions( null_or_int_or_string=tm.basic_types.Int32OrString.Int32(7), diff --git a/tooling/internal/matlab/static_files/+binary/UnionSerializer.m b/tooling/internal/matlab/static_files/+binary/UnionSerializer.m index ba935c9b..57b30ec7 100755 --- a/tooling/internal/matlab/static_files/+binary/UnionSerializer.m +++ b/tooling/internal/matlab/static_files/+binary/UnionSerializer.m @@ -1,7 +1,7 @@ % Copyright (c) Microsoft Corporation. % Licensed under the MIT License. -classdef UnionSerializer < handle +classdef UnionSerializer < yardl.binary.TypeSerializer properties (Access=protected) classname_