27#ifndef SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ 
   28#define SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ 
   48    inline MethodRegistrator::MethodRegistrator(IObject& 
object, std::string methodName)
 
   50        , methodName_(std::move(methodName))
 
   51        , exceptions_(std::uncaught_exceptions())
 
   55    inline MethodRegistrator::~MethodRegistrator() noexcept(false) 
 
   58        if (std::uncaught_exceptions() != exceptions_)
 
   61        assert(!interfaceName_.empty()); 
 
   62        assert(methodCallback_); 
 
   73        object_.registerMethod( interfaceName_
 
   74                              , std::move(methodName_)
 
   75                              , std::move(inputSignature_)
 
   77                              , std::move(outputSignature_)
 
   79                              , std::move(methodCallback_)
 
   83    inline MethodRegistrator& MethodRegistrator::onInterface(std::string interfaceName)
 
   85        interfaceName_ = std::move(interfaceName);
 
   90    template <
typename _Function>
 
   91    MethodRegistrator& MethodRegistrator::implementedAs(_Function&& callback)
 
   93        inputSignature_ = signature_of_function_input_arguments<_Function>::str();
 
   94        outputSignature_ = signature_of_function_output_arguments<_Function>::str();
 
   95        methodCallback_ = [callback = std::forward<_Function>(callback)](MethodCall call)
 
   99            tuple_of_function_input_arg_types_t<_Function> inputArgs;
 
  104            if constexpr (!is_async_method_v<_Function>)
 
  107                auto ret = sdbus::apply(callback, inputArgs);
 
  110                auto reply = call.createReply();
 
  117                using AsyncResult = 
typename function_traits<_Function>::async_result_t;
 
  118                sdbus::apply(callback, AsyncResult{std::move(call)}, std::move(inputArgs));
 
  125    inline MethodRegistrator& MethodRegistrator::withInputParamNames(std::vector<std::string> paramNames)
 
  127        inputParamNames_ = std::move(paramNames);
 
  132    template <
typename... _String>
 
  133    inline MethodRegistrator& MethodRegistrator::withInputParamNames(_String... paramNames)
 
  135        static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, 
"Parameter names must be (convertible to) strings");
 
  137        return withInputParamNames({paramNames...});
 
  140    inline MethodRegistrator& MethodRegistrator::withOutputParamNames(std::vector<std::string> paramNames)
 
  142        outputParamNames_ = std::move(paramNames);
 
  147    template <
typename... _String>
 
  148    inline MethodRegistrator& MethodRegistrator::withOutputParamNames(_String... paramNames)
 
  150        static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, 
"Parameter names must be (convertible to) strings");
 
  152        return withOutputParamNames({paramNames...});
 
  155    inline MethodRegistrator& MethodRegistrator::markAsDeprecated()
 
  157        flags_.set(Flags::DEPRECATED);
 
  162    inline MethodRegistrator& MethodRegistrator::markAsPrivileged()
 
  164        flags_.set(Flags::PRIVILEGED);
 
  169    inline MethodRegistrator& MethodRegistrator::withNoReply()
 
  171        flags_.set(Flags::METHOD_NO_REPLY);
 
  180    inline SignalRegistrator::SignalRegistrator(IObject& 
object, std::string signalName)
 
  182        , signalName_(std::move(signalName))
 
  183        , exceptions_(std::uncaught_exceptions())
 
  187    inline SignalRegistrator::~SignalRegistrator() noexcept(false) 
 
  190        if (std::uncaught_exceptions() != exceptions_)
 
  193        assert(!interfaceName_.empty()); 
 
  204        object_.registerSignal( interfaceName_
 
  205                              , std::move(signalName_)
 
  206                              , std::move(signalSignature_)
 
  208                              , std::move(flags_) );
 
  211    inline SignalRegistrator& SignalRegistrator::onInterface(std::string interfaceName)
 
  213        interfaceName_ = std::move(interfaceName);
 
  218    template <
typename... _Args>
 
  219    inline SignalRegistrator& SignalRegistrator::withParameters()
 
  221        signalSignature_ = signature_of_function_input_arguments<void(_Args...)>::str();
 
  226    template <
