1*9356374aSAndroid Build Coastguard Worker // 2*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors. 3*9356374aSAndroid Build Coastguard Worker // 4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 7*9356374aSAndroid Build Coastguard Worker // 8*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 9*9356374aSAndroid Build Coastguard Worker // 10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 14*9356374aSAndroid Build Coastguard Worker // limitations under the License. 15*9356374aSAndroid Build Coastguard Worker // 16*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 17*9356374aSAndroid Build Coastguard Worker // File: bit_gen_ref.h 18*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 19*9356374aSAndroid Build Coastguard Worker // 20*9356374aSAndroid Build Coastguard Worker // This header defines a bit generator "reference" class, for use in interfaces 21*9356374aSAndroid Build Coastguard Worker // that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g. 22*9356374aSAndroid Build Coastguard Worker // `std::mt19937`) bit generators. 23*9356374aSAndroid Build Coastguard Worker 24*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_BIT_GEN_REF_H_ 25*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_BIT_GEN_REF_H_ 26*9356374aSAndroid Build Coastguard Worker 27*9356374aSAndroid Build Coastguard Worker #include <limits> 28*9356374aSAndroid Build Coastguard Worker #include <type_traits> 29*9356374aSAndroid Build Coastguard Worker #include <utility> 30*9356374aSAndroid Build Coastguard Worker 31*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h" 32*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/fast_type_id.h" 33*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h" 34*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 35*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/distribution_caller.h" 36*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/fast_uniform_bits.h" 37*9356374aSAndroid Build Coastguard Worker 38*9356374aSAndroid Build Coastguard Worker namespace absl { 39*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 40*9356374aSAndroid Build Coastguard Worker namespace random_internal { 41*9356374aSAndroid Build Coastguard Worker 42*9356374aSAndroid Build Coastguard Worker template <typename URBG, typename = void, typename = void, typename = void> 43*9356374aSAndroid Build Coastguard Worker struct is_urbg : std::false_type {}; 44*9356374aSAndroid Build Coastguard Worker 45*9356374aSAndroid Build Coastguard Worker template <typename URBG> 46*9356374aSAndroid Build Coastguard Worker struct is_urbg< 47*9356374aSAndroid Build Coastguard Worker URBG, 48*9356374aSAndroid Build Coastguard Worker absl::enable_if_t<std::is_same< 49*9356374aSAndroid Build Coastguard Worker typename URBG::result_type, 50*9356374aSAndroid Build Coastguard Worker typename std::decay<decltype((URBG::min)())>::type>::value>, 51*9356374aSAndroid Build Coastguard Worker absl::enable_if_t<std::is_same< 52*9356374aSAndroid Build Coastguard Worker typename URBG::result_type, 53*9356374aSAndroid Build Coastguard Worker typename std::decay<decltype((URBG::max)())>::type>::value>, 54*9356374aSAndroid Build Coastguard Worker absl::enable_if_t<std::is_same< 55*9356374aSAndroid Build Coastguard Worker typename URBG::result_type, 56*9356374aSAndroid Build Coastguard Worker typename std::decay<decltype(std::declval<URBG>()())>::type>::value>> 57*9356374aSAndroid Build Coastguard Worker : std::true_type {}; 58*9356374aSAndroid Build Coastguard Worker 59*9356374aSAndroid Build Coastguard Worker template <typename> 60*9356374aSAndroid Build Coastguard Worker struct DistributionCaller; 61*9356374aSAndroid Build Coastguard Worker class MockHelpers; 62*9356374aSAndroid Build Coastguard Worker 63*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 64*9356374aSAndroid Build Coastguard Worker 65*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 66*9356374aSAndroid Build Coastguard Worker // absl::BitGenRef 67*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 68*9356374aSAndroid Build Coastguard Worker // 69*9356374aSAndroid Build Coastguard Worker // `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic 70*9356374aSAndroid Build Coastguard Worker // non-owning "reference" interface for use in place of any specific uniform 71*9356374aSAndroid Build Coastguard Worker // random bit generator (URBG). This class may be used for both Abseil 72*9356374aSAndroid Build Coastguard Worker // (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g 73*9356374aSAndroid Build Coastguard Worker // `std::mt19937`, `std::minstd_rand`) bit generators. 74*9356374aSAndroid Build Coastguard Worker // 75*9356374aSAndroid Build Coastguard Worker // Like other reference classes, `absl::BitGenRef` does not own the 76*9356374aSAndroid Build Coastguard Worker // underlying bit generator, and the underlying instance must outlive the 77*9356374aSAndroid Build Coastguard Worker // `absl::BitGenRef`. 78*9356374aSAndroid Build Coastguard Worker // 79*9356374aSAndroid Build Coastguard Worker // `absl::BitGenRef` is particularly useful when used with an 80*9356374aSAndroid Build Coastguard Worker // `absl::MockingBitGen` to test specific paths in functions which use random 81*9356374aSAndroid Build Coastguard Worker // values. 82*9356374aSAndroid Build Coastguard Worker // 83*9356374aSAndroid Build Coastguard Worker // Example: 84*9356374aSAndroid Build Coastguard Worker // void TakesBitGenRef(absl::BitGenRef gen) { 85*9356374aSAndroid Build Coastguard Worker // int x = absl::Uniform<int>(gen, 0, 1000); 86*9356374aSAndroid Build Coastguard Worker // } 87*9356374aSAndroid Build Coastguard Worker // 88*9356374aSAndroid Build Coastguard Worker class BitGenRef { 89*9356374aSAndroid Build Coastguard Worker // SFINAE to detect whether the URBG type includes a member matching 90*9356374aSAndroid Build Coastguard Worker // bool InvokeMock(base_internal::FastTypeIdType, void*, void*). 91*9356374aSAndroid Build Coastguard Worker // 92*9356374aSAndroid Build Coastguard Worker // These live inside BitGenRef so that they have friend access 93*9356374aSAndroid Build Coastguard Worker // to MockingBitGen. (see similar methods in DistributionCaller). 94*9356374aSAndroid Build Coastguard Worker template <template <class...> class Trait, class AlwaysVoid, class... Args> 95*9356374aSAndroid Build Coastguard Worker struct detector : std::false_type {}; 96*9356374aSAndroid Build Coastguard Worker template <template <class...> class Trait, class... Args> 97*9356374aSAndroid Build Coastguard Worker struct detector<Trait, absl::void_t<Trait<Args...>>, Args...> 98*9356374aSAndroid Build Coastguard Worker : std::true_type {}; 99*9356374aSAndroid Build Coastguard Worker 100*9356374aSAndroid Build Coastguard Worker template <class T> 101*9356374aSAndroid Build Coastguard Worker using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock( 102*9356374aSAndroid Build Coastguard Worker std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(), 103*9356374aSAndroid Build Coastguard Worker std::declval<void*>())); 104*9356374aSAndroid Build Coastguard Worker 105*9356374aSAndroid Build Coastguard Worker template <typename T> 106*9356374aSAndroid Build Coastguard Worker using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type; 107*9356374aSAndroid Build Coastguard Worker 108*9356374aSAndroid Build Coastguard Worker public: 109*9356374aSAndroid Build Coastguard Worker BitGenRef(const BitGenRef&) = default; 110*9356374aSAndroid Build Coastguard Worker BitGenRef(BitGenRef&&) = default; 111*9356374aSAndroid Build Coastguard Worker BitGenRef& operator=(const BitGenRef&) = default; 112*9356374aSAndroid Build Coastguard Worker BitGenRef& operator=(BitGenRef&&) = default; 113*9356374aSAndroid Build Coastguard Worker 114*9356374aSAndroid Build Coastguard Worker template < 115*9356374aSAndroid Build Coastguard Worker typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>, 116*9356374aSAndroid Build Coastguard Worker typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value && 117*9356374aSAndroid Build Coastguard Worker random_internal::is_urbg<URBG>::value && 118*9356374aSAndroid Build Coastguard Worker !HasInvokeMock<URBG>::value)>* = nullptr> 119*9356374aSAndroid Build Coastguard Worker BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 120*9356374aSAndroid Build Coastguard Worker : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)), 121*9356374aSAndroid Build Coastguard Worker mock_call_(NotAMock), 122*9356374aSAndroid Build Coastguard Worker generate_impl_fn_(ImplFn<URBG>) {} 123*9356374aSAndroid Build Coastguard Worker 124*9356374aSAndroid Build Coastguard Worker template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>, 125*9356374aSAndroid Build Coastguard Worker typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value && 126*9356374aSAndroid Build Coastguard Worker random_internal::is_urbg<URBG>::value && 127*9356374aSAndroid Build Coastguard Worker HasInvokeMock<URBG>::value)>* = nullptr> 128*9356374aSAndroid Build Coastguard Worker BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 129*9356374aSAndroid Build Coastguard Worker : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)), 130*9356374aSAndroid Build Coastguard Worker mock_call_(&MockCall<URBG>), 131*9356374aSAndroid Build Coastguard Worker generate_impl_fn_(ImplFn<URBG>) {} 132*9356374aSAndroid Build Coastguard Worker 133*9356374aSAndroid Build Coastguard Worker using result_type = uint64_t; 134*9356374aSAndroid Build Coastguard Worker 135*9356374aSAndroid Build Coastguard Worker static constexpr result_type(min)() { 136*9356374aSAndroid Build Coastguard Worker return (std::numeric_limits<result_type>::min)(); 137*9356374aSAndroid Build Coastguard Worker } 138*9356374aSAndroid Build Coastguard Worker 139*9356374aSAndroid Build Coastguard Worker static constexpr result_type(max)() { 140*9356374aSAndroid Build Coastguard Worker return (std::numeric_limits<result_type>::max)(); 141*9356374aSAndroid Build Coastguard Worker } 142*9356374aSAndroid Build Coastguard Worker 143*9356374aSAndroid Build Coastguard Worker result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); } 144*9356374aSAndroid Build Coastguard Worker 145*9356374aSAndroid Build Coastguard Worker private: 146*9356374aSAndroid Build Coastguard Worker using impl_fn = result_type (*)(uintptr_t); 147*9356374aSAndroid Build Coastguard Worker using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*, 148*9356374aSAndroid Build Coastguard Worker void*); 149*9356374aSAndroid Build Coastguard Worker 150*9356374aSAndroid Build Coastguard Worker template <typename URBG> 151*9356374aSAndroid Build Coastguard Worker static result_type ImplFn(uintptr_t ptr) { 152*9356374aSAndroid Build Coastguard Worker // Ensure that the return values from operator() fill the entire 153*9356374aSAndroid Build Coastguard Worker // range promised by result_type, min() and max(). 154*9356374aSAndroid Build Coastguard Worker absl::random_internal::FastUniformBits<result_type> fast_uniform_bits; 155*9356374aSAndroid Build Coastguard Worker return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr)); 156*9356374aSAndroid Build Coastguard Worker } 157*9356374aSAndroid Build Coastguard Worker 158*9356374aSAndroid Build Coastguard Worker // Get a type-erased InvokeMock pointer. 159*9356374aSAndroid Build Coastguard Worker template <typename URBG> 160*9356374aSAndroid Build Coastguard Worker static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type, 161*9356374aSAndroid Build Coastguard Worker void* result, void* arg_tuple) { 162*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result, 163*9356374aSAndroid Build Coastguard Worker arg_tuple); 164*9356374aSAndroid Build Coastguard Worker } 165*9356374aSAndroid Build Coastguard Worker static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) { 166*9356374aSAndroid Build Coastguard Worker return false; 167*9356374aSAndroid Build Coastguard Worker } 168*9356374aSAndroid Build Coastguard Worker 169*9356374aSAndroid Build Coastguard Worker inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple, 170*9356374aSAndroid Build Coastguard Worker void* result) { 171*9356374aSAndroid Build Coastguard Worker if (mock_call_ == NotAMock) return false; // avoids an indirect call. 172*9356374aSAndroid Build Coastguard Worker return mock_call_(t_erased_gen_ptr_, type, args_tuple, result); 173*9356374aSAndroid Build Coastguard Worker } 174*9356374aSAndroid Build Coastguard Worker 175*9356374aSAndroid Build Coastguard Worker uintptr_t t_erased_gen_ptr_; 176*9356374aSAndroid Build Coastguard Worker mock_call_fn mock_call_; 177*9356374aSAndroid Build Coastguard Worker impl_fn generate_impl_fn_; 178*9356374aSAndroid Build Coastguard Worker 179*9356374aSAndroid Build Coastguard Worker template <typename> 180*9356374aSAndroid Build Coastguard Worker friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock 181*9356374aSAndroid Build Coastguard Worker friend class ::absl::random_internal::MockHelpers; // for InvokeMock 182*9356374aSAndroid Build Coastguard Worker }; 183*9356374aSAndroid Build Coastguard Worker 184*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 185*9356374aSAndroid Build Coastguard Worker } // namespace absl 186*9356374aSAndroid Build Coastguard Worker 187*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_BIT_GEN_REF_H_ 188