[XTypes/PL_CDR2] Member header issue for sequences with an inner type of 2 bytes length (short, unsigned short)
In some cases NEXTINT is not serialized for a sequence with an inner type of 2 bytes length (short, unsigned short), also the incorrect Length code value is assigned.
According to XTypes spec (7.4.3.4.2 Member Header (EMHEADER), Length Code (LC) and NEXTINT).
LC = 4 = 0b100 indicates serialized member length is NEXTINT
The Member header for the sequences of (unsigned) shorts should always be 8 bytes in length (i.e include NEXTINT) and has a Length code of 4, but in some cases depending on the sequence length NEXTINT is not serialized at all, and incorrect LC code value is assigned.
// IDL
module test
{
@mutable
struct with_short_seq
{
sequence<short> the_shorts_;
};
};
// empty seq
000b0000080000000000002000000000
// single el
000b00000a00000000000000010000002a000000
//two elements
000b00000c00000000000030020000002a002b00
//three elements
000b000012000000000000400a000000030000002a002b002c000000
// four elements
000b000014000000000000400c000000040000002a002b002c002d00
Looks like that the proper encoding started from the sequences with a length of three elements (correct length code + nextint).
//Reproducible example //DataWriter
typename test::with_short_seqPubSubType::type data;
for (int i = 0; i < 5; ++i)
{
std::cout << "Pub: " << i << " seq lenght: " << data.the_shorts_().size() <<"\n";
writer_->write(&data);
data.the_shorts_().emplace_back(i + 42);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
//DataReader void on_data_available(fastdds::DataReader* reader) override
{
fastdds::SampleInfo info;
while (reader->take_next_sample(&msg_, &info) == ReturnCode_t::RETCODE_OK)
{
if (info.valid_data)
{
std::cout << "Rec seq length: " << msg_.the_shorts_().size() << std::endl;
}
}
}
*Subscriber cannot handle the sequence with a single element, because of malformed member header.
Seems it happened because the generated code calls serialize_member function (from << op) with subsequent xcdr2_begin_serialize_member always with default header_selerction (XCdrHeaderSelection header_selection = XCdrHeaderSelection::AUTO_WITH_SHORT_HEADER_BY_DEFAULT). Later on in the xcdr2_end_serialize_member not switched to the long header because the member length is less or equal than 8 bytes for sequence < 3 elements (8 bytes - length (uint32_t) + 2 * 2B).