mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-15 03:27:49 +01:00
sf: alter serialization to re-use as much logic as possible
This commit is contained in:
parent
d2f81d2ca2
commit
4f7f37fae6
@ -368,18 +368,11 @@ namespace ams::sf::impl {
|
||||
size_t out_object_index;
|
||||
};
|
||||
|
||||
template<auto MemberFunction, typename Return, typename Class, typename... Arguments>
|
||||
template<typename... Arguments>
|
||||
struct CommandMetaInfo {
|
||||
public:
|
||||
using ReturnType = Return;
|
||||
using ClassType = Class;
|
||||
using ClassTypePointer = ClassType *;
|
||||
using ArgsType = std::tuple<typename std::decay<Arguments>::type...>;
|
||||
|
||||
static constexpr bool ReturnsResult = std::is_same<ReturnType, Result>::value;
|
||||
static constexpr bool ReturnsVoid = std::is_same<ReturnType, void>::value;
|
||||
static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void.");
|
||||
|
||||
using InDatas = TupleFilter<InDataFilter>::FilteredType<ArgsType>;
|
||||
using OutDatas = TupleFilter<OutDataFilter>::FilteredType<ArgsType>;
|
||||
using Buffers = TupleFilter<BufferFilter>::FilteredType<ArgsType>;
|
||||
@ -1036,15 +1029,13 @@ namespace ams::sf::impl {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
||||
constexpr Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
||||
using CommandMeta = CommandMetaInfo<ServiceCommandImpl, Return, ClassType, Arguments...>;
|
||||
template<typename CommandMeta, typename... Arguments>
|
||||
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<CommandMeta>;
|
||||
using BufferArrayType = std::array<cmif::PointerAndSize, CommandMeta::NumBuffers>;
|
||||
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles>;
|
||||
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign>;
|
||||
using InOutObjectHolderType = InOutObjectHolder<CommandMeta::NumInObjects, CommandMeta::NumOutObjects>;
|
||||
static_assert(std::is_base_of<sf::IServiceObject, typename CommandMeta::ClassType>::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<typename CommandMeta::ClassTypePointer>(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,17 +1093,19 @@ 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<Arguments>(args)...); }, args_tuple);
|
||||
using TrueArgumentsTuple = std::tuple<Arguments...>;
|
||||
|
||||
sf::IServiceObject * const this_ptr = ctx.srv_obj;
|
||||
const auto command_result = [this_ptr, invoke_impl, &args_tuple]<size_t ...Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||
return invoke_impl(this_ptr, std::forward<typename std::tuple_element<Ix, TrueArgumentsTuple>::type>(std::get<Ix>(args_tuple))...);
|
||||
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsType>::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;
|
||||
}
|
||||
} else {
|
||||
std::apply([=](auto&&... args) { (this_ptr->*ServiceCommandImpl)(std::forward<Arguments>(args)...); }, args_tuple);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode. */
|
||||
@ -1137,6 +1129,26 @@ namespace ams::sf::impl {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
||||
constexpr Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
||||
using CommandMeta = CommandMetaInfo<Arguments...>;
|
||||
static_assert(std::is_base_of<sf::IServiceObject, ClassType>::value, "InvokeServiceCommandImpl: Service Commands must be ServiceObject member functions");
|
||||
|
||||
constexpr bool ReturnsResult = std::is_same<Return, Result>::value;
|
||||
constexpr bool ReturnsVoid = std::is_same<Return, void>::value;
|
||||
static_assert(ReturnsResult || ReturnsVoid, "Service Commands must return Result or void.");
|
||||
|
||||
|
||||
return InvokeServiceCommandImplCommon<CommandMeta, Arguments...>(out_header_ptr, ctx, in_raw_data, +[](sf::IServiceObject *srv_obj, Arguments &&... args) -> Result {
|
||||
if constexpr (ReturnsResult) {
|
||||
return (static_cast<ClassType *>(srv_obj)->*ServiceCommandImpl)(std::forward<Arguments>(args)...);
|
||||
} else {
|
||||
(static_cast<ClassType *>(srv_obj)->*ServiceCommandImpl)(std::forward<Arguments>(args)...);
|
||||
return ResultSuccess();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::sf::impl {
|
||||
|
Loading…
Reference in New Issue
Block a user