typename... _Args>
 
  227    inline SignalRegistrator& SignalRegistrator::withParameters(std::vector<std::string> paramNames)
 
  229        paramNames_ = std::move(paramNames);
 
  231        return withParameters<_Args...>();
 
  234    template <
typename... _Args, 
typename... _String>
 
  235    inline SignalRegistrator& SignalRegistrator::withParameters(_String... paramNames)
 
  237        static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, 
"Parameter names must be (convertible to) strings");
 
  238        static_assert(
sizeof...(_Args) == 
sizeof...(_String), 
"Numbers of signal parameters and their names don't match");
 
  240        return withParameters<_Args...>({paramNames...});
 
  243    inline SignalRegistrator& SignalRegistrator::markAsDeprecated()
 
  245        flags_.set(Flags::DEPRECATED);
 
  254    inline PropertyRegistrator::PropertyRegistrator(IObject& 
object, 
const std::string& propertyName)
 
  256        , propertyName_(propertyName)
 
  257        , exceptions_(std::uncaught_exceptions())
 
  261    inline PropertyRegistrator::~PropertyRegistrator() noexcept(false) 
 
  264        if (std::uncaught_exceptions() != exceptions_)
 
  267        assert(!interfaceName_.empty()); 
 
  278        object_.registerProperty( interfaceName_
 
  286    inline PropertyRegistrator& PropertyRegistrator::onInterface(std::string interfaceName)
 
  288        interfaceName_ = std::move(interfaceName);
 
  293    template <
typename _Function>
 
  294    inline PropertyRegistrator& PropertyRegistrator::withGetter(_Function&& callback)
 
  296        static_assert(function_argument_count_v<_Function> == 0, 
"Property getter function must not take any arguments");
 
  297        static_assert(!std::is_void<function_result_t<_Function>>::value, 
"Property getter function must return property value");
 
  299        if (propertySignature_.empty())
 
  300            propertySignature_ = signature_of_function_output_arguments<_Function>::str();
 
  302        getter_ = [callback = std::forward<_Function>(callback)](PropertyGetReply& reply)
 
  311    template <
typename _Function>
 
  312    inline PropertyRegistrator& PropertyRegistrator::withSetter(_Function&& callback)
 
  314        static_assert(function_argument_count_v<_Function> == 1, 
"Property setter function must take one parameter - the property value");
 
  315        static_assert(std::is_void<function_result_t<_Function>>::value, 
"Property setter function must not return any value");
 
  317        if (propertySignature_.empty())
 
  318            propertySignature_ = signature_of_function_input_arguments<_Function>::str();
 
  320        setter_ = [callback = std::forward<_Function>(callback)](PropertySetCall& call)
 
  323            using property_type = function_argument_t<_Function, 0>;
 
  324            std::decay_t<property_type> property;
 
  336    inline PropertyRegistrator& PropertyRegistrator::markAsDeprecated()
 
  338        flags_.set(Flags::DEPRECATED);
 
  343    inline PropertyRegistrator& PropertyRegistrator::markAsPrivileged()
 
  345        flags_.set(Flags::PRIVILEGED);
 
  350    inline PropertyRegistrator& PropertyRegistrator::withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior)
 
  352        flags_.set(behavior);
 
  361    inline InterfaceFlagsSetter::InterfaceFlagsSetter(IObject& 
object, 
const std::string& interfaceName)
 
  363        , interfaceName_(interfaceName)
 
  364        , exceptions_(std::uncaught_exceptions())
 
  368    inline InterfaceFlagsSetter::~InterfaceFlagsSetter() noexcept(false) 
 
  371        if (std::uncaught_exceptions() != exceptions_)
 
  383        object_.setInterfaceFlags(interfaceName_, std::move(flags_));
 
  386    inline InterfaceFlagsSetter& InterfaceFlagsSetter::markAsDeprecated()
 
  388        flags_.set(Flags::DEPRECATED);
 
  393    inline InterfaceFlagsSetter& InterfaceFlagsSetter::markAsPrivileged()
 
  395        flags_.set(Flags::PRIVILEGED);
 
  400    inline InterfaceFlagsSetter& InterfaceFlagsSetter::withNoReplyMethods()
 
  402        flags_.set(Flags::METHOD_NO_REPLY);
 
  407    inline InterfaceFlagsSetter& InterfaceFlagsSetter::withPropertyUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior)
 
  409        flags_.set(behavior);
 
  418    inline SignalEmitter::SignalEmitter(IObject& 
object, 
const std::string& signalName)
 
  420        , signalName_(signalName)
 
  421        , exceptions_(std::uncaught_exceptions())
 
  425    inline SignalEmitter::~SignalEmitter() noexcept(false) 
 
  428        if (std::uncaught_exceptions() != exceptions_)
 
  440        object_.emitSignal(signal_);
 
  443    inline SignalEmitter& SignalEmitter::onInterface(
const std::string& interfaceName)
 
  445        signal_ = object_.createSignal(interfaceName, signalName_);
 
  450    template <
