xref: /aosp_15_r20/external/cronet/base/test/rectify_callback_internal.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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