Rocket.Chat.ReactNative/ios/Pods/Flipper-RSocket/yarpl/observable/Observer.h

227 lines
6.3 KiB
C++

// Copyright (c) Facebook, Inc. and its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <folly/ExceptionWrapper.h>
#include <folly/functional/Invoke.h>
#include <glog/logging.h>
#include "yarpl/Refcounted.h"
#include "yarpl/observable/Subscription.h"
namespace yarpl {
namespace observable {
template <typename T>
class Observer : public yarpl::enable_get_ref {
public:
// Note: If any of the following methods is overridden in a subclass, the new
// methods SHOULD ensure that these are invoked as well.
virtual void onSubscribe(std::shared_ptr<Subscription> subscription) {
DCHECK(subscription);
if (subscription_) {
DLOG(ERROR) << "attempt to double subscribe";
subscription->cancel();
return;
}
if (cancelled_) {
subscription->cancel();
}
subscription_ = std::move(subscription);
}
// No further calls to the subscription after this method is invoked.
virtual void onComplete() {
DCHECK(subscription_) << "Calling onComplete() without a subscription";
subscription_.reset();
}
// No further calls to the subscription after this method is invoked.
virtual void onError(folly::exception_wrapper) {
DCHECK(subscription_) << "Calling onError() without a subscription";
subscription_.reset();
}
virtual void onNext(T) = 0;
bool isUnsubscribed() const {
CHECK(subscription_);
return subscription_->isCancelled();
}
// Ability to add more subscription objects which will be notified when the
// subscription has been cancelled.
// Note that calling cancel on the tied subscription is not going to cancel
// this subscriber
void addSubscription(std::shared_ptr<Subscription> subscription) {
if (!subscription_) {
subscription->cancel();
return;
}
subscription_->tieSubscription(std::move(subscription));
}
template <typename OnCancel>
void addSubscription(OnCancel onCancel) {
addSubscription(Subscription::create(std::move(onCancel)));
}
bool isUnsubscribedOrTerminated() const {
return !subscription_ || subscription_->isCancelled();
}
protected:
void unsubscribe() {
if (subscription_) {
subscription_->cancel();
} else {
cancelled_ = true;
}
}
public:
template <
typename Next,
typename =
typename std::enable_if<folly::is_invocable<Next, T>::value>::type>
static std::shared_ptr<Observer<T>> create(Next next);
template <
typename Next,
typename Error,
typename =
typename std::enable_if<folly::is_invocable<Next, T>::value>::type,
typename = typename std::enable_if<
folly::is_invocable<Error, folly::exception_wrapper>::value>::type>
static std::shared_ptr<Observer<T>> create(Next next, Error error);
template <
typename Next,
typename Error,
typename Complete,
typename =
typename std::enable_if<folly::is_invocable<Next, T>::value>::type,
typename = typename std::enable_if<
folly::is_invocable<Error, folly::exception_wrapper>::value>::type,
typename =
typename std::enable_if<folly::is_invocable<Complete>::value>::type>
static std::shared_ptr<Observer<T>>
create(Next next, Error error, Complete complete);
static std::shared_ptr<Observer<T>> create() {
class NullObserver : public Observer<T> {
public:
void onNext(T) {}
};
return std::make_shared<NullObserver>();
}
private:
std::shared_ptr<Subscription> subscription_;
bool cancelled_{false};
};
namespace details {
template <typename T, typename Next>
class Base : public Observer<T> {
static_assert(std::is_same<std::decay_t<Next>, Next>::value, "undecayed");
public:
template <typename FNext>
explicit Base(FNext&& next) : next_(std::forward<FNext>(next)) {}
void onNext(T value) override {
next_(std::move(value));
}
private:
Next next_;
};
template <typename T, typename Next, typename Error>
class WithError : public Base<T, Next> {
static_assert(std::is_same<std::decay_t<Error>, Error>::value, "undecayed");
public:
template <typename FNext, typename FError>
WithError(FNext&& next, FError&& error)
: Base<T, Next>(std::forward<FNext>(next)),
error_(std::forward<FError>(error)) {}
void onError(folly::exception_wrapper error) override {
error_(std::move(error));
}
private:
Error error_;
};
template <typename T, typename Next, typename Error, typename Complete>
class WithErrorAndComplete : public WithError<T, Next, Error> {
static_assert(
std::is_same<std::decay_t<Complete>, Complete>::value,
"undecayed");
public:
template <typename FNext, typename FError, typename FComplete>
WithErrorAndComplete(FNext&& next, FError&& error, FComplete&& complete)
: WithError<T, Next, Error>(
std::forward<FNext>(next),
std::forward<FError>(error)),
complete_(std::move(complete)) {}
void onComplete() override {
complete_();
}
private:
Complete complete_;
};
} // namespace details
template <typename T>
template <typename Next, typename>
std::shared_ptr<Observer<T>> Observer<T>::create(Next next) {
return std::make_shared<details::Base<T, Next>>(std::move(next));
}
template <typename T>
template <typename Next, typename Error, typename, typename>
std::shared_ptr<Observer<T>> Observer<T>::create(Next next, Error error) {
return std::make_shared<details::WithError<T, Next, Error>>(
std::move(next), std::move(error));
}
template <typename T>
template <
typename Next,
typename Error,
typename Complete,
typename,
typename,
typename>
std::shared_ptr<Observer<T>>
Observer<T>::create(Next next, Error error, Complete complete) {
return std::make_shared<
details::WithErrorAndComplete<T, Next, Error, Complete>>(
std::move(next), std::move(error), std::move(complete));
}
} // namespace observable
} // namespace yarpl