| // Copyright 2023 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef LIBHWSEC_MIDDLEWARE_SUBCLASS_HELPER_H_ | |
| #define LIBHWSEC_MIDDLEWARE_SUBCLASS_HELPER_H_ | |
| #include <concepts> | |
| #include <type_traits> | |
| #include <utility> | |
| #include <base/functional/callback.h> | |
| #include <base/functional/callback_helpers.h> | |
| #include "libhwsec/status.h" | |
| #if USE_FUZZER | |
| #include "libhwsec/fuzzers/backend_command_list.h" | |
| #endif | |
| #ifndef BUILD_LIBHWSEC | |
| #error "Don't include this file outside libhwsec!" | |
| #endif | |
| namespace hwsec { | |
| // Type of the backend call. | |
| enum class CallType { | |
| // Synchronous backend call, and the function signature will be: | |
| // Result SubClass::Function(Args...); | |
| kSync, | |
| // Asynchronous backend call, and the function signature will be: | |
| // void SubClass::Function(base::OnceCallback<void(Result)>. Args...); | |
| kAsync, | |
| }; | |
| template <typename Func> | |
| struct SubClassHelper { | |
| static_assert(sizeof(Func) == -1, "Unknown member function"); | |
| }; | |
| // SubClass helper for the synchronous backend call. | |
| template <typename R, typename S, typename... Args> | |
| requires(std::constructible_from<R, Status>) | |
| struct SubClassHelper<R (S::*)(Args...)> { | |
| inline constexpr static CallType type = CallType::kSync; | |
| using Result = R; | |
| using SubClass = S; | |
| using Callback = base::OnceCallback<void(R)>; | |
| static R Signature(Args...); | |
| }; | |
| // SubClass helper for the asynchronous backend call. | |
| template <typename R, typename S, typename... Args> | |
| requires(std::constructible_from<R, Status>) | |
| struct SubClassHelper<void (S::*)(base::OnceCallback<void(R)>, Args...)> { | |
| inline constexpr static CallType type = CallType::kAsync; | |
| using Result = R; | |
| using SubClass = S; | |
| using Callback = base::OnceCallback<void(R)>; | |
| static R Signature(Args...); | |
| }; | |
| template <typename Func> | |
| using SubClassResult = typename SubClassHelper<Func>::Result; | |
| template <typename Func> | |
| using SubClassType = typename SubClassHelper<Func>::SubClass; | |
| template <typename Func> | |
| using SubClassCallback = typename SubClassHelper<Func>::Callback; | |
| template <typename Func> | |
| concept SyncBackendMethod = SubClassHelper<Func>::type == CallType::kSync; | |
| template <typename Func> | |
| concept AsyncBackendMethod = SubClassHelper<Func>::type == CallType::kAsync; | |
| #if USE_FUZZER | |
| // To save the build time in the normal build, we only do the fuzzed command | |
| // check in the fuzzer build. | |
| template <typename Func> | |
| concept BackendMethod = FuzzedBackendCommand<Func> && | |
| (SyncBackendMethod<Func> || AsyncBackendMethod<Func>); | |
| #else | |
| template <typename Func> | |
| concept BackendMethod = SyncBackendMethod<Func> || AsyncBackendMethod<Func>; | |
| #endif | |
| // The custom parameter forwarding rules. | |
| template <typename T> | |
| requires(!std::is_pointer_v<T>) | |
| static T ForwardParameter(T&& t) { | |
| // The rvalue should still be rvalue, because we have the ownership. | |
| return t; | |
| } | |
| template <typename T> | |
| requires(!std::is_pointer_v<T>) | |
| static const T& ForwardParameter(T& t) { | |
| // Add const for normal reference, because we don't have the ownership. | |
| // base::BindOnce will copy const reference parameter when binding. | |
| return t; | |
| } | |
| template <typename T> | |
| requires(!std::is_pointer_v<T>) | |
| static const T& ForwardParameter(const T& t) { | |
| // The const reference would still be const reference. | |
| // base::BindOnce will copy const reference parameter when binding. | |
| return t; | |
| } | |
| template <typename Func, typename... Args> | |
| concept ValidBackendMethodArgs = | |
| BackendMethod<Func> && requires(Args&&... args) { | |
| // Validate the function signature is callable with the forwarded | |
| // arguments. | |
| SubClassHelper<Func>::Signature( | |
| ForwardParameter(std::forward<Args>(args))...); | |
| }; | |
| } // namespace hwsec | |
| #endif // LIBHWSEC_MIDDLEWARE_SUBCLASS_HELPER_H_ |