1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_TEST_RECTIFY_CALLBACK_INTERNAL_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_TEST_RECTIFY_CALLBACK_INTERNAL_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <utility> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h" 12*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/types/is_instantiation.h" 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker namespace base::internal { 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker // RectifyCallbackWrapper binds a wrapper around the actual callback that 18*6777b538SAndroid Build Coastguard Worker // discards the ignored arguments and forwards the remaining arguments to the 19*6777b538SAndroid Build Coastguard Worker // wrapped callback. 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker template <template <typename> typename CallbackType, 22*6777b538SAndroid Build Coastguard Worker typename PartialSignature, 23*6777b538SAndroid Build Coastguard Worker typename IgnoreSignature> 24*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackWrapper; 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker template <template <typename> typename CallbackType, 27*6777b538SAndroid Build Coastguard Worker typename R, 28*6777b538SAndroid Build Coastguard Worker typename... PartialArgs, 29*6777b538SAndroid Build Coastguard Worker typename... IgnoredArgs> 30*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackWrapper<CallbackType, 31*6777b538SAndroid Build Coastguard Worker R(PartialArgs...), 32*6777b538SAndroid Build Coastguard Worker void(IgnoredArgs...)> { 33*6777b538SAndroid Build Coastguard Worker template <typename Actual> 34*6777b538SAndroid Build Coastguard Worker static CallbackType<R(IgnoredArgs..., PartialArgs...)> Rectify( 35*6777b538SAndroid Build Coastguard Worker Actual&& callback) { 36*6777b538SAndroid Build Coastguard Worker if constexpr (is_instantiation<OnceCallback, CallbackType<void()>>) { 37*6777b538SAndroid Build Coastguard Worker return BindOnce( 38*6777b538SAndroid Build Coastguard Worker [](OnceCallback<R(PartialArgs...)> callback, IgnoredArgs..., 39*6777b538SAndroid Build Coastguard Worker PartialArgs... args) { 40*6777b538SAndroid Build Coastguard Worker return std::move(callback).Run(std::forward<PartialArgs>(args)...); 41*6777b538SAndroid Build Coastguard Worker }, 42*6777b538SAndroid Build Coastguard Worker std::forward<Actual>(callback)); 43*6777b538SAndroid Build Coastguard Worker } else { 44*6777b538SAndroid Build Coastguard Worker return BindRepeating( 45*6777b538SAndroid Build Coastguard Worker [](const RepeatingCallback<R(PartialArgs...)> callback, 46*6777b538SAndroid Build Coastguard Worker IgnoredArgs..., PartialArgs... args) { 47*6777b538SAndroid Build Coastguard Worker return callback.Run(std::forward<PartialArgs>(args)...); 48*6777b538SAndroid Build Coastguard Worker }, 49*6777b538SAndroid Build Coastguard Worker std::forward<Actual>(callback)); 50*6777b538SAndroid Build Coastguard Worker } 51*6777b538SAndroid Build Coastguard Worker } 52*6777b538SAndroid Build Coastguard Worker }; 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker // RectifyCallbackSplitter is a helper that returns the first N args of 55*6777b538SAndroid Build Coastguard Worker // `Signature` as the type `void(Args...)`. These are the arguments that need 56*6777b538SAndroid Build Coastguard Worker // to be ignored when rectifying a callback. 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker template <size_t count, typename Signature, typename Result = void()> 59*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackSplitter; 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker template <typename Arg, typename... Args, typename... Results> 62*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackSplitter<0, void(Arg, Args...), void(Results...)> { 63*6777b538SAndroid Build Coastguard Worker using type = void(Results...); 64*6777b538SAndroid Build Coastguard Worker }; 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker template <typename... Args, typename... Results> 67*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackSplitter<0, void(Args...), void(Results...)> { 68*6777b538SAndroid Build Coastguard Worker using type = void(Results...); 69*6777b538SAndroid Build Coastguard Worker }; 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Worker template <size_t count, typename Arg, typename... Args, typename... Results> 72*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackSplitter<count, void(Arg, Args...), void(Results...)> 73*6777b538SAndroid Build Coastguard Worker : RectifyCallbackSplitter<count - 1, void(Args...), void(Results..., Arg)> { 74*6777b538SAndroid Build Coastguard Worker }; 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker // Given a desired type and an actual type, RectifyCallbackImpl provides a 77*6777b538SAndroid Build Coastguard Worker // Rectify() method that adapts the input callback to be callable using the 78*6777b538SAndroid Build Coastguard Worker // arguments from desired type. 79*6777b538SAndroid Build Coastguard Worker 80*6777b538SAndroid Build Coastguard Worker template <typename DesiredType, typename ActualType, typename SFINAE = void> 81*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackImpl; 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker // Main specialization that handles the case where the desired and actual types 84*6777b538SAndroid Build Coastguard Worker // have already been normalized into callback types. The other specializations 85*6777b538SAndroid Build Coastguard Worker // allow additional flexibility for callers, but eventually all delegate here. 86*6777b538SAndroid Build Coastguard Worker template <template <typename> typename DesiredCallbackType, 87*6777b538SAndroid Build Coastguard Worker template <typename> 88*6777b538SAndroid Build Coastguard Worker typename ActualCallbackType, 89*6777b538SAndroid Build Coastguard Worker typename R, 90*6777b538SAndroid Build Coastguard Worker typename... DesiredArgs, 91*6777b538SAndroid Build Coastguard Worker typename... ActualArgs> 92*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackImpl<DesiredCallbackType<R(DesiredArgs...)>, 93*6777b538SAndroid Build Coastguard Worker ActualCallbackType<R(ActualArgs...)>> { 94*6777b538SAndroid Build Coastguard Worker static DesiredCallbackType<R(DesiredArgs...)> Rectify( 95*6777b538SAndroid Build Coastguard Worker ActualCallbackType<R(ActualArgs...)> callback) { 96*6777b538SAndroid Build Coastguard Worker if constexpr (std::is_same_v<R(DesiredArgs...), R(ActualArgs...)>) { 97*6777b538SAndroid Build Coastguard Worker // No adapting needed when the parameter lists already match. 98*6777b538SAndroid Build Coastguard Worker return callback; 99*6777b538SAndroid Build Coastguard Worker } 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker // For uniformity, if the input callback is null, the output callback should 102*6777b538SAndroid Build Coastguard Worker // be null as well. 103*6777b538SAndroid Build Coastguard Worker if (!callback) { 104*6777b538SAndroid Build Coastguard Worker return NullCallback(); 105*6777b538SAndroid Build Coastguard Worker } 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker using IgnoreSignature = 108*6777b538SAndroid Build Coastguard Worker typename RectifyCallbackSplitter<sizeof...(DesiredArgs) - 109*6777b538SAndroid Build Coastguard Worker sizeof...(ActualArgs), 110*6777b538SAndroid Build Coastguard Worker void(DesiredArgs...)>::type; 111*6777b538SAndroid Build Coastguard Worker return RectifyCallbackWrapper< 112*6777b538SAndroid Build Coastguard Worker DesiredCallbackType, R(ActualArgs...), 113*6777b538SAndroid Build Coastguard Worker IgnoreSignature>::Rectify(std::move(callback)); 114*6777b538SAndroid Build Coastguard Worker } 115*6777b538SAndroid Build Coastguard Worker }; 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker // Specialization that handles a type signature as the desired type. The output 118*6777b538SAndroid Build Coastguard Worker // in this case will be based on the type of callback passed in. 119*6777b538SAndroid Build Coastguard Worker template <typename R, 120*6777b538SAndroid Build Coastguard Worker typename... Args, 121*6777b538SAndroid Build Coastguard Worker template <typename> 122*6777b538SAndroid Build Coastguard Worker typename ActualCallbackType, 123*6777b538SAndroid Build Coastguard Worker typename ActualSignature> 124*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackImpl<R(Args...), ActualCallbackType<ActualSignature>> 125*6777b538SAndroid Build Coastguard Worker : RectifyCallbackImpl<ActualCallbackType<R(Args...)>, 126*6777b538SAndroid Build Coastguard Worker ActualCallbackType<ActualSignature>> {}; 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker // Fallback for things like DoNothing(), NullCallback(), etc. where a specific 129*6777b538SAndroid Build Coastguard Worker // callback return type is provided. 130*6777b538SAndroid Build Coastguard Worker template <template <typename> typename DesiredCallbackType, 131*6777b538SAndroid Build Coastguard Worker typename R, 132*6777b538SAndroid Build Coastguard Worker typename... Args, 133*6777b538SAndroid Build Coastguard Worker typename T> 134*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackImpl<DesiredCallbackType<R(Args...)>, T> 135*6777b538SAndroid Build Coastguard Worker : RectifyCallbackImpl<DesiredCallbackType<R(Args...)>, 136*6777b538SAndroid Build Coastguard Worker DesiredCallbackType<R(Args...)>> {}; 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker // Fallback for things like DoNothing(), NullCallback(), etc. where only the 139*6777b538SAndroid Build Coastguard Worker // signature of the return type is provided. In this case, `RepeatingCallback` 140*6777b538SAndroid Build Coastguard Worker // is implicitly generated, as it can be used as both a `OnceCallback` or 141*6777b538SAndroid Build Coastguard Worker // `RepeatingCallback`. 142*6777b538SAndroid Build Coastguard Worker template <typename R, typename... Args, typename T> 143*6777b538SAndroid Build Coastguard Worker struct RectifyCallbackImpl<R(Args...), T> 144*6777b538SAndroid Build Coastguard Worker : RectifyCallbackImpl<RepeatingCallback<R(Args...)>, 145*6777b538SAndroid Build Coastguard Worker RepeatingCallback<R(Args...)>> {}; 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker } // namespace base::internal 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker #endif // BASE_TEST_RECTIFY_CALLBACK_INTERNAL_H_ 150