Add the pre-generated map pair property ordering

The map pair require explicit "optional" flag, since all map values
should be serialized independent of field presence. Use the
pre-generated ordering info of the following message:
   message pair {
       optional string key = 1;
       optional string value = 2;
   }

The field type is not considered when deserializing map pairs.

Also remove the previous map pair ordering functions from
QProtobufPropertyOrderingInfo.

[ChangeLog][QtProtobuf] Removed infoForMapKey and infoForMapValue
methods from the QtProtobufPrivate::QProtobufPropertyOrderingInfo
structure.

Pick-to: 6.7
Change-Id: I6c4411a35ac1d19b669b1acd8b56a41bf5a0dda8
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Alexey Edelev 2023-12-17 10:59:45 +01:00
parent af429547ec
commit 252ee90ea9
5 changed files with 52 additions and 8 deletions

View File

@ -676,8 +676,8 @@ void QProtobufJsonSerializer::serializeMapPair(const QVariant &key, const QVaria
auto store = d_ptr->activeValue.toObject();
QJsonObject mapObject = store.value(fieldName).toObject();
d_ptr->activeValue = QJsonObject();
d_ptr->serializeProperty(value, fieldInfo.infoForMapValue());
mapObject.insert(key.toString(), d_ptr->activeValue.toObject().value(fieldName));
d_ptr->serializeProperty(value, QProtobufSerializerPrivate::mapValueOrdering);
mapObject.insert(key.toString(), d_ptr->activeValue.toObject().value("value"_L1));
store.insert(fieldName, mapObject);
d_ptr->activeValue = store;
}

View File

@ -108,6 +108,48 @@ using SerializerRegistryType =
std::array<QProtobufSerializerPrivate::ProtobufSerializationHandler, N>;
namespace {
static constexpr struct {
QtProtobufPrivate::QProtobufPropertyOrdering::Data data;
const std::array<uint, 9> qt_protobuf_Maptest_uint_data;
const char qt_protobuf_Maptest_char_data[23];
} qt_protobuf_Maptest_metadata {
// data
{
0, /* = version */
2, /* = num fields */
3, /* = field number offset */
5, /* = property index offset */
7, /* = field flags offset */
4, /* = message full name length */
},
// uint_data
{
// JSON name offsets:
5, /* = key */
9, /* = value */
15, /* = end-of-string-marker */
// Field numbers:
1, /* = key */
2, /* = value */
// Property indices:
0, /* = key */
2, /* = value */
// Field flags:
QtProtobufPrivate::Optional, /* = key */
QtProtobufPrivate::Optional, /* = value */
},
// char_data
/* metadata char_data: */
"pair\0" /* = full message name */
/* field char_data: */
"key\0value\0"
};
const QtProtobufPrivate::QProtobufPropertyOrdering mapPropertyOrdering = {
&qt_protobuf_Maptest_metadata.data
};
#define QT_CONSTRUCT_PROTOBUF_SERIALIZATION_HANDLER(Type, WireType) \
{ \
QMetaType::fromType<Type>(), \
@ -266,6 +308,10 @@ QByteArray QProtobufSerializer::serializeMessage(
return d_ptr->result;
}
const QProtobufPropertyOrderingInfo QProtobufSerializerPrivate::mapValueOrdering{
mapPropertyOrdering, 1
};
void QProtobufSerializerPrivate::serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering
&ordering)
@ -375,7 +421,7 @@ void QProtobufSerializer::serializeMapPair(const QVariant &key, const QVariant &
->serializer(key,
QProtobufSerializerPrivate::encodeHeader(1,
keyHandler->wireType)));
d_ptr->serializeProperty(value, fieldInfo.infoForMapValue());
d_ptr->serializeProperty(value, QProtobufSerializerPrivate::mapValueOrdering);
store.append(QProtobufSerializerPrivate::encodeHeader(fieldInfo.getFieldNumber(),
QtProtobuf::WireTypes::LengthDelimited));
store.append(QProtobufSerializerPrivate::serializeVarintCommon<uint32_t>(d_ptr->result.size()));

View File

@ -523,6 +523,9 @@ public:
QByteArray result;
bool preserveUnknownFields = true;
static const QtProtobufPrivate::QProtobufPropertyOrderingInfo mapValueOrdering;
private:
Q_DISABLE_COPY_MOVE(QProtobufSerializerPrivate)
QProtobufSerializer *q_ptr;

View File

@ -68,10 +68,6 @@ struct QProtobufPropertyOrderingInfo
int getPropertyIndex() const { return ordering.getPropertyIndex(index); }
uint getFieldFlags() const { return ordering.getFieldFlags(index); }
// Needed for maps, which uses field number 1 and 2 for key and value respectively
QProtobufPropertyOrderingInfo infoForMapKey() const { return { ordering, index, 1 }; }
QProtobufPropertyOrderingInfo infoForMapValue() const { return { ordering, index, 2 }; }
private:
QProtobufPropertyOrderingInfo(QProtobufPropertyOrdering ord, int ind, int fieldNumber)
: ordering(ord), index(ind), overrideFieldNumber(fieldNumber)

View File

@ -50,7 +50,6 @@ void QtProtobufJsonMapTypesSerializationTest::SimpleFixed32StringMapSerializeTes
{ 15, { "fifteen" } },
{ 0, { "" } } });
QByteArray result = test.serialize(m_serializer.get());
QEXPECT_FAIL("", "Map value with no presence are ignored by json serializer.", Continue);
QCOMPARE(
result,
"{\"mapField\":{\"0\":\"\",\"10\":\"ten\",\"15\":\"fifteen\",\"42\":\"fourty two\"}}"_ba);