typename... _Args>
 
  451    inline void SignalEmitter::withArguments(_Args&&... args)
 
  453        assert(signal_.isValid()); 
 
  455        detail::serialize_pack(signal_, std::forward<_Args>(args)...);
 
  462    inline MethodInvoker::MethodInvoker(IProxy& proxy, 
const std::string& methodName)
 
  464        , methodName_(methodName)
 
  465        , exceptions_(std::uncaught_exceptions())
 
  469    inline MethodInvoker::~MethodInvoker() noexcept(false) 
 
  473        if (methodCalled_ || std::uncaught_exceptions() != exceptions_)
 
  485        proxy_.callMethod(method_, timeout_);
 
  488    inline MethodInvoker& MethodInvoker::onInterface(
const std::string& interfaceName)
 
  490        method_ = proxy_.createMethodCall(interfaceName, methodName_);
 
  495    inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec)
 
  502    template <
typename _Rep, 
typename _Period>
 
  503    inline MethodInvoker& MethodInvoker::withTimeout(
const std::chrono::duration<_Rep, _Period>& timeout)
 
  505        auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
 
  506        return withTimeout(microsecs.count());
 
  509    template <
typename... _Args>
 
  510    inline MethodInvoker& MethodInvoker::withArguments(_Args&&... args)
 
  512        assert(method_.isValid()); 
 
  514        detail::serialize_pack(method_, std::forward<_Args>(args)...);
 
  519    template <
typename... _Args>
 
  520    inline void MethodInvoker::storeResultsTo(_Args&... args)
 
  522        assert(method_.isValid()); 
 
  524        auto reply = proxy_.callMethod(method_, timeout_);
 
  525        methodCalled_ = 
true;
 
  527        detail::deserialize_pack(reply, args...);
 
  530    inline void MethodInvoker::dontExpectReply()
 
  532        assert(method_.isValid()); 
 
  534        method_.dontExpectReply();
 
  541    inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, 
const std::string& methodName)
 
  543        , methodName_(methodName)
 
  547    inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(
const std::string& interfaceName)
 
  549        method_ = proxy_.createMethodCall(interfaceName, methodName_);
 
  554    inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec)
 
  561    template <
typename _Rep, 
typename _Period>
 
  562    inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(
const std::chrono::duration<_Rep, _Period>& timeout)
 
  564        auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
 
  565        return withTimeout(microsecs.count());
 
  568    template <
typename... _Args>
 
  569    inline AsyncMethodInvoker& AsyncMethodInvoker::withArguments(_Args&&... args)
 
  571        assert(method_.isValid()); 
 
  573        detail::serialize_pack(method_, std::forward<_Args>(args)...);
 
  578    template <
typename _Function>
 
  579    PendingAsyncCall AsyncMethodInvoker::uponReplyInvoke(_Function&& callback)
 
  581        assert(method_.isValid()); 
 
  583        auto asyncReplyHandler = [callback = std::forward<_Function>(callback)](MethodReply& reply, 
const Error* error)
 
  587            tuple_of_function_input_arg_types_t<_Function> args;
 
  590            if (error == 
nullptr)
 
  596                catch (
const Error& e)
 
  601                    sdbus::apply(callback, &e, args);
 
  607            sdbus::apply(callback, error, args);
 
  610        return proxy_.callMethod(method_, std::move(asyncReplyHandler), timeout_);
 
  613    template <
