Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/sandbox/chromium/base/bind.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef BASE_BIND_H_
6
#define BASE_BIND_H_
7
8
#include "base/bind_internal.h"
9
10
// -----------------------------------------------------------------------------
11
// Usage documentation
12
// -----------------------------------------------------------------------------
13
//
14
// See //docs/callback.md for documentation.
15
//
16
//
17
// -----------------------------------------------------------------------------
18
// Implementation notes
19
// -----------------------------------------------------------------------------
20
//
21
// If you're reading the implementation, before proceeding further, you should
22
// read the top comment of base/bind_internal.h for a definition of common
23
// terms and concepts.
24
25
namespace base {
26
27
namespace internal {
28
29
// IsOnceCallback<T> is a std::true_type if |T| is a OnceCallback.
30
template <typename T>
31
struct IsOnceCallback : std::false_type {};
32
33
template <typename Signature>
34
struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {};
35
36
// Helper to assert that parameter |i| of type |Arg| can be bound, which means:
37
// - |Arg| can be retained internally as |Storage|.
38
// - |Arg| can be forwarded as |Unwrapped| to |Param|.
39
template <size_t i,
40
          typename Arg,
41
          typename Storage,
42
          typename Unwrapped,
43
          typename Param>
44
struct AssertConstructible {
45
 private:
46
  static constexpr bool param_is_forwardable =
47
      std::is_constructible<Param, Unwrapped>::value;
48
  // Unlike the check for binding into storage below, the check for
49
  // forwardability drops the const qualifier for repeating callbacks. This is
50
  // to try to catch instances where std::move()--which forwards as a const
51
  // reference with repeating callbacks--is used instead of base::Passed().
52
  static_assert(
53
      param_is_forwardable ||
54
          !std::is_constructible<Param, typename std::decay<Unwrapped>::type&&>::value,
55
      "Bound argument |i| is move-only but will be forwarded by copy. "
56
      "Ensure |Arg| is bound using base::Passed(), not std::move().");
57
  static_assert(
58
      param_is_forwardable,
59
      "Bound argument |i| of type |Arg| cannot be forwarded as "
60
      "|Unwrapped| to the bound functor, which declares it as |Param|.");
61
62
  static constexpr bool arg_is_storable =
63
      std::is_constructible<Storage, Arg>::value;
64
  static_assert(arg_is_storable ||
65
                    !std::is_constructible<Storage, typename std::decay<Arg>::type&&>::value,
66
                "Bound argument |i| is move-only but will be bound by copy. "
67
                "Ensure |Arg| is mutable and bound using std::move().");
68
  static_assert(arg_is_storable,
69
                "Bound argument |i| of type |Arg| cannot be converted and "
70
                "bound as |Storage|.");
71
};
72
73
// Takes three same-length TypeLists, and applies AssertConstructible for each
74
// triples.
75
template <typename Index,
76
          typename Args,
77
          typename UnwrappedTypeList,
78
          typename ParamsList>
79
struct AssertBindArgsValidity;
80
81
template <size_t... Ns,
82
          typename... Args,
83
          typename... Unwrapped,
84
          typename... Params>
85
struct AssertBindArgsValidity<IndexSequence<Ns...>,
86
                              TypeList<Args...>,
87
                              TypeList<Unwrapped...>,
88
                              TypeList<Params...>>
89
    : AssertConstructible<Ns, Args, typename std::decay<Args>::type, Unwrapped, Params>... {
90
  static constexpr bool ok = true;
91
};
92
93
// The implementation of TransformToUnwrappedType below.
94
template <bool is_once, typename T>
95
struct TransformToUnwrappedTypeImpl;
96
97
template <typename T>
98
struct TransformToUnwrappedTypeImpl<true, T> {
99
  using StoredType = typename std::decay<T>::type;
100
  using ForwardType = StoredType&&;
101
  using Unwrapped = decltype(Unwrap(std::declval<ForwardType>()));
102
};
103
104
template <typename T>
105
struct TransformToUnwrappedTypeImpl<false, T> {
106
  using StoredType = typename std::decay<T>::type;
107
  using ForwardType = const StoredType&;
108
  using Unwrapped = decltype(Unwrap(std::declval<ForwardType>()));
109
};
110
111
// Transform |T| into `Unwrapped` type, which is passed to the target function.
112
// Example:
113
//   In is_once == true case,
114
//     `int&&` -> `int&&`,
115
//     `const int&` -> `int&&`,
116
//     `OwnedWrapper<int>&` -> `int*&&`.
117
//   In is_once == false case,
118
//     `int&&` -> `const int&`,
119
//     `const int&` -> `const int&`,
120
//     `OwnedWrapper<int>&` -> `int* const &`.
121
template <bool is_once, typename T>
122
using TransformToUnwrappedType =
123
    typename TransformToUnwrappedTypeImpl<is_once, T>::Unwrapped;
124
125
// Transforms |Args| into `Unwrapped` types, and packs them into a TypeList.
126
// If |is_method| is true, tries to dereference the first argument to support
127
// smart pointers.
128
template <bool is_once, bool is_method, typename... Args>
129
struct MakeUnwrappedTypeListImpl {
130
  using Type = TypeList<TransformToUnwrappedType<is_once, Args>...>;
131
};
132
133
// Performs special handling for this pointers.
134
// Example:
135
//   int* -> int*,
136
//   std::unique_ptr<int> -> int*.
137
template <bool is_once, typename Receiver, typename... Args>
138
struct MakeUnwrappedTypeListImpl<is_once, true, Receiver, Args...> {
139
  using UnwrappedReceiver = TransformToUnwrappedType<is_once, Receiver>;
140
  using Type = TypeList<decltype(&*std::declval<UnwrappedReceiver>()),
141
                        TransformToUnwrappedType<is_once, Args>...>;
142
};
143
144
template <bool is_once, bool is_method, typename... Args>
145
using MakeUnwrappedTypeList =
146
    typename MakeUnwrappedTypeListImpl<is_once, is_method, Args...>::Type;
147
148
}  // namespace internal
149
150
// Bind as OnceCallback.
151
template <typename Functor, typename... Args>
152
inline OnceCallback<MakeUnboundRunType<Functor, Args...>>
153
BindOnce(Functor&& functor, Args&&... args) {
154
  static_assert(
155
      !internal::IsOnceCallback<typename std::decay<Functor>::type>() ||
156
          (std::is_rvalue_reference<Functor&&>() &&
157
           !std::is_const<typename std::remove_reference<Functor>::type>()),
158
      "BindOnce requires non-const rvalue for OnceCallback binding."
159
      " I.e.: base::BindOnce(std::move(callback)).");
160
161
  // This block checks if each |args| matches to the corresponding params of the
162
  // target function. This check does not affect the behavior of Bind, but its
163
  // error message should be more readable.
164
  using Helper = internal::BindTypeHelper<Functor, Args...>;
165
  using FunctorTraits = typename Helper::FunctorTraits;
166
  using BoundArgsList = typename Helper::BoundArgsList;
167
  using UnwrappedArgsList =
168
      internal::MakeUnwrappedTypeList<true, FunctorTraits::is_method,
169
                                      Args&&...>;
170
  using BoundParamsList = typename Helper::BoundParamsList;
171
  static_assert(internal::AssertBindArgsValidity<
172
                    MakeIndexSequence<Helper::num_bounds>, BoundArgsList,
173
                    UnwrappedArgsList, BoundParamsList>::ok,
174
                "The bound args need to be convertible to the target params.");
175
176
  using BindState = internal::MakeBindStateType<Functor, Args...>;
177
  using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
178
  using Invoker = internal::Invoker<BindState, UnboundRunType>;
179
  using CallbackType = OnceCallback<UnboundRunType>;
180
181
  // Store the invoke func into PolymorphicInvoke before casting it to
182
  // InvokeFuncStorage, so that we can ensure its type matches to
183
  // PolymorphicInvoke, to which CallbackType will cast back.
184
  using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
185
  PolymorphicInvoke invoke_func = &Invoker::RunOnce;
186
187
  using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage;
188
  return CallbackType(new BindState(
189
      reinterpret_cast<InvokeFuncStorage>(invoke_func),
190
      std::forward<Functor>(functor),
191
      std::forward<Args>(args)...));
192
}
193
194
// Bind as RepeatingCallback.
195
template <typename Functor, typename... Args>
196
inline RepeatingCallback<MakeUnboundRunType<Functor, Args...>>
197
0
BindRepeating(Functor&& functor, Args&&... args) {
198
0
  static_assert(
199
0
      !internal::IsOnceCallback<typename std::decay<Functor>::type>(),
200
0
      "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move().");
201
0
202
0
  // This block checks if each |args| matches to the corresponding params of the
203
0
  // target function. This check does not affect the behavior of Bind, but its
204
0
  // error message should be more readable.
205
0
  using Helper = internal::BindTypeHelper<Functor, Args...>;
206
0
  using FunctorTraits = typename Helper::FunctorTraits;
207
0
  using BoundArgsList = typename Helper::BoundArgsList;
208
0
  using UnwrappedArgsList =
209
0
      internal::MakeUnwrappedTypeList<false, FunctorTraits::is_method,
210
0
                                      Args&&...>;
211
0
  using BoundParamsList = typename Helper::BoundParamsList;
212
0
  static_assert(internal::AssertBindArgsValidity<
213
0
                    MakeIndexSequence<Helper::num_bounds>, BoundArgsList,
214
0
                    UnwrappedArgsList, BoundParamsList>::ok,
215
0
                "The bound args need to be convertible to the target params.");
216
0
217
0
  using BindState = internal::MakeBindStateType<Functor, Args...>;
218
0
  using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
219
0
  using Invoker = internal::Invoker<BindState, UnboundRunType>;
220
0
  using CallbackType = RepeatingCallback<UnboundRunType>;
221
0
222
0
  // Store the invoke func into PolymorphicInvoke before casting it to
223
0
  // InvokeFuncStorage, so that we can ensure its type matches to
224
0
  // PolymorphicInvoke, to which CallbackType will cast back.
225
0
  using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
226
0
  PolymorphicInvoke invoke_func = &Invoker::Run;
227
0
228
0
  using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage;
229
0
  return CallbackType(new BindState(
230
0
      reinterpret_cast<InvokeFuncStorage>(invoke_func),
231
0
      std::forward<Functor>(functor),
232
0
      std::forward<Args>(args)...));
233
0
}
234
235
// Unannotated Bind.
236
// TODO(tzik): Deprecate this and migrate to OnceCallback and
237
// RepeatingCallback, once they get ready.
238
template <typename Functor, typename... Args>
239
inline Callback<MakeUnboundRunType<Functor, Args...>>
240
0
Bind(Functor&& functor, Args&&... args) {
241
0
  return BindRepeating(std::forward<Functor>(functor),
242
0
                       std::forward<Args>(args)...);
243
0
}
244
245
// Special cases for binding to a base::Callback without extra bound arguments.
246
template <typename Signature>
247
OnceCallback<Signature> BindOnce(OnceCallback<Signature> closure) {
248
  return closure;
249
}
250
251
template <typename Signature>
252
RepeatingCallback<Signature> BindRepeating(
253
    RepeatingCallback<Signature> closure) {
254
  return closure;
255
}
256
257
template <typename Signature>
258
Callback<Signature> Bind(Callback<Signature> closure) {
259
  return closure;
260
}
261
262
}  // namespace base
263
264
#endif  // BASE_BIND_H_