Re-enable google.protobuf.Timestamp support in well-know types

Enable google.protobuf.Timestamp in well-know types. Add extra
methods that allow convert the generated class from/to QDateTime.

Task-number: QTBUG-114972
Task-number: QTBUG-112430
Change-Id: I00a6878cdd0461f9f0938dd5fa284743df0d8dc8
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Alexey Edelev 2023-06-30 14:03:36 +02:00
parent 01c3c1c811
commit 4d963586fb
9 changed files with 130 additions and 19 deletions

View File

@ -98,11 +98,6 @@ void MessageDeclarationPrinter::printComparisonOperators()
void MessageDeclarationPrinter::printConstructors() void MessageDeclarationPrinter::printConstructors()
{ {
m_printer->Print(m_typeMap, CommonTemplates::ConstructorMessageDeclarationTemplate()); m_printer->Print(m_typeMap, CommonTemplates::ConstructorMessageDeclarationTemplate());
if (m_descriptor->full_name() == "google.protobuf.Timestamp") {
m_printer->Print("Timestamp(const QDateTime &datetime);\n"
"operator QDateTime() const;\n");
}
} }
void MessageDeclarationPrinter::printMaps() void MessageDeclarationPrinter::printMaps()
@ -388,6 +383,14 @@ void MessageDeclarationPrinter::printOneofEnums()
}); });
} }
void MessageDeclarationPrinter::printPublicExtras()
{
if (m_descriptor->full_name() == "google.protobuf.Timestamp") {
m_printer->Print("static Timestamp fromDateTime(const QDateTime &dateTime);\n"
"QDateTime toDateTime() const;\n");
}
}
void MessageDeclarationPrinter::printClassBody() void MessageDeclarationPrinter::printClassBody()
{ {
printProperties(); printProperties();
@ -412,6 +415,7 @@ void MessageDeclarationPrinter::printClassBody()
Indent(); Indent();
m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationDeclaration()); m_printer->Print(m_typeMap, CommonTemplates::MetaTypeRegistrationDeclaration());
printPublicExtras();
Outdent(); Outdent();
printPrivateBlock(); printPrivateBlock();

View File

@ -42,6 +42,7 @@ private:
void printFieldEnum(); void printFieldEnum();
void printQEnums(); void printQEnums();
void printOneofEnums(); void printOneofEnums();
void printPublicExtras();
//Recursive functionality //Recursive functionality
void printClassDeclarationPrivate(); void printClassDeclarationPrivate();

View File

@ -129,6 +129,7 @@ void MessageDefinitionPrinter::printClassDefinitionPrivate()
printMoveSemantic(); printMoveSemantic();
printComparisonOperators(); printComparisonOperators();
printGetters(); printGetters();
printPublicExtras();
} }
void MessageDefinitionPrinter::printClassDefinition() void MessageDefinitionPrinter::printClassDefinition()
@ -300,19 +301,6 @@ void MessageDefinitionPrinter::printConstructors()
{ {
m_printer->Print(m_typeMap, CommonTemplates::ConstructorMessageDefinitionTemplate()); m_printer->Print(m_typeMap, CommonTemplates::ConstructorMessageDefinitionTemplate());
m_printer->Print(CommonTemplates::EmptyBracesTemplate()); m_printer->Print(CommonTemplates::EmptyBracesTemplate());
if (m_descriptor->full_name() == "google.protobuf.Timestamp") {
m_printer->Print(
"Timestamp::Timestamp(const QDateTime &datetime) : "
"QProtobufMessage(&Timestamp::staticMetaObject),"
"m_seconds(datetime.toMSecsSinceEpoch() / 1000)\n"
", m_nanos((datetime.toMSecsSinceEpoch() % 1000) * 1000)\n"
"{}\n"
"Timestamp::operator QDateTime() const\n"
"{\n"
" return QDateTime::fromMSecsSinceEpoch(m_seconds * 1000 + m_nanos / 1000);\n"
"}\n");
}
} }
void MessageDefinitionPrinter::printInitializationList() void MessageDefinitionPrinter::printInitializationList()
@ -475,6 +463,25 @@ void MessageDefinitionPrinter::printDestructor()
m_printer->Print(m_typeMap, "$classname$::~$classname$() = default;\n\n"); m_printer->Print(m_typeMap, "$classname$::~$classname$() = default;\n\n");
} }
void MessageDefinitionPrinter::printPublicExtras()
{
if (m_descriptor->full_name() == "google.protobuf.Timestamp") {
m_printer->Print(
"Timestamp Timestamp::fromDateTime(const QDateTime &dateTime)\n"
"{\n"
" Timestamp ts;\n"
" ts.setSeconds(dateTime.toMSecsSinceEpoch() / 1000);\n"
" ts.setNanos((dateTime.toMSecsSinceEpoch() % 1000) * 1000000);\n"
" return ts;\n"
"}\n\n"
"QDateTime Timestamp::toDateTime() const\n"
"{\n"
" return QDateTime::fromMSecsSinceEpoch(\n"
" seconds() * 1000 + nanos() / 1000000, QTimeZone(QTimeZone::UTC));\n"
"}\n\n");
}
}
void MessageDefinitionPrinter::printClassRegistration(Printer *printer) void MessageDefinitionPrinter::printClassRegistration(Printer *printer)
{ {
if (common::hasNestedMessages(m_descriptor)) { if (common::hasNestedMessages(m_descriptor)) {

View File

@ -43,6 +43,8 @@ private:
void printGetters(); void printGetters();
void printDestructor(); void printDestructor();
void printPublicExtras();
void printClassDefinitionPrivate(); void printClassDefinitionPrivate();
}; };

View File

@ -75,6 +75,18 @@ void QProtobufGenerator::GenerateSources(const FileDescriptor *file,
registrationPrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}}, registrationPrinter->Print({{"include", basename + CommonTemplates::ProtoFileSuffix()}},
CommonTemplates::InternalIncludeTemplate()); CommonTemplates::InternalIncludeTemplate());
bool generateWellknownTimestamp = false;
common::iterateMessages(file, [&](const Descriptor *message) {
if (message->full_name() == "google.protobuf.Timestamp") {
generateWellknownTimestamp = true;
return;
}
});
if (generateWellknownTimestamp) {
sourcePrinter->Print({ { "include", "QtCore/QTimeZone" } },
CommonTemplates::ExternalIncludeTemplate());
}
sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}}, sourcePrinter->Print({{"include", "QtProtobuf/qprotobufserializer.h"}},
CommonTemplates::ExternalIncludeTemplate()); CommonTemplates::ExternalIncludeTemplate());
if (Options::instance().hasQml()) { if (Options::instance().hasQml()) {

View File

@ -19,7 +19,7 @@ qt_internal_add_protobuf_wellknown_types(ProtobufWellKnownTypes
# field_mask # field_mask
# source_context # source_context
# struct # struct
# timestamp timestamp
# wrappers # wrappers
# type # type
# api # api

View File

@ -17,4 +17,20 @@ qt6_add_protobuf(tst_protobuf_any
PROTO_INCLUDES PROTO_INCLUDES
$<TARGET_PROPERTY:Qt6::ProtobufWellKnownTypes,QT_PROTO_INCLUDES> $<TARGET_PROPERTY:Qt6::ProtobufWellKnownTypes,QT_PROTO_INCLUDES>
) )
qt_internal_add_test(tst_protobuf_timestamp
SOURCES
tst_protobuf_timestamp.cpp
LIBRARIES
Qt::Test
Qt::ProtobufWellKnownTypes
)
qt6_add_protobuf(tst_protobuf_timestamp
PROTO_FILES
../../shared/data/proto/timestampmessages.proto
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated"
PROTO_INCLUDES
$<TARGET_PROPERTY:Qt6::ProtobufWellKnownTypes,QT_PROTO_INCLUDES>
)
qt_autogen_tools_initial_setup(tst_protobuf_basictypes_gen) qt_autogen_tools_initial_setup(tst_protobuf_basictypes_gen)

View File

@ -0,0 +1,57 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "timestampmessages.qpb.h"
#include <QtProtobuf/qprotobufserializer.h>
#include <ratio>
#include <QtTest/QtTest>
class tst_protobuf_timestamp : public QObject
{
Q_OBJECT
private slots:
void simpleMessage();
};
using namespace qtproto::tests;
using namespace Qt::StringLiterals;
void tst_protobuf_timestamp::simpleMessage()
{
QProtobufSerializer serializer;
TimestampMessage ts;
ts.setField(google::protobuf::Timestamp::fromDateTime(
{ { 1970, 01, 01 }, { 0, 0, 1 }, QTimeZone(QTimeZone::UTC) }));
QCOMPARE_EQ(ts.field().nanos(), 0);
QCOMPARE_EQ(ts.field().seconds(), 1);
ts.setField(google::protobuf::Timestamp::fromDateTime(
{ { 1984, 6, 8 }, { 10, 10, 10 }, QTimeZone(QTimeZone::UTC) }));
QCOMPARE_EQ(ts.field().nanos(), 0);
QCOMPARE_EQ(ts.field().seconds(), 455537410);
QDateTime now = QDateTime::currentDateTime();
ts.setField(google::protobuf::Timestamp::fromDateTime(now));
QCOMPARE_EQ(ts.field().toDateTime(), now);
constexpr auto milliToNano = std::ratio_divide<std::nano, std::milli>::den;
QCOMPARE_EQ(ts.field().nanos(), (now.toMSecsSinceEpoch() % std::milli::den) * milliToNano);
QCOMPARE_EQ(ts.field().seconds(), now.toMSecsSinceEpoch() / std::milli::den);
ts.setField(google::protobuf::Timestamp::fromDateTime(
QDateTime::fromMSecsSinceEpoch(1688124178703, QTimeZone(QTimeZone::UTC))));
QCOMPARE_EQ(ts.serialize(&serializer).toHex(), "0a0c0892f6faa40610c0db9bcf02"_ba);
QVERIFY(ts.deserialize(&serializer, QByteArray::fromHex("0a0c08c3f7faa4061080d594d603")));
QCOMPARE_EQ(ts.field().toDateTime(),
QDateTime::fromMSecsSinceEpoch(1688124355986, QTimeZone(QTimeZone::UTC)));
}
QTEST_MAIN(tst_protobuf_timestamp)
#include "tst_protobuf_timestamp.moc"

View File

@ -0,0 +1,12 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package qtproto.tests;
message TimestampMessage
{
google.protobuf.Timestamp field = 1;
}