inline CallStatus handleDBusMessageReply(
            const CallStatus dbusMessageCallStatus,
            const DBusMessage& dbusMessage,
            index_sequence<ArgIndices_...>,
            std::tuple<ArgTypes_...> argTuple) const {
        (void)argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes
                        // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650

        CallStatus callStatus = dbusMessageCallStatus;

        if (dbusMessageCallStatus == CallStatus::SUCCESS) {
            if (!dbusMessage.isErrorType()) {
                DBusInputStream dbusInputStream(dbusMessage);
                const bool success
                    = DBusSerializableArguments<ArgTypes_...>::deserialize(
                            dbusInputStream,
                            std::get<ArgIndices_>(argTuple)...);
                if (!success)
                    callStatus = CallStatus::REMOTE_ERROR;
            } else {
                callStatus = CallStatus::REMOTE_ERROR;
            }
        }

        callback_(callStatus, std::move(std::get<ArgIndices_>(argTuple))...);
        return callStatus;
    }
    inline CallStatus handleDBusMessageReply(
            const CallStatus _dbusMessageCallStatus,
            const DBusMessage& _dbusMessage,
            index_sequence<ArgIndices_...>,
            std::tuple<ArgTypes_...>& _argTuple) const {
        (void)_argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes
                        // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650

        CallStatus callStatus = _dbusMessageCallStatus;

        if (_dbusMessageCallStatus == CallStatus::SUCCESS) {
            DBusInputStream dbusInputStream(_dbusMessage);
            if(DBusSerializableArguments<ArgTypes_...>::deserialize(dbusInputStream,
                    std::get<ArgIndices_>(_argTuple)...)) {
            } else {
                callStatus = CallStatus::REMOTE_ERROR;
            }
        } else {
            if(_dbusMessage.isErrorType()) {
                //ensure that delegate object (e.g. Proxy and its error events) survives
                if(auto itsDelegateObject = this->delegate_.object_.lock()) {
                    DBusErrorEventHelper::notifyListeners(_dbusMessage,
                                                          _dbusMessage.getError(),
                                                          typename make_sequence_range<sizeof...(ErrorEvents_), 0>::type(),
                                                          errorEvents_);
                }
            }
        }

        //ensure that delegate object (i.e Proxy) is not destroyed while callback function is invoked
        if(auto itsDelegateObject = this->delegate_.object_.lock())
            this->delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(_argTuple))...);

        return callStatus;
    }
SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& dbusMessage) {
    const std::string& dbusServiceUniqueName = dbusMessage.getSenderName();

    assert(dbusMessage.isSignalType());
    assert(dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager"));
    assert(dbusMessage.hasMemberName("InterfacesAdded") || dbusMessage.hasMemberName("InterfacesRemoved"));

    DBusInputStream dbusInputStream(dbusMessage);
    std::string dbusObjectPath;
    std::unordered_set<std::string> dbusInterfaceNames;
    DBusRecordState dbusInterfaceNameState;

    dbusInputStream >> dbusObjectPath;

    if (dbusMessage.hasMemberName("InterfacesAdded")) {
        dbusInterfaceNameState = DBusRecordState::AVAILABLE;

        typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict;
        typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict;
        typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict;
        DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict;
        dbusInputStream >> dbusObjectPathAndInterfacesDict;

        for (auto& dbusInterfaceIterator : dbusObjectPathAndInterfacesDict) {
            const auto& dbusInterfaceName = dbusInterfaceIterator.first;
            dbusInterfaceNames.insert(dbusInterfaceName);
        }
    } else {
    inline CallStatus handleDBusMessageReply(
            const CallStatus _dbusMessageCallStatus,
            const DBusMessage& _dbusMessage,
            index_sequence<ArgIndices_...>,
            std::tuple<ArgTypes_...>& _argTuple) const {
        (void)_argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes
                        // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650

        CallStatus callStatus = _dbusMessageCallStatus;

        if (_dbusMessageCallStatus == CallStatus::SUCCESS) {
            DBusInputStream dbusInputStream(_dbusMessage);
            if(DBusSerializableArguments<ArgTypes_...>::deserialize(dbusInputStream,
                    std::get<ArgIndices_>(_argTuple)...)) {
            } else {
                callStatus = CallStatus::REMOTE_ERROR;
            }
        }

        //ensure that delegate object (e.g. Proxy) survives
        if(auto itsDelegateObject = delegate_.object_.lock())
            delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(_argTuple))...);

        return callStatus;
    }
const CommonAPI::DBus::DBusObjectManagerStub::DBusObjectPathAndInterfacesDict getManagedObjects(const std::string& dbusObjectPath,
                                                                                                std::shared_ptr<CommonAPI::DBus::DBusConnection> connection) {
    auto dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall(
                    dbusServiceName,
                    dbusObjectPath,
                    CommonAPI::DBus::DBusObjectManagerStub::getInterfaceName(),
                    "GetManagedObjects");

    CommonAPI::DBus::DBusError dbusError;
    auto dbusMessageReply = connection->sendDBusMessageWithReplyAndBlock(dbusMessageCall, dbusError);

    CommonAPI::DBus::DBusInputStream dbusInputStream(dbusMessageReply);

    CommonAPI::DBus::DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict;
    dbusInputStream >> dbusObjectPathAndInterfacesDict;

    return dbusObjectPathAndInterfacesDict;
}