File indexing completed on 2024-05-05 04:41:15

0001 // SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com>
0002 //
0003 // SPDX-License-Identifier: MIT
0004 
0005 #pragma once
0006 
0007 #include <QJSEngine>
0008 #include <QJSValue>
0009 #include <QSharedPointer>
0010 #include <QVariant>
0011 
0012 namespace Croutons
0013 {
0014 
0015 class FutureBase
0016 {
0017 
0018     Q_GADGET
0019 
0020     struct Shared {
0021         QVariant result;
0022 
0023         // ok, err
0024         std::function<void(QVariant)> onSucc = [](QVariant) {};
0025         std::function<void(QVariant)> onFail = [](QVariant) {};
0026 
0027         std::function<void(QVariant)> valueOr = [](QVariant) {};
0028         QObject* valueOrObject = nullptr;
0029 
0030         bool settled = false;
0031         bool succeeded = false;
0032     };
0033     QSharedPointer<Shared> d;
0034 
0035 public:
0036     FutureBase() {
0037         d.reset(new Shared);
0038     }
0039     FutureBase(const FutureBase& other) {
0040         this->d = other.d;
0041     }
0042     ~FutureBase() {
0043     }
0044 
0045     void succeed(const QVariant& value) const {
0046         if (d->settled) {
0047             return;
0048         }
0049         d->settled = true;
0050         d->succeeded = true;
0051 
0052         d->result = value;
0053         d->onSucc(d->result);
0054         d->valueOr(d->result);
0055     }
0056     void fail(const QVariant& value) const {
0057         if (d->settled) {
0058             return;
0059         }
0060         d->settled = true;
0061         d->succeeded = false;
0062 
0063         d->result = value;
0064         d->onFail(d->result);
0065     }
0066     QVariant result() const {
0067         return d->result;
0068     }
0069     void then(std::function<void(QVariant)> then, std::function<void(QVariant)> fail = nullptr) const {
0070         d->onSucc = then;
0071         if (fail != nullptr) {
0072             d->onFail = fail;
0073         }
0074         if (d->settled && d->succeeded) {
0075             then(result());
0076         } else if (d->settled && !d->succeeded && fail != nullptr) {
0077             fail(result());
0078         }
0079     }
0080     bool settled() const {
0081         return d->settled;
0082     }
0083     bool success() const {
0084         return d->succeeded;
0085     }
0086     Q_INVOKABLE void then(const QJSValue& it) {
0087         d->onSucc = [va = it](QVariant n) mutable {
0088             va.call({va.engine()->toScriptValue(n)});
0089         };
0090         d->onFail = [va = it](QVariant n) mutable {
0091             va.call({QJSValue(), va.engine()->toScriptValue(n)});
0092         };
0093 
0094         if (d->settled && d->succeeded) {
0095             d->onSucc(result());
0096             d->valueOr(result());
0097         } else if (d->settled && !d->succeeded) {
0098             d->onFail(result());
0099         }
0100     }
0101     Q_INVOKABLE QJSValue valueOr(const QJSValue& it);
0102 };
0103 
0104 }; // namespace Croutons