tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

distribution_caller.h (3611B)


      1 //
      2 // Copyright 2018 The Abseil Authors.
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      https://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
     18 #define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
     19 
     20 #include <tuple>
     21 #include <type_traits>
     22 #include <utility>
     23 
     24 #include "absl/base/config.h"
     25 #include "absl/base/internal/fast_type_id.h"
     26 #include "absl/meta/type_traits.h"
     27 #include "absl/utility/utility.h"
     28 
     29 namespace absl {
     30 ABSL_NAMESPACE_BEGIN
     31 namespace random_internal {
     32 
     33 // DistributionCaller provides an opportunity to overload the general
     34 // mechanism for calling a distribution, allowing for mock-RNG classes
     35 // to intercept such calls.
     36 template <typename URBG>
     37 struct DistributionCaller {
     38  static_assert(!std::is_pointer<URBG>::value,
     39                "You must pass a reference, not a pointer.");
     40  // SFINAE to detect whether the URBG type includes a member matching
     41  // bool InvokeMock(key_id, args_tuple*, result*).
     42  //
     43  // These live inside BitGenRef so that they have friend access
     44  // to MockingBitGen. (see similar methods in DistributionCaller).
     45  template <template <class...> class Trait, class AlwaysVoid, class... Args>
     46  struct detector : std::false_type {};
     47  template <template <class...> class Trait, class... Args>
     48  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
     49      : std::true_type {};
     50 
     51  template <class T>
     52  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
     53      std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
     54      std::declval<void*>()));
     55 
     56  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
     57 
     58  // Default implementation of distribution caller.
     59  template <typename DistrT, typename... Args>
     60  static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
     61                                           Args&&... args) {
     62    DistrT dist(std::forward<Args>(args)...);
     63    return dist(*urbg);
     64  }
     65 
     66  // Mock implementation of distribution caller.
     67  // The underlying KeyT must match the KeyT constructed by MockOverloadSet.
     68  template <typename DistrT, typename... Args>
     69  static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
     70                                           Args&&... args) {
     71    using ResultT = typename DistrT::result_type;
     72    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
     73    using KeyT = ResultT(DistrT, ArgTupleT);
     74 
     75    ArgTupleT arg_tuple(std::forward<Args>(args)...);
     76    ResultT result;
     77    if (!urbg->InvokeMock(base_internal::FastTypeId<KeyT>(), &arg_tuple,
     78                          &result)) {
     79      auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
     80      result = dist(*urbg);
     81    }
     82    return result;
     83  }
     84 
     85  // Default implementation of distribution caller.
     86  template <typename DistrT, typename... Args>
     87  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
     88    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
     89                                 std::forward<Args>(args)...);
     90  }
     91 };
     92 
     93 }  // namespace random_internal
     94 ABSL_NAMESPACE_END
     95 }  // namespace absl
     96 
     97 #endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_