1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtGrpcQuick/qqmlgrpcfunctionalhandlers.h>
5
6QT_BEGIN_NAMESPACE
7
8namespace QtGrpcQuickFunctional {
9
10void handleDeserializationError(QJSEngine *jsEngine, const QJSValue &errorCallback)
11{
12 if (!errorCallback.isCallable())
13 return;
14 using StatusCode = QtGrpc::StatusCode;
15 const auto status = QGrpcStatus{ StatusCode::InvalidArgument,
16 "Unable to deserialize return value" };
17 errorCallback.call(args: QJSValueList{ jsEngine->toScriptValue(value: status) });
18}
19
20bool checkReceivedStatus(QJSEngine *jsEngine, const QGrpcStatus &status,
21 const QJSValue &errorCallback)
22{
23 Q_ASSERT(jsEngine != nullptr);
24
25 if (status.isOk())
26 return true;
27
28 if (errorCallback.isCallable())
29 errorCallback.call(args: QJSValueList{ jsEngine->toScriptValue(value: status) });
30 return false;
31}
32
33void connectMultipleReceiveOperationFinished(QJSEngine *jsEngine,
34 std::unique_ptr<QGrpcOperation> &&operation,
35 const QJSValue &successCallback,
36 const QJSValue &errorCallback)
37{
38 auto *operationPtr = operation.get();
39 QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operation: operationPtr);
40
41 QObject::connect(
42 sender: operationPtr, signal: &QGrpcOperation::finished, context: jsEngine,
43 slot: [successCallback, errorCallback, jsEngine,
44 operation = std::move(operation)](const QGrpcStatus &status) {
45 // We take 'operation' by copy so that its lifetime
46 // is extended until this lambda is destroyed.
47 if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback)
48 && successCallback.isCallable()) {
49 successCallback.call();
50 }
51 },
52 type: Qt::SingleShotConnection);
53}
54
55void handleReceivedMessageImpl(QJSEngine *jsEngine, std::optional<QJSValue> message,
56 const QJSValue &successCallback, const QJSValue &errorCallback)
57{
58 if (!successCallback.isCallable())
59 return;
60
61 if (message)
62 successCallback.call(args: QJSValueList{ *message });
63 else
64 QtGrpcQuickFunctional::handleDeserializationError(jsEngine, errorCallback);
65}
66
67void Private::connectSingleReceiveOperationFinishedImpl(QJSEngine *jsEngine,
68 HandleReceivedMessageImpl impl,
69 std::unique_ptr<QGrpcOperation> &&operation,
70 const QJSValue &successCallback,
71 const QJSValue &errorCallback)
72{
73 auto *operationPtr = operation.get();
74 QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operation: operationPtr);
75
76 QObject::connect(
77 sender: operationPtr, signal: &QGrpcCallReply::finished, context: jsEngine,
78 slot: [jsEngine, successCallback, errorCallback, impl,
79 operation = std::move(operation)](const QGrpcStatus &status) {
80 // We take 'operation' by copy so that its lifetime
81 // is extended until this lambda is destroyed.
82 if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback))
83 impl(jsEngine, operation.get(), successCallback, errorCallback);
84 },
85 type: Qt::SingleShotConnection);
86}
87
88void Private::makeServerStreamConnectionsImpl(QJSEngine *jsEngine,
89 HandleReceivedMessageImpl impl,
90 std::unique_ptr<QGrpcServerStream> &&stream,
91 const QJSValue &messageCallback,
92 const QJSValue &finishCallback,
93 const QJSValue &errorCallback)
94{
95 QObject::connect(sender: stream.get(), signal: &QGrpcServerStream::messageReceived, context: jsEngine,
96 slot: [streamPtr = stream.get(), impl, messageCallback, jsEngine, errorCallback]() {
97 impl(jsEngine, streamPtr, messageCallback, errorCallback);
98 });
99 QtGrpcQuickFunctional::connectMultipleReceiveOperationFinished(jsEngine, operation: std::move(stream),
100 successCallback: finishCallback, errorCallback);
101}
102
103} // namespace QtGrpcQuickFunctional
104
105QT_END_NAMESPACE
106

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