diff --git a/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_command_serialization.hpp b/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_command_serialization.hpp index aae4a5d2c..efce57035 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_command_serialization.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_command_serialization.hpp @@ -368,18 +368,11 @@ namespace ams::sf::impl { size_t out_object_index; }; - template + template struct CommandMetaInfo { public: - using ReturnType = Return; - using ClassType = Class; - using ClassTypePointer = ClassType *; using ArgsType = std::tuple::type...>; - static constexpr bool ReturnsResult = std::is_same::value; - static constexpr bool ReturnsVoid = std::is_same::value; - static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void."); - using InDatas = TupleFilter::FilteredType; using OutDatas = TupleFilter::FilteredType; using Buffers = TupleFilter::FilteredType; @@ -1036,15 +1029,13 @@ namespace ams::sf::impl { return ResultSuccess(); } - template - constexpr Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) { - using CommandMeta = CommandMetaInfo; + template + constexpr Result InvokeServiceCommandImplCommon(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, Result (*invoke_impl)(sf::IServiceObject *, Arguments &&...)) { using ImplProcessorType = HipcCommandProcessor; using BufferArrayType = std::array; using OutHandleHolderType = OutHandleHolder; using OutRawHolderType = OutRawHolder; using InOutObjectHolderType = InOutObjectHolder; - static_assert(std::is_base_of::value, "InvokeServiceCommandImpl: Service Commands must be ServiceObject member functions"); /* Create a processor for us to work with. */ ImplProcessorType impl_processor; @@ -1076,7 +1067,6 @@ namespace ams::sf::impl { /* Decoding/Invocation. */ { - typename CommandMeta::ClassTypePointer this_ptr = static_cast(ctx.srv_obj); typename CommandMeta::ArgsType args_tuple = ImplProcessorType::DeserializeArguments(ctx, in_raw_data, out_raw_holder, buffers, out_handles_holder, in_out_objects_holder); /* Handle in process ID holder if relevant. */ @@ -1103,16 +1093,18 @@ namespace ams::sf::impl { #undef _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID } - if constexpr (CommandMeta::ReturnsResult) { - const auto command_result = std::apply([=](auto&&... args) { return (this_ptr->*ServiceCommandImpl)(std::forward(args)...); }, args_tuple); - if (R_FAILED(command_result)) { - cmif::PointerAndSize out_raw_data; - ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata); - R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data)); - return command_result; - } - } else { - std::apply([=](auto&&... args) { (this_ptr->*ServiceCommandImpl)(std::forward(args)...); }, args_tuple); + using TrueArgumentsTuple = std::tuple; + + sf::IServiceObject * const this_ptr = ctx.srv_obj; + const auto command_result = [this_ptr, invoke_impl, &args_tuple](std::index_sequence) ALWAYS_INLINE_LAMBDA { + return invoke_impl(this_ptr, std::forward::type>(std::get(args_tuple))...); + }(std::make_index_sequence::value>()); + + if (R_FAILED(command_result)) { + cmif::PointerAndSize out_raw_data; + ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata); + R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data)); + return command_result; } } @@ -1137,6 +1129,26 @@ namespace ams::sf::impl { return ResultSuccess(); } + template + constexpr Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) { + using CommandMeta = CommandMetaInfo; + static_assert(std::is_base_of::value, "InvokeServiceCommandImpl: Service Commands must be ServiceObject member functions"); + + constexpr bool ReturnsResult = std::is_same::value; + constexpr bool ReturnsVoid = std::is_same::value; + static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void."); + + + return InvokeServiceCommandImplCommon(out_header_ptr, ctx, in_raw_data, +[](sf::IServiceObject *srv_obj, Arguments &&... args) -> Result { + if constexpr (ReturnsResult) { + return (static_cast(srv_obj)->*ServiceCommandImpl)(std::forward(args)...); + } else { + (static_cast(srv_obj)->*ServiceCommandImpl)(std::forward(args)...); + return ResultSuccess(); + } + }); + } + } namespace ams::sf::impl {