/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include namespace { namespace detail { template struct functionArgSaver; // Provides a std::function that takes one argument, and a buffer // wherein the function will store its argument. The buffer has // the same type as the argument, but with const and reference // modifiers removed. template struct functionArgSaver> final { using StorageT = typename std::remove_const< typename std::remove_reference::type>::type; std::function saveArgs = [this](ArgT arg) { this->saved_values = arg; }; StorageT saved_values; }; // Provides a std::function that takes two arguments, and a buffer // wherein the function will store its arguments. The buffer is a // std::pair, whose elements have the same types as the arguments // (but with const and reference modifiers removed). template struct functionArgSaver> final { using StorageT = std::pair::type>::type, typename std::remove_const< typename std::remove_reference::type>::type>; std::function saveArgs = [this](Arg1T arg1, Arg2T arg2) { this->saved_values = {arg1, arg2}; }; StorageT saved_values; }; // Provides a std::function that takes three or more arguments, and a // buffer wherein the function will store its arguments. The buffer is a // std::tuple whose elements have the same types as the arguments (but // with const and reference modifiers removed). template struct functionArgSaver> final { using StorageT = std::tuple::type>::type...>; std::function saveArgs = [this](ArgT... arg) { this->saved_values = {arg...}; }; StorageT saved_values; }; // Invokes |method| on |object|, providing |method| a CallbackT as the // final argument. Returns a copy of the parameters that |method| provided // to CallbackT. (The parameters are returned by value.) template typename functionArgSaver::StorageT invokeMethod( MethodT method, ObjectT object, ArgT&&... methodArg) { functionArgSaver result_buffer; const auto& res = ((*object).*method)(std::forward(methodArg)..., result_buffer.saveArgs); EXPECT_TRUE(res.isOk()); return result_buffer.saved_values; } } // namespace detail } // namespace // Invokes |method| on |strong_pointer|, passing provided arguments through to // |method|. // // Returns either: // - A copy of the result callback parameter (for callbacks with a single // parameter), OR // - A pair containing a copy of the result callback parameters (for callbacks // with two parameters), OR // - A tuple containing a copy of the result callback paramters (for callbacks // with three or more parameters). // // Example usage: // EXPECT_EQ(WifiStatusCode::SUCCESS, // HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code); // EXPECT_EQ(WifiStatusCode::SUCCESS, // HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore) // .first.code); // EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>( // HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore)) // .code); #define HIDL_INVOKE(strong_pointer, method, ...) \ (detail::invokeMethod< \ std::remove_reference::type::method##_cb>( \ &std::remove_reference::type::method, \ strong_pointer, ##__VA_ARGS__))