summaryrefslogtreecommitdiffstats
path: root/src/grpcquick/qqmlgrpcfunctionalhandlers.cpp
blob: 771349c84294b6e99ccc2b4f886c7534882d142d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include <QtGrpcQuick/qqmlgrpcfunctionalhandlers.h>

QT_BEGIN_NAMESPACE

namespace QtGrpcQuickFunctional {

void handleDeserializationError(QJSEngine *jsEngine, const QJSValue &errorCallback)
{
    if (!errorCallback.isCallable())
        return;
    using StatusCode = QtGrpc::StatusCode;
    const auto status = QGrpcStatus{ StatusCode::InvalidArgument,
                                     "Unable to deserialize return value" };
    errorCallback.call(QJSValueList{ jsEngine->toScriptValue(status) });
}

bool checkReceivedStatus(QJSEngine *jsEngine, const QGrpcStatus &status,
                         const QJSValue &errorCallback)
{
    Q_ASSERT(jsEngine != nullptr);

    if (status.isOk())
        return true;

    if (errorCallback.isCallable())
        errorCallback.call(QJSValueList{ jsEngine->toScriptValue(status) });
    return false;
}

void connectMultipleReceiveOperationFinished(QJSEngine *jsEngine,
                                             std::unique_ptr<QGrpcOperation> &&operation,
                                             const QJSValue &successCallback,
                                             const QJSValue &errorCallback)
{
    auto *operationPtr = operation.get();
    QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operationPtr);

    QObject::connect(
        operationPtr, &QGrpcOperation::finished, jsEngine,
        [successCallback, errorCallback, jsEngine,
         operation = std::move(operation)](const QGrpcStatus &status) {
            // We take 'operation' by copy so that its lifetime
            // is extended until this lambda is destroyed.
            if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback)
                && successCallback.isCallable()) {
                successCallback.call();
            }
        },
        Qt::SingleShotConnection);
}

void handleReceivedMessageImpl(QJSEngine *jsEngine, std::optional<QJSValue> message,
                               const QJSValue &successCallback, const QJSValue &errorCallback)
{
    if (!successCallback.isCallable())
        return;

    if (message)
        successCallback.call(QJSValueList{ *message });
    else
        QtGrpcQuickFunctional::handleDeserializationError(jsEngine, errorCallback);
}

void Private::connectSingleReceiveOperationFinishedImpl(QJSEngine *jsEngine,
                                                        HandleReceivedMessageImpl impl,
                                                        std::unique_ptr<QGrpcOperation> &&operation,
                                                        const QJSValue &successCallback,
                                                        const QJSValue &errorCallback)
{
    auto *operationPtr = operation.get();
    QtGrpcQuickFunctional::validateEngineAndOperation(jsEngine, operationPtr);

    QObject::connect(
        operationPtr, &QGrpcCallReply::finished, jsEngine,
        [jsEngine, successCallback, errorCallback, impl,
         operation = std::move(operation)](const QGrpcStatus &status) {
            // We take 'operation' by copy so that its lifetime
            // is extended until this lambda is destroyed.
            if (QtGrpcQuickFunctional::checkReceivedStatus(jsEngine, status, errorCallback))
                impl(jsEngine, operation.get(), successCallback, errorCallback);
        },
        Qt::SingleShotConnection);
}

void Private::makeServerStreamConnectionsImpl(QJSEngine *jsEngine,
                                              HandleReceivedMessageImpl impl,
                                              std::unique_ptr<QGrpcServerStream> &&stream,
                                              const QJSValue &messageCallback,
                                              const QJSValue &finishCallback,
                                              const QJSValue &errorCallback)
{
    QObject::connect(stream.get(), &QGrpcServerStream::messageReceived, jsEngine,
                     [streamPtr = stream.get(), impl, messageCallback, jsEngine, errorCallback]() {
        impl(jsEngine, streamPtr, messageCallback, errorCallback);
    });
    QtGrpcQuickFunctional::connectMultipleReceiveOperationFinished(jsEngine, std::move(stream),
                                                                   finishCallback, errorCallback);
}

} // namespace QtGrpcQuickFunctional

QT_END_NAMESPACE