mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
sf: alter serialization to re-use as much logic as possible
This commit is contained in:
parent
d2f81d2ca2
commit
4f7f37fae6
1 changed files with 35 additions and 23 deletions
|
@ -368,18 +368,11 @@ namespace ams::sf::impl {
|
||||||
size_t out_object_index;
|
size_t out_object_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<auto MemberFunction, typename Return, typename Class, typename... Arguments>
|
template<typename... Arguments>
|
||||||
struct CommandMetaInfo {
|
struct CommandMetaInfo {
|
||||||
public:
|
public:
|
||||||
using ReturnType = Return;
|
|
||||||
using ClassType = Class;
|
|
||||||
using ClassTypePointer = ClassType *;
|
|
||||||
using ArgsType = std::tuple<typename std::decay<Arguments>::type...>;
|
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 InDatas = TupleFilter<InDataFilter>::FilteredType<ArgsType>;
|
||||||
using OutDatas = TupleFilter<OutDataFilter>::FilteredType<ArgsType>;
|
using OutDatas = TupleFilter<OutDataFilter>::FilteredType<ArgsType>;
|
||||||
using Buffers = TupleFilter<BufferFilter>::FilteredType<ArgsType>;
|
using Buffers = TupleFilter<BufferFilter>::FilteredType<ArgsType>;
|
||||||
|
@ -1036,15 +1029,13 @@ namespace ams::sf::impl {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto ServiceCommandImpl, typename Return, typename ClassType, typename... Arguments>
|
template<typename CommandMeta, typename... Arguments>
|
||||||
constexpr Result InvokeServiceCommandImpl(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data) {
|
constexpr Result InvokeServiceCommandImplCommon(CmifOutHeader **out_header_ptr, cmif::ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, Result (*invoke_impl)(sf::IServiceObject *, Arguments &&...)) {
|
||||||
using CommandMeta = CommandMetaInfo<ServiceCommandImpl, Return, ClassType, Arguments...>;
|
|
||||||
using ImplProcessorType = HipcCommandProcessor<CommandMeta>;
|
using ImplProcessorType = HipcCommandProcessor<CommandMeta>;
|
||||||
using BufferArrayType = std::array<cmif::PointerAndSize, CommandMeta::NumBuffers>;
|
using BufferArrayType = std::array<cmif::PointerAndSize, CommandMeta::NumBuffers>;
|
||||||
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles>;
|
using OutHandleHolderType = OutHandleHolder<CommandMeta::NumOutMoveHandles, CommandMeta::NumOutCopyHandles>;
|
||||||
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign>;
|
using OutRawHolderType = OutRawHolder<CommandMeta::OutDataSize, CommandMeta::OutDataAlign>;
|
||||||
using InOutObjectHolderType = InOutObjectHolder<CommandMeta::NumInObjects, CommandMeta::NumOutObjects>;
|
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. */
|
/* Create a processor for us to work with. */
|
||||||
ImplProcessorType impl_processor;
|
ImplProcessorType impl_processor;
|
||||||
|
@ -1076,7 +1067,6 @@ namespace ams::sf::impl {
|
||||||
|
|
||||||
/* Decoding/Invocation. */
|
/* 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);
|
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. */
|
/* Handle in process ID holder if relevant. */
|
||||||
|
@ -1103,16 +1093,18 @@ namespace ams::sf::impl {
|
||||||
#undef _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID
|
#undef _SF_IMPL_PROCESSOR_MARSHAL_PROCESS_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (CommandMeta::ReturnsResult) {
|
using TrueArgumentsTuple = std::tuple<Arguments...>;
|
||||||
const auto command_result = std::apply([=](auto&&... args) { return (this_ptr->*ServiceCommandImpl)(std::forward<Arguments>(args)...); }, args_tuple);
|
|
||||||
if (R_FAILED(command_result)) {
|
sf::IServiceObject * const this_ptr = ctx.srv_obj;
|
||||||
cmif::PointerAndSize out_raw_data;
|
const auto command_result = [this_ptr, invoke_impl, &args_tuple]<size_t ...Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
ctx.processor->PrepareForErrorReply(ctx, out_raw_data, runtime_metadata);
|
return invoke_impl(this_ptr, std::forward<typename std::tuple_element<Ix, TrueArgumentsTuple>::type>(std::get<Ix>(args_tuple))...);
|
||||||
R_TRY(GetCmifOutHeaderPointer(out_header_ptr, out_raw_data));
|
}(std::make_index_sequence<std::tuple_size<typename CommandMeta::ArgsType>::value>());
|
||||||
return command_result;
|
|
||||||
}
|
if (R_FAILED(command_result)) {
|
||||||
} else {
|
cmif::PointerAndSize out_raw_data;
|
||||||
std::apply([=](auto&&... args) { (this_ptr->*ServiceCommandImpl)(std::forward<Arguments>(args)...); }, args_tuple);
|
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();
|
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 {
|
namespace ams::sf::impl {
|
||||||
|
|
Loading…
Reference in a new issue