1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QQMLGRPCFUNCTIONALHANDLERS_H
5#define QQMLGRPCFUNCTIONALHANDLERS_H
6
7#include <QtGrpcQuick/qtgrpcquickexports.h>
8
9#include <QtGrpc/qgrpccallreply.h>
10#include <QtGrpc/qgrpcstream.h>
11
12#include <QtQml/qqmlengine.h>
13
14#include <QtCore/qobject.h>
15#include <QtCore/qtconfigmacros.h>
16
17QT_BEGIN_NAMESPACE
18
19namespace QtGrpcQuickFunctional {
20
21Q_ALWAYS_INLINE void validateEngineAndOperation(QJSEngine *jsEngine, QGrpcOperation *operation)
22{
23 Q_ASSERT(jsEngine != nullptr);
24 Q_ASSERT(operation != nullptr);
25}
26
27template <typename Ret>
28std::optional<QJSValue> readMessageToJSValue(QJSEngine *jsEngine, QGrpcOperation *operation)
29{
30 QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operation);
31
32 if (std::optional<Ret> result = operation->read<Ret>())
33 return jsEngine->toScriptValue(*result);
34 return std::nullopt;
35}
36
37Q_GRPCQUICK_EXPORT
38void handleReceivedMessageImpl(QJSEngine *jsEngine, std::optional<QJSValue> message,
39 const QJSValue &successCallback, const QJSValue &errorCallback);
40
41template <typename Ret>
42void handleReceivedMessage(QJSEngine *jsEngine, QGrpcOperation *operation,
43 const QJSValue &successCallback, const QJSValue &errorCallback)
44{
45 auto message = QtGrpcQuickFunctional::readMessageToJSValue<Ret>(jsEngine, operation);
46 QtGrpcQuickFunctional::handleReceivedMessageImpl(jsEngine, message: std::move(message), successCallback,
47 errorCallback);
48}
49
50Q_GRPCQUICK_EXPORT
51bool checkReceivedStatus(QJSEngine *jsEngine, const QGrpcStatus &status,
52 const QJSValue &errorCallback);
53
54Q_GRPCQUICK_EXPORT
55void connectMultipleReceiveOperationFinished(QJSEngine *jsEngine,
56 std::unique_ptr<QGrpcOperation> &&operation,
57 const QJSValue &successCallback,
58 const QJSValue &errorCallback);
59
60template <typename Ret>
61void connectSingleReceiveOperationFinished(QJSEngine *jsEngine,
62 std::unique_ptr<QGrpcOperation> &&operation,
63 const QJSValue &successCallback,
64 const QJSValue &errorCallback)
65{
66 auto *operationPtr = operation.get();
67 QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operation: operationPtr);
68
69 auto finishConnection = std::make_shared<QMetaObject::Connection>();
70 *finishConnection = QObject::
71 connect(operationPtr, &QGrpcCallReply::finished, jsEngine,
72 [jsEngine, successCallback, errorCallback, finishConnection,
73 operation = std::move(operation)](const QGrpcStatus &status) {
74 // We take 'operation' by copy so that its lifetime
75 // is extended until this lambda is destroyed.
76 if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status,
77 errorCallback)) {
78 QtGrpcQuickFunctional::handleReceivedMessage<Ret>(jsEngine, operation.get(),
79 successCallback,
80 errorCallback);
81 }
82 QObject::disconnect(*finishConnection);
83 });
84}
85
86template <typename Ret>
87void makeCallConnections(QJSEngine *jsEngine, std::unique_ptr<QGrpcCallReply> &&reply,
88 const QJSValue &finishCallback, const QJSValue &errorCallback)
89{
90 QtGrpcQuickFunctional::connectSingleReceiveOperationFinished<Ret>(jsEngine, std::move(reply),
91 finishCallback,
92 errorCallback);
93}
94
95template <typename Ret>
96void makeServerStreamConnections(QJSEngine *jsEngine, std::unique_ptr<QGrpcServerStream> &&stream,
97 const QJSValue &messageCallback, const QJSValue &finishCallback,
98 const QJSValue &errorCallback)
99{
100 QObject::connect(stream.get(), &QGrpcServerStream::messageReceived, jsEngine,
101 [streamPtr = stream.get(), messageCallback, jsEngine, errorCallback]() {
102 QtGrpcQuickFunctional::handleReceivedMessage<Ret>(jsEngine, streamPtr,
103 messageCallback,
104 errorCallback);
105 });
106 QtGrpcQuickFunctional::connectMultipleReceiveOperationFinished(jsEngine, operation: std::move(stream),
107 successCallback: finishCallback, errorCallback);
108}
109
110template <typename Ret>
111void makeClientStreamConnections(QJSEngine *jsEngine, std::unique_ptr<QGrpcClientStream> &&stream,
112 const QJSValue &finishCallback, const QJSValue &errorCallback)
113{
114 QtGrpcQuickFunctional::connectSingleReceiveOperationFinished<Ret>(jsEngine, std::move(stream),
115 finishCallback,
116 errorCallback);
117}
118
119template <typename Ret>
120void makeBidiStreamConnections(QJSEngine *jsEngine, std::unique_ptr<QGrpcBidiStream> &&stream,
121 const QJSValue &messageCallback, const QJSValue &finishCallback,
122 const QJSValue &errorCallback)
123{
124 QObject::connect(stream.get(), &QGrpcBidiStream::messageReceived, jsEngine,
125 [streamPtr = stream.get(), messageCallback, jsEngine, errorCallback] {
126 QtGrpcQuickFunctional::handleReceivedMessage<Ret>(jsEngine, streamPtr,
127 messageCallback,
128 errorCallback);
129 });
130 QtGrpcQuickFunctional::connectMultipleReceiveOperationFinished(jsEngine, operation: std::move(stream),
131 successCallback: finishCallback, errorCallback);
132}
133
134} // namespace QtGrpcQuickFunctional
135
136QT_END_NAMESPACE
137
138#endif // QQMLGRPCFUNCTIONALHANDLERS_H
139

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtgrpc/src/grpcquick/qqmlgrpcfunctionalhandlers.h