diff --git a/src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.cpp b/src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.cpp index a82147d0573..af4ef8b9b63 100644 --- a/src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.cpp +++ b/src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.cpp @@ -373,11 +373,12 @@ bool DynamicDataImpl::equals( } else if (TK_UNION == type_kind) { - return std::static_pointer_cast(value_.at(0))->equals( - std::static_pointer_cast(other_data->value_.at(0))) && - (MEMBER_ID_INVALID == selected_union_member_ || - std::static_pointer_cast(value_.at(selected_union_member_))->equals( - std::static_pointer_cast(other_data->value_.at(selected_union_member_)))); + return (MEMBER_ID_INVALID == selected_union_member_ && + MEMBER_ID_INVALID == other_data->selected_union_member()) || + (std::static_pointer_cast(value_.at(0))->equals(std::static_pointer_cast( + other_data->value_.at(0))) && + std::static_pointer_cast(value_.at(selected_union_member_))->equals(std:: + static_pointer_cast(other_data->value_.at(selected_union_member_)))); } else if (TK_ARRAY == type_kind || TK_SEQUENCE == type_kind) @@ -6478,6 +6479,12 @@ bool DynamicDataImpl::deserialize( if (MEMBER_ID_INVALID == selected_union_member_) { selected_union_member_ = type->default_union_member(); + + // Check again after attempting to assign the default member + if (MEMBER_ID_INVALID == selected_union_member_) + { + ret_value = false; + } } } else @@ -6488,7 +6495,12 @@ bool DynamicDataImpl::deserialize( break; default: { - if (1 == value_.count(selected_union_member_)) + if (MEMBER_ID_INVALID == selected_union_member_) + { + // Do nothing + return false; + } + else if (1 == value_.count(selected_union_member_)) { // Check MemberId in mutable case. auto member_data {std::static_pointer_cast(value_.at( diff --git a/src/cpp/fastdds/xtypes/serializers/json/dynamic_data_json.cpp b/src/cpp/fastdds/xtypes/serializers/json/dynamic_data_json.cpp index 3c9cb86e910..9234376c0e7 100644 --- a/src/cpp/fastdds/xtypes/serializers/json/dynamic_data_json.cpp +++ b/src/cpp/fastdds/xtypes/serializers/json/dynamic_data_json.cpp @@ -199,19 +199,29 @@ ReturnCode_t json_serialize_member( // Fill JSON object with loaned value nlohmann::json j_union; - DynamicTypeMember::_ref_type active_type_member; - ReturnCode_t ret = st_data->enclosing_type()->get_member(active_type_member, - st_data->selected_union_member()); - if (RETCODE_OK != ret) + ReturnCode_t ret = RETCODE_OK; + MemberId selected_member = st_data->selected_union_member(); + + if (MEMBER_ID_INVALID == selected_member) { - EPROSIMA_LOG_ERROR(XTYPES_UTILS, - "Error encountered while serializing union member to JSON: get_member failed."); + // No member selected, insert empty JSON object + json_insert(member_name, j_union, output); } else { - if (RETCODE_OK == (ret = json_serialize_member(st_data, active_type_member, j_union, format))) + DynamicTypeMember::_ref_type active_type_member; + ret = st_data->enclosing_type()->get_member(active_type_member, selected_member); + if (RETCODE_OK != ret) { - json_insert(member_name, j_union, output); + EPROSIMA_LOG_ERROR(XTYPES_UTILS, + "Error encountered while serializing union member to JSON: get_member failed."); + } + else + { + if (RETCODE_OK == (ret = json_serialize_member(st_data, active_type_member, j_union, format))) + { + json_insert(member_name, j_union, output); + } } } diff --git a/test/dds-types-test/unions.hpp b/test/dds-types-test/unions.hpp index c67d1e834d6..02778bdc2b5 100644 --- a/test/dds-types-test/unions.hpp +++ b/test/dds-types-test/unions.hpp @@ -19159,6 +19159,176 @@ class DefaultAnnotationExternalValue std::function member_destructor_; }; +/*! + * @brief This class represents the structure UnionShortExtraMember defined by the user in the IDL file. + * @ingroup unions + */ +class UnionShortExtraMember +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport UnionShortExtraMember() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~UnionShortExtraMember() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object UnionShortExtraMember that will be copied. + */ + eProsima_user_DllExport UnionShortExtraMember( + const UnionShortExtraMember& x) + { + m_var_union_short = x.m_var_union_short; + + m_var_long = x.m_var_long; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object UnionShortExtraMember that will be copied. + */ + eProsima_user_DllExport UnionShortExtraMember( + UnionShortExtraMember&& x) noexcept + { + m_var_union_short = std::move(x.m_var_union_short); + m_var_long = x.m_var_long; + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object UnionShortExtraMember that will be copied. + */ + eProsima_user_DllExport UnionShortExtraMember& operator =( + const UnionShortExtraMember& x) + { + + m_var_union_short = x.m_var_union_short; + + m_var_long = x.m_var_long; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object UnionShortExtraMember that will be copied. + */ + eProsima_user_DllExport UnionShortExtraMember& operator =( + UnionShortExtraMember&& x) noexcept + { + + m_var_union_short = std::move(x.m_var_union_short); + m_var_long = x.m_var_long; + return *this; + } + + /*! + * @brief Comparison operator. + * @param x UnionShortExtraMember object to compare. + */ + eProsima_user_DllExport bool operator ==( + const UnionShortExtraMember& x) const + { + return (m_var_union_short == x.m_var_union_short && + m_var_long == x.m_var_long); + } + + /*! + * @brief Comparison operator. + * @param x UnionShortExtraMember object to compare. + */ + eProsima_user_DllExport bool operator !=( + const UnionShortExtraMember& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member var_union_short + * @param _var_union_short New value to be copied in member var_union_short + */ + eProsima_user_DllExport void var_union_short( + const Union_Short& _var_union_short) + { + m_var_union_short = _var_union_short; + } + + /*! + * @brief This function moves the value in member var_union_short + * @param _var_union_short New value to be moved in member var_union_short + */ + eProsima_user_DllExport void var_union_short( + Union_Short&& _var_union_short) + { + m_var_union_short = std::move(_var_union_short); + } + + /*! + * @brief This function returns a constant reference to member var_union_short + * @return Constant reference to member var_union_short + */ + eProsima_user_DllExport const Union_Short& var_union_short() const + { + return m_var_union_short; + } + + /*! + * @brief This function returns a reference to member var_union_short + * @return Reference to member var_union_short + */ + eProsima_user_DllExport Union_Short& var_union_short() + { + return m_var_union_short; + } + + + /*! + * @brief This function sets a value in member var_long + * @param _var_long New value for member var_long + */ + eProsima_user_DllExport void var_long( + int32_t _var_long) + { + m_var_long = _var_long; + } + + /*! + * @brief This function returns the value of member var_long + * @return Value of member var_long + */ + eProsima_user_DllExport int32_t var_long() const + { + return m_var_long; + } + + /*! + * @brief This function returns a reference to member var_long + * @return Reference to member var_long + */ + eProsima_user_DllExport int32_t& var_long() + { + return m_var_long; + } + + + +private: + + Union_Short m_var_union_short; + int32_t m_var_long{0}; + +}; #endif // _FAST_DDS_GENERATED_UNIONS_HPP_ diff --git a/test/dds-types-test/unionsCdrAux.hpp b/test/dds-types-test/unionsCdrAux.hpp index b867b30d18c..97080a482b5 100644 --- a/test/dds-types-test/unionsCdrAux.hpp +++ b/test/dds-types-test/unionsCdrAux.hpp @@ -182,6 +182,9 @@ constexpr uint32_t UnionInnerUnionHelper_max_key_cdr_typesize {0UL}; +constexpr uint32_t UnionShortExtraMember_max_cdr_typesize {20UL}; +constexpr uint32_t UnionShortExtraMember_max_key_cdr_typesize {0UL}; + constexpr uint32_t UnionDiscriminatorULongLong_max_cdr_typesize {24UL}; @@ -378,6 +381,10 @@ eProsima_user_DllExport void serialize_key( +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const UnionShortExtraMember& data); + } // namespace fastcdr } // namespace eprosima diff --git a/test/dds-types-test/unionsCdrAux.ipp b/test/dds-types-test/unionsCdrAux.ipp index 7d79e3d484e..4247d00a70b 100644 --- a/test/dds-types-test/unionsCdrAux.ipp +++ b/test/dds-types-test/unionsCdrAux.ipp @@ -8474,6 +8474,95 @@ eProsima_user_DllExport void deserialize( }); } +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const UnionShortExtraMember& data, + size_t& current_alignment) +{ + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.var_union_short(), current_alignment); + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1), + data.var_long(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const UnionShortExtraMember& data) +{ + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.var_union_short() + << eprosima::fastcdr::MemberId(1) << data.var_long() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + UnionShortExtraMember& data) +{ + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.var_union_short(); + break; + + case 1: + dcdr >> data.var_long(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const UnionShortExtraMember& data) +{ + + static_cast(scdr); + static_cast(data); + scdr << data.var_union_short(); + + scdr << data.var_long(); + +} + + } // namespace fastcdr } // namespace eprosima diff --git a/test/dds-types-test/unionsPubSubTypes.cxx b/test/dds-types-test/unionsPubSubTypes.cxx index 76958231cfb..6bdd0a1cfc5 100644 --- a/test/dds-types-test/unionsPubSubTypes.cxx +++ b/test/dds-types-test/unionsPubSubTypes.cxx @@ -7454,6 +7454,187 @@ void UnionSeveralFieldsWithDefaultPubSubType::register_type_object_representatio +UnionShortExtraMemberPubSubType::UnionShortExtraMemberPubSubType() +{ + set_name("UnionShortExtraMember"); + uint32_t type_size = UnionShortExtraMember_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = UnionShortExtraMember_max_key_cdr_typesize > 16 ? UnionShortExtraMember_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); +} + +UnionShortExtraMemberPubSubType::~UnionShortExtraMemberPubSubType() +{ + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } +} + +bool UnionShortExtraMemberPubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) +{ + const UnionShortExtraMember* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; +} + +bool UnionShortExtraMemberPubSubType::deserialize( + SerializedPayload_t& payload, + void* data) +{ + try + { + // Convert DATA to pointer of your type + UnionShortExtraMember* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; +} + +uint32_t UnionShortExtraMemberPubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) +{ + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } +} + +void* UnionShortExtraMemberPubSubType::create_data() +{ + return reinterpret_cast(new UnionShortExtraMember()); +} + +void UnionShortExtraMemberPubSubType::delete_data( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool UnionShortExtraMemberPubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + UnionShortExtraMember data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; +} + +bool UnionShortExtraMemberPubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + const UnionShortExtraMember* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + UnionShortExtraMember_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || UnionShortExtraMember_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; +} + +void UnionShortExtraMemberPubSubType::register_type_object_representation() +{ + register_UnionShortExtraMember_type_identifier(type_identifiers_); +} + // Include auxiliary functions like for serializing/deserializing. #include "unionsCdrAux.ipp" diff --git a/test/dds-types-test/unionsPubSubTypes.hpp b/test/dds-types-test/unionsPubSubTypes.hpp index 66d99edd67f..4401752582c 100644 --- a/test/dds-types-test/unionsPubSubTypes.hpp +++ b/test/dds-types-test/unionsPubSubTypes.hpp @@ -3362,5 +3362,86 @@ class UnionSeveralFieldsWithDefaultPubSubType : public eprosima::fastdds::dds::T +/*! + * @brief This class represents the TopicDataType of the type UnionShortExtraMember defined by the user in the IDL file. + * @ingroup unions + */ +class UnionShortExtraMemberPubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef UnionShortExtraMember type; + + eProsima_user_DllExport UnionShortExtraMemberPubSubType(); + + eProsima_user_DllExport ~UnionShortExtraMemberPubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return true; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + +private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + +}; + #endif // FAST_DDS_GENERATED__UNIONS_PUBSUBTYPES_HPP diff --git a/test/dds-types-test/unionsTypeObjectSupport.cxx b/test/dds-types-test/unionsTypeObjectSupport.cxx index c28ca6611fd..3627bcb4382 100644 --- a/test/dds-types-test/unionsTypeObjectSupport.cxx +++ b/test/dds-types-test/unionsTypeObjectSupport.cxx @@ -7228,4 +7228,91 @@ void register_DefaultAnnotationExternalValue_type_identifier( } } } +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_UnionShortExtraMember_type_identifier( + TypeIdentifierPair& type_ids_UnionShortExtraMember) +{ + + ReturnCode_t return_code_UnionShortExtraMember {eprosima::fastdds::dds::RETCODE_OK}; + return_code_UnionShortExtraMember = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "UnionShortExtraMember", type_ids_UnionShortExtraMember); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_UnionShortExtraMember) + { + StructTypeFlag struct_flags_UnionShortExtraMember = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_UnionShortExtraMember = "UnionShortExtraMember"; + eprosima::fastcdr::optional type_ann_builtin_UnionShortExtraMember; + eprosima::fastcdr::optional ann_custom_UnionShortExtraMember; + CompleteTypeDetail detail_UnionShortExtraMember = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_UnionShortExtraMember, ann_custom_UnionShortExtraMember, type_name_UnionShortExtraMember.to_string()); + CompleteStructHeader header_UnionShortExtraMember; + header_UnionShortExtraMember = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_UnionShortExtraMember); + CompleteStructMemberSeq member_seq_UnionShortExtraMember; + { + TypeIdentifierPair type_ids_var_union_short; + ReturnCode_t return_code_var_union_short {eprosima::fastdds::dds::RETCODE_OK}; + return_code_var_union_short = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "Union_Short", type_ids_var_union_short); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_var_union_short) + { + ::register_Union_Short_type_identifier(type_ids_var_union_short); + } + StructMemberFlag member_flags_var_union_short = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_var_union_short = 0x00000000; + bool common_var_union_short_ec {false}; + CommonStructMember common_var_union_short {TypeObjectUtils::build_common_struct_member(member_id_var_union_short, member_flags_var_union_short, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_var_union_short, common_var_union_short_ec))}; + if (!common_var_union_short_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure var_union_short member TypeIdentifier inconsistent."); + return; + } + MemberName name_var_union_short = "var_union_short"; + eprosima::fastcdr::optional member_ann_builtin_var_union_short; + ann_custom_UnionShortExtraMember.reset(); + CompleteMemberDetail detail_var_union_short = TypeObjectUtils::build_complete_member_detail(name_var_union_short, member_ann_builtin_var_union_short, ann_custom_UnionShortExtraMember); + CompleteStructMember member_var_union_short = TypeObjectUtils::build_complete_struct_member(common_var_union_short, detail_var_union_short); + TypeObjectUtils::add_complete_struct_member(member_seq_UnionShortExtraMember, member_var_union_short); + } + { + TypeIdentifierPair type_ids_var_long; + ReturnCode_t return_code_var_long {eprosima::fastdds::dds::RETCODE_OK}; + return_code_var_long = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "_int32_t", type_ids_var_long); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_var_long) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "var_long Structure member TypeIdentifier unknown to TypeObjectRegistry."); + return; + } + StructMemberFlag member_flags_var_long = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_var_long = 0x00000001; + bool common_var_long_ec {false}; + CommonStructMember common_var_long {TypeObjectUtils::build_common_struct_member(member_id_var_long, member_flags_var_long, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_var_long, common_var_long_ec))}; + if (!common_var_long_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure var_long member TypeIdentifier inconsistent."); + return; + } + MemberName name_var_long = "var_long"; + eprosima::fastcdr::optional member_ann_builtin_var_long; + ann_custom_UnionShortExtraMember.reset(); + CompleteMemberDetail detail_var_long = TypeObjectUtils::build_complete_member_detail(name_var_long, member_ann_builtin_var_long, ann_custom_UnionShortExtraMember); + CompleteStructMember member_var_long = TypeObjectUtils::build_complete_struct_member(common_var_long, detail_var_long); + TypeObjectUtils::add_complete_struct_member(member_seq_UnionShortExtraMember, member_var_long); + } + CompleteStructType struct_type_UnionShortExtraMember = TypeObjectUtils::build_complete_struct_type(struct_flags_UnionShortExtraMember, header_UnionShortExtraMember, member_seq_UnionShortExtraMember); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_UnionShortExtraMember, type_name_UnionShortExtraMember.to_string(), type_ids_UnionShortExtraMember)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "UnionShortExtraMember already registered in TypeObjectRegistry for a different type."); + } + } +} diff --git a/test/dds-types-test/unionsTypeObjectSupport.hpp b/test/dds-types-test/unionsTypeObjectSupport.hpp index fe75d7be5fc..d2757c9d758 100644 --- a/test/dds-types-test/unionsTypeObjectSupport.hpp +++ b/test/dds-types-test/unionsTypeObjectSupport.hpp @@ -1046,6 +1046,18 @@ eProsima_user_DllExport void register_DefaultAnnotation_type_identifier( */ eProsima_user_DllExport void register_DefaultAnnotationExternalValue_type_identifier( eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); +/** + * @brief Register UnionShortExtraMember related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_UnionShortExtraMember_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); #endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC diff --git a/test/dds/xtypes/TypeLookupServicePublisher.h b/test/dds/xtypes/TypeLookupServicePublisher.h index 8389fc1be9a..cfd9087b89c 100644 --- a/test/dds/xtypes/TypeLookupServicePublisher.h +++ b/test/dds/xtypes/TypeLookupServicePublisher.h @@ -893,6 +893,7 @@ class TypeLookupServicePublisher PUBLISHER_TYPE_CREATOR_FUNCTION(UnionSeveralFields); PUBLISHER_TYPE_CREATOR_FUNCTION(UnionSeveralFieldsWithDefault); PUBLISHER_TYPE_CREATOR_FUNCTION(UnionShort); + PUBLISHER_TYPE_CREATOR_FUNCTION(UnionShortExtraMember); PUBLISHER_TYPE_CREATOR_FUNCTION(UnionString); PUBLISHER_TYPE_CREATOR_FUNCTION(UnionULong); PUBLISHER_TYPE_CREATOR_FUNCTION(UnionULongLong); diff --git a/test/dds/xtypes/TypeLookupServiceSubscriber.h b/test/dds/xtypes/TypeLookupServiceSubscriber.h index b302dc729d6..ca3bdd17ed3 100644 --- a/test/dds/xtypes/TypeLookupServiceSubscriber.h +++ b/test/dds/xtypes/TypeLookupServiceSubscriber.h @@ -905,6 +905,7 @@ class TypeLookupServiceSubscriber SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionSeveralFields); SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionSeveralFieldsWithDefault); SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionShort); + SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionShortExtraMember); SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionString); SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionULong); SUBSCRIBER_TYPE_CREATOR_FUNCTION(UnionULongLong); diff --git a/test/dds/xtypes/TypesTestsCases/Cases_unions.json b/test/dds/xtypes/TypesTestsCases/Cases_unions.json index dd553071ff6..ae259f7822b 100644 --- a/test/dds/xtypes/TypesTestsCases/Cases_unions.json +++ b/test/dds/xtypes/TypesTestsCases/Cases_unions.json @@ -735,6 +735,27 @@ } ] }, + { + "TestCase": "Case_unions_UnionShortExtraMember", + "participants": [ + { + "kind": "publisher", + "samples": "10", + "timeout": "10", + "expected_matches": "1", + "known_types": [ + "UnionShortExtraMember" + ] + }, + { + "kind": "subscriber", + "samples": "10", + "timeout": "10", + "expected_matches": "1", + "known_types": [] + } + ] + }, { "TestCase": "Case_unions_UnionString", "participants": [ diff --git a/test/feature/dynamic_types/dds_types_tests/DynamicTypesUnionsDDSTypesTests.cpp b/test/feature/dynamic_types/dds_types_tests/DynamicTypesUnionsDDSTypesTests.cpp index 98a705460ae..1ad333e0a96 100644 --- a/test/feature/dynamic_types/dds_types_tests/DynamicTypesUnionsDDSTypesTests.cpp +++ b/test/feature/dynamic_types/dds_types_tests/DynamicTypesUnionsDDSTypesTests.cpp @@ -72,6 +72,7 @@ constexpr const char* struct_union_enum_label_discriminator_name = "UnionDiscrim constexpr const char* struct_union_alias_discriminator_name = "UnionDiscriminatorAlias"; constexpr const char* struct_union_several_fields_name = "UnionSeveralFields"; constexpr const char* struct_union_several_fields_with_default_name = "UnionSeveralFieldsWithDefault"; +constexpr const char* struct_union_short_extra_member_name = "UnionShortExtraMember"; constexpr const char* union_short_name = "Union_Short"; constexpr const char* union_ushort_name = "Union_UShort"; @@ -2740,6 +2741,64 @@ TEST_F(DynamicTypesDDSTypesTest, DDSTypesTest_UnionSeveralFieldsWithDefault) EXPECT_EQ(DynamicDataFactory::get_instance()->delete_data(data), RETCODE_OK); } +// Regression test for issue #21773 +TEST_F(DynamicTypesDDSTypesTest, DDSTypesTest_UnionShortExtraMember) +{ + TypeDescriptor::_ref_type type_descriptor {traits::make_shared()}; + type_descriptor->kind(TK_STRUCTURE); + type_descriptor->name(struct_union_short_extra_member_name); + DynamicTypeBuilder::_ref_type struct_builder {DynamicTypeBuilderFactory::get_instance()->create_type(type_descriptor)}; + + type_descriptor = traits::make_shared(); + type_descriptor->kind(TK_UNION); + type_descriptor->name(union_short_name); + type_descriptor->discriminator_type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_INT32)); + DynamicTypeBuilder::_ref_type union_builder {DynamicTypeBuilderFactory::get_instance()->create_type(type_descriptor)}; + + MemberDescriptor::_ref_type member_descriptor {traits::make_shared()}; + member_descriptor->name(var_union_member_a); + member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_INT16)); + member_descriptor->label({0}); + union_builder->add_member(member_descriptor); + + member_descriptor = traits::make_shared(); + member_descriptor->name(var_union_short_name); + member_descriptor->type(union_builder->build()); + struct_builder->add_member(member_descriptor); + + member_descriptor = traits::make_shared(); + member_descriptor->name(var_long_name); + member_descriptor->type(DynamicTypeBuilderFactory::get_instance()->get_primitive_type(TK_INT32)); + struct_builder->add_member(member_descriptor); + + DynamicType::_ref_type struct_type {struct_builder->build()}; + + DynamicData::_ref_type data {DynamicDataFactory::get_instance()->create_data(struct_type)}; + ASSERT_TRUE(data); + + // Set no value for union (will be empty as no default is set) + + // Set value for extra member + int32_t test_value = 23; + EXPECT_EQ(data->set_int32_value(data->get_member_id_by_name(var_long_name), test_value), RETCODE_OK); + + for (auto encoding : encodings) + { + UnionShortExtraMember struct_data; + TypeSupport static_pubsubType {new UnionShortExtraMemberPubSubType()}; + check_serialization_deserialization(struct_type, data, encoding, struct_data, + static_pubsubType); + EXPECT_THROW(struct_data.var_union_short().a(), eprosima::fastcdr::exception::BadParamException); + EXPECT_EQ(struct_data.var_long(), test_value); + } + + xtypes::TypeIdentifierPair static_type_ids; + register_UnionShortExtraMember_type_identifier(static_type_ids); + check_typeobject_registry(struct_type, static_type_ids); + + EXPECT_EQ(DynamicDataFactory::get_instance()->delete_data(data), RETCODE_OK); +} + // This union is custom and serves to test a specific case used in internal type of DDS X-Types (TypeIdentifier). // No supported by Dynamic Language Binding. // TEST_F(DynamicTypesDDSTypesTest, DDSTypesTest_DefaultAnnotation) diff --git a/thirdparty/dds-types-test b/thirdparty/dds-types-test index c856b2479b7..923dc5986cc 160000 --- a/thirdparty/dds-types-test +++ b/thirdparty/dds-types-test @@ -1 +1 @@ -Subproject commit c856b2479b7f15c242b7dc1dd382143c0498da07 +Subproject commit 923dc5986cc64bf34ceee2b20fdcb4c045907672