typename... _Args>
 
  614    std::future<future_return_t<_Args...>> AsyncMethodInvoker::getResultAsFuture()
 
  616        auto promise = std::make_shared<std::promise<future_return_t<_Args...>>>();
 
  617        auto future = promise->get_future();
 
  619        uponReplyInvoke([promise = std::move(promise)](
const Error* error, _Args... args)
 
  621            if (error == nullptr)
 
  622                if constexpr (!std::is_void_v<future_return_t<_Args...>>)
 
  623                    promise->set_value({std::move(args)...});
 
  625                    promise->set_value();
 
  627                promise->set_exception(std::make_exception_ptr(*error));
 
  640    inline SignalSubscriber::SignalSubscriber(IProxy& proxy, 
const std::string& signalName)
 
  642        , signalName_(signalName)
 
  646    inline SignalSubscriber& SignalSubscriber::onInterface(std::string interfaceName)
 
  648        interfaceName_ = std::move(interfaceName);
 
  653    template <
typename _Function>
 
  654    inline void SignalSubscriber::call(_Function&& callback)
 
  656        assert(!interfaceName_.empty()); 
 
  658        proxy_.registerSignalHandler( interfaceName_
 
  660                                    , [callback = std::forward<_Function>(callback)](Signal& signal)
 
  664            tuple_of_function_input_arg_types_t<_Function> signalArgs;
 
  670            if constexpr (has_error_param_v<_Function>)
 
  675                    signal >> signalArgs;
 
  680                    sdbus::apply(callback, &e, signalArgs);
 
  684                sdbus::apply(callback, 
nullptr, signalArgs);
 
  689                signal >> signalArgs;
 
  692                sdbus::apply(callback, signalArgs);
 
  701    inline SignalUnsubscriber::SignalUnsubscriber(IProxy& proxy, 
const std::string& signalName)
 
  703        , signalName_(signalName)
 
  707    inline void SignalUnsubscriber::onInterface(
const std::string& interfaceName)
 
  709        proxy_.unregisterSignalHandler(interfaceName, signalName_);
 
  716    inline PropertyGetter::PropertyGetter(IProxy& proxy, 
const std::string& propertyName)
 
  718        , propertyName_(propertyName)
 
  722    inline Variant PropertyGetter::onInterface(
const std::string& interfaceName)
 
  725        proxy_.callMethod(
"Get")
 
  726              .onInterface(
"org.freedesktop.DBus.Properties")
 
  727              .withArguments(interfaceName, propertyName_)
 
  728              .storeResultsTo(var);
 
  736    inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, 
const std::string& propertyName)
 
  738            , propertyName_(propertyName)
 
  742    inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(
const std::string& interfaceName)
 
  744        interfaceName_ = &interfaceName;
 
  749    template <
typename _Function>
 
  750    PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(_Function&& callback)
 
  752        static_assert(std::is_invocable_r_v<void, _Function, const Error*, Variant>, 
"Property get callback function must accept Error* and property value as Variant");
 
  754        assert(interfaceName_ != 
nullptr); 
 
  756        return proxy_.callMethodAsync(
"Get")
 
  757                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  758                     .withArguments(*interfaceName_, propertyName_)
 
  759                     .uponReplyInvoke(std::forward<_Function>(callback));
 
  762    inline std::future<Variant> AsyncPropertyGetter::getResultAsFuture()
 
  764        assert(interfaceName_ != 
nullptr); 
 
  766        return proxy_.callMethodAsync(
"Get")
 
  767                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  768                     .withArguments(*interfaceName_, propertyName_)
 
  769                     .getResultAsFuture<Variant>();
 
  776    inline PropertySetter::PropertySetter(IProxy& proxy, 
const std::string& propertyName)
 
  778        , propertyName_(propertyName)
 
  782    inline PropertySetter& PropertySetter::onInterface(
const std::string& interfaceName)
 
  784        interfaceName_ = &interfaceName;
 
  789    template <
typename _Value>
 
  790    inline void PropertySetter::toValue(
const _Value& value)
 
  792        PropertySetter::toValue(Variant{value});
 
  795    template <
typename _Value>
 
  796    inline void PropertySetter::toValue(
const _Value& value, dont_expect_reply_t)
 
  798        PropertySetter::toValue(Variant{value}, dont_expect_reply);
 
  801    inline void PropertySetter::toValue(
const Variant& value)
 
  803        assert(interfaceName_ != 
nullptr); 
 
  805        proxy_.callMethod(
"Set")
 
  806              .onInterface(
"org.freedesktop.DBus.Properties")
 
  807              .withArguments(*interfaceName_, propertyName_, value);
 
  810    inline void PropertySetter::toValue(
const Variant& value, dont_expect_reply_t)
 
  812        assert(interfaceName_ != 
nullptr); 
 
  814        proxy_.callMethod(
"Set")
 
  815                .onInterface(
"org.freedesktop.DBus.Properties")
 
  816                .withArguments(*interfaceName_, propertyName_, value)
 
  824    inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, 
const std::string& propertyName)
 
  826            , propertyName_(propertyName)
 
  830    inline AsyncPropertySetter& AsyncPropertySetter::onInterface(
const std::string& interfaceName)
 
  832        interfaceName_ = &interfaceName;
 
  837    template <
typename _Value>
 
  838    inline AsyncPropertySetter& AsyncPropertySetter::toValue(_Value&& value)
 
  840        return AsyncPropertySetter::toValue(Variant{std::forward<_Value>(value)});
 
  843    inline AsyncPropertySetter& AsyncPropertySetter::toValue(Variant value)
 
  845        value_ = std::move(value);
 
  850    template <
typename _Function>
 
  851    PendingAsyncCall AsyncPropertySetter::uponReplyInvoke(_Function&& callback)
 
  853        static_assert(std::is_invocable_r_v<void, _Function, const Error*>, 
"Property set callback function must accept Error* only");
 
  855        assert(interfaceName_ != 
nullptr); 
 
  857        return proxy_.callMethodAsync(
"Set")
 
  858                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  859                     .withArguments(*interfaceName_, propertyName_, std::move(value_))
 
  860                     .uponReplyInvoke(std::forward<_Function>(callback));
 
  863    inline std::future<void> AsyncPropertySetter::getResultAsFuture()
 
  865        assert(interfaceName_ != 
nullptr); 
 
  867        return proxy_.callMethodAsync(
"Set")
 
  868                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  869                     .withArguments(*interfaceName_, propertyName_, std::move(value_))
 
  870                     .getResultAsFuture<>();
 
  877    inline AllPropertiesGetter::AllPropertiesGetter(IProxy& proxy)
 
  882    inline std::map<std::string, Variant> AllPropertiesGetter::onInterface(
const std::string& interfaceName)
 
  884        std::map<std::string, Variant> props;
 
  885        proxy_.callMethod(
"GetAll")
 
  886                .onInterface(
"org.freedesktop.DBus.Properties")
 
  887                .withArguments(interfaceName)
 
  888                .storeResultsTo(props);
 
  896    inline AsyncAllPropertiesGetter::AsyncAllPropertiesGetter(IProxy& proxy)
 
  901    inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(
const std::string& interfaceName)
 
  903        interfaceName_ = &interfaceName;
 
  908    template <
typename _Function>
 
  909    PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback)
 
  911        static_assert( std::is_invocable_r_v<void, _Function, const Error*, std::map<std::string, Variant>>
 
  912                     , 
"All properties get callback function must accept Error* and a map of property names to their values" );
 
  914        assert(interfaceName_ != 
nullptr); 
 
  916        return proxy_.callMethodAsync(
"GetAll")
 
  917                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  918                     .withArguments(*interfaceName_)
 
  919                     .uponReplyInvoke(std::forward<_Function>(callback));
 
  922    inline std::future<std::map<std::string, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
 
  924        assert(interfaceName_ != 
nullptr); 
 
  926        return proxy_.callMethodAsync(
"GetAll")
 
  927                     .onInterface(
"org.freedesktop.DBus.Properties")
 
  928                     .withArguments(*interfaceName_)
 
  929                     .getResultAsFuture<std::map<std::string, Variant>>();