// 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 #include #include "yarpl/single/SingleSubscription.h" namespace yarpl { namespace single { template class SingleObserver { public: virtual ~SingleObserver() = default; virtual void onSubscribe(std::shared_ptr) = 0; virtual void onSuccess(T) = 0; virtual void onError(folly::exception_wrapper) = 0; template static std::shared_ptr> create(Success&& success); template static std::shared_ptr> create( Success&& success, Error&& error); }; template class SingleObserverBase : public SingleObserver { public: // Note: If any of the following methods is overridden in a subclass, the new // methods SHOULD ensure that these are invoked as well. void onSubscribe(std::shared_ptr subscription) override { DCHECK(subscription); if (subscription_) { subscription->cancel(); return; } subscription_ = std::move(subscription); } void onSuccess(T) override { DCHECK(subscription_) << "Calling onSuccess() without a subscription"; subscription_.reset(); } // No further calls to the subscription after this method is invoked. void onError(folly::exception_wrapper) override { DCHECK(subscription_) << "Calling onError() without a subscription"; subscription_.reset(); } protected: SingleSubscription* subscription() { return subscription_.operator->(); } private: std::shared_ptr subscription_; }; /// Specialization of SingleObserverBase. template <> class SingleObserverBase { public: virtual ~SingleObserverBase() = default; // 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) { DCHECK(subscription); if (subscription_) { subscription->cancel(); return; } subscription_ = std::move(subscription); } virtual void onSuccess() { DCHECK(subscription_) << "Calling onSuccess() 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(); } protected: SingleSubscription* subscription() { return subscription_.operator->(); } private: std::shared_ptr subscription_; }; template class SimpleSingleObserver : public SingleObserver { public: SimpleSingleObserver(Success success, Error error) : success_(std::move(success)), error_(std::move(error)) {} void onSubscribe(std::shared_ptr) { // throw away the subscription } void onSuccess(T value) override { success_(std::move(value)); } void onError(folly::exception_wrapper ew) { error_(std::move(ew)); } Success success_; Error error_; }; template template std::shared_ptr> SingleObserver::create( Success&& success) { static_assert( folly::is_invocable::value, "Input `success` should be invocable with a parameter of `T`."); return std::make_shared, folly::Function>>( std::forward(success), [](folly::exception_wrapper) {}); } template template std::shared_ptr> SingleObserver::create( Success&& success, Error&& error) { static_assert( folly::is_invocable::value, "Input `success` should be invocable with a parameter of `T`."); static_assert( folly::is_invocable::value, "Input `error` should be invocable with a parameter of " "`folly::exception_wrapper`."); return std::make_shared< SimpleSingleObserver, std::decay_t>>( std::forward(success), std::forward(error)); } } // namespace single } // namespace yarpl