/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 #include namespace apache::thrift::detail { using ServiceInterceptorOnRequestStorage = util::TypeErasedValue<64, alignof(std::max_align_t)>; struct ServiceInterceptorRequestStorageContext { std::size_t count = 0; util::AllocationColocator<>::ArrayPtr onRequest = nullptr; }; using ServiceInterceptorOnConnectionStorage = util::TypeErasedValue<128, alignof(std::max_align_t)>; class ServiceInterceptorTypeErasedArgumentsVTable { public: virtual ~ServiceInterceptorTypeErasedArgumentsVTable() = default; virtual std::optional get( std::size_t index, const void* tuple) const noexcept = 0; }; template class ServiceInterceptorTypeErasedArgumentsVTableImpl; // This specialization is for methods with no arguments template <> class ServiceInterceptorTypeErasedArgumentsVTableImpl<> : public ServiceInterceptorTypeErasedArgumentsVTable { std::optional get( std::size_t, const void*) const noexcept override { return std::nullopt; } }; template class ServiceInterceptorTypeErasedArgumentsVTableImpl : public ServiceInterceptorTypeErasedArgumentsVTable { private: static_assert(sizeof...(Fields) > 0); using Tuple = std::tuple; using DynamicGetFunc = std::pair (*)(const Tuple&); // DynamicGetFuncTable allows mapping a runtime index into a table of // corresponding function pointers that call std::get and the // corresponding std::type_info at that index. // This mechanism allows type-erased (but type-checked) access to a list of // arguments at runtime. template > struct DynamicGetFuncTable; template struct DynamicGetFuncTable> { using TypeErasedResult = std::pair; template static TypeErasedResult getTypeErased(const Tuple& result) { return TypeErasedResult( static_cast(std::addressof(std::get(result))), typeid(std::tuple_element_t)); } static inline constexpr DynamicGetFunc dynamicGet[sizeof...(Indices)] = { &getTypeErased...}; }; std::optional get( std::size_t index, const void* tuple) const noexcept override { if (index < sizeof...(Fields)) { const auto& [ptr, typeInfo] = DynamicGetFuncTable<>::dynamicGet[index]( *reinterpret_cast(tuple)); return apache::thrift::util::TypeErasedRef::fromTypeInfoUnchecked( ptr, typeInfo); } return std::nullopt; } }; template inline const ServiceInterceptorTypeErasedArgumentsVTableImpl serviceInterceptorTypeErasedArgumentsVTableImpl; class ServiceInterceptorOnRequestArguments { public: template explicit ServiceInterceptorOnRequestArguments(std::tuple& args) : vtable_(&serviceInterceptorTypeErasedArgumentsVTableImpl), typeErasedArgs_(static_cast(std::addressof(args))), count_(sizeof...(Args)) {} ServiceInterceptorOnRequestArguments( const ServiceInterceptorOnRequestArguments&) = default; ServiceInterceptorOnRequestArguments& operator=( const ServiceInterceptorOnRequestArguments&) = default; std::size_t count() const { return count_; } std::optional get( std::size_t index) const { return vtable_->get(index, typeErasedArgs_); } private: const ServiceInterceptorTypeErasedArgumentsVTable* vtable_; const void* typeErasedArgs_; std::size_t count_; }; } // namespace apache::thrift::detail