e44aa568368b165f82e1edc41adbbad201ac59a4
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-internal / dali-toolkit-test-utils / dbus-wrapper.h
1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
3
4 /*
5  * Copyright 2019  Samsung Electronics Co., Ltd
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <memory>
22 #include <array>
23 #include <atomic>
24 #include <cstdint>
25 #include <cstring>
26 #include <map>
27 #include <list>
28 #include <sstream>
29 #include <string>
30 #include <thread>
31 #include <tuple>
32 #include <type_traits>
33 #include <unordered_map>
34 #include <vector>
35 #include <functional>
36
37 // INTERNAL INCLUDES
38 //#include <dali/public-api/adaptor-framework/accessibility.h>
39 //#include <dali/internal/accessibility/bridge/optional.h>
40
41 #include <dali/devel-api/adaptor-framework/accessibility.h>
42
43 #define ATSPI_PREFIX_PATH "/org/a11y/atspi/accessible/"
44 #define ATSPI_NULL_PATH "/org/a11y/atspi/null"
45
46
47 //// BART QUICK HACK
48 #define bart_assert(x) do{}while(0)
49
50 struct _Eina_Value;
51
52 /// \cond
53 struct ObjectPath
54 {
55   std::string value;
56 };
57
58 struct DBusWrapper
59 {
60   virtual ~DBusWrapper() = default;
61
62   enum class ConnectionType
63   {
64     SYSTEM,
65     SESSION
66   };
67
68 #define DEFINE_TYPE(name, eldbus_name, unref_call) \
69     struct name { virtual ~name() = default; }; \
70     using name ## Ptr = std::shared_ptr<name>; \
71     using name ## WeakPtr = std::weak_ptr<name>; \
72
73   DEFINE_TYPE(Connection, Eldbus_Connection, )
74   DEFINE_TYPE(MessageIter, Eldbus_Message_Iter, eldbus_message_iter_container_close( Value ))
75   DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref( Value ))
76   DEFINE_TYPE(Proxy, Eldbus_Proxy, eldbus_proxy_unref( Value ))
77   DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref( Value ))
78   DEFINE_TYPE(Pending, Eldbus_Pending, )
79   DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
80
81 #undef DEFINE_TYPE
82   virtual ConnectionPtr eldbus_address_connection_get_impl(const std::string &addr) = 0;
83
84 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
85   virtual void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) = 0; \
86   virtual bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) = 0;
87 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
88   eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
89
90   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
91   eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
92   eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
93   eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
94   eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
95   eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
96   eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
97   eldbus_message_iter_arguments_append_impl_basic(double, d)
98   eldbus_message_iter_arguments_append_impl_basic(bool, b)
99   eldbus_message_iter_arguments_append_impl_basic_impl(const std::string &, std::string, s)
100   eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath &, ObjectPath, o)
101
102 #undef eldbus_message_iter_arguments_append_impl_basic
103 #undef eldbus_message_iter_arguments_append_impl_basic_impl
104
105   virtual MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) = 0;
106   virtual MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) = 0;
107   virtual MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) = 0;
108   virtual MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) = 0;
109   virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) = 0;
110   virtual bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) = 0;
111   virtual std::string eldbus_message_signature_get_impl(const MessagePtr &msg) = 0;
112
113   using SendCallback = std::function<void(const MessagePtr &msg)>;
114   virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) = 0;
115   virtual std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) = 0;
116   virtual void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) = 0;
117   virtual std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) = 0;
118   virtual MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) = 0;
119   virtual MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) = 0;
120   virtual PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) = 0;
121   virtual MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) = 0;
122   virtual MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) = 0;
123   virtual ConnectionPtr eldbus_connection_get_impl(ConnectionType type) = 0;
124   virtual std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) = 0;
125   virtual ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) = 0;
126   virtual ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) = 0;
127   virtual ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) = 0;
128
129   class StringStorage
130   {
131   public:
132     struct char_ptr_deleter
133     {
134       void operator()( char* p )
135       {
136         free( p );
137       }
138     };
139     std::vector< std::unique_ptr< char, char_ptr_deleter > > storage;
140
141     const char* add( const char* txt )
142     {
143       auto ptr = strdup( txt );
144       storage.push_back( std::unique_ptr< char, char_ptr_deleter >( ptr ) );
145       return storage.back().get();
146     }
147     const char* add( const std::string& txt )
148     {
149       return add( txt.c_str() );
150     }
151   };
152
153   struct CallId
154   {
155     static std::atomic< unsigned int > LastId;
156     unsigned int id = ++LastId;
157   };
158   struct MethodInfo
159   {
160     CallId id;
161     std::string memberName;
162     std::vector< std::pair<std::string, std::string> > in, out; // _Eldbus_Arg_Info
163     std::function< DBusWrapper::MessagePtr( const DBusWrapper::MessagePtr &msg ) > callback;
164   };
165   struct SignalInfo
166   {
167     CallId id;
168     std::string memberName;
169     std::vector< std::pair<std::string, std::string> > args;
170     unsigned int uniqueId;
171   };
172   struct PropertyInfo
173   {
174     CallId setterId, getterId;
175     std::string memberName, typeSignature;
176     std::function< std::string( const DBusWrapper::MessagePtr &src, const DBusWrapper::MessageIterPtr &dst ) > getCallback, setCallback;
177   };
178   struct SignalId
179   {
180     CallId id;
181
182     SignalId() = default;
183     SignalId( CallId id ) : id( id ) {}
184   };
185   virtual void add_interface_impl( bool fallback, const std::string& pathName,
186                               const ConnectionPtr &connection,
187                               std::vector<std::function<void()>> &destructors,
188                               const std::string& interfaceName,
189                               std::vector< MethodInfo >& dscrMethods,
190                               std::vector< PropertyInfo >& dscrProperties,
191                               std::vector< SignalInfo >& dscrSignals ) = 0;
192   virtual void add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const _Eina_Value * ) > cb) = 0;
193   static DBusWrapper *Installed();
194   static void Install(std::unique_ptr<DBusWrapper>);
195
196   StringStorage Strings;
197 };
198
199 namespace detail {
200   enum class MethodType {
201     Method, Getter, Setter
202   };
203 }
204
205 namespace std {
206   template <> struct hash<std::tuple<std::string, std::string, std::string>> {
207     size_t operator () (const std::tuple<std::string, std::string, std::string> &a) const {
208       auto a1 = std::hash<std::string>()(std::get<0>(a));
209       auto a2 = std::hash<std::string>()(std::get<1>(a));
210       auto a3 = std::hash<std::string>()(std::get<2>(a));
211       size_t v = a1;
212       v = (v * 11400714819323198485llu) + a2;
213       v = (v * 11400714819323198485llu) + a3;
214       return v;
215     }
216   };
217   template <> struct hash<std::tuple<std::string, std::string, std::string, detail::MethodType>> {
218     size_t operator () (const std::tuple<std::string, std::string, std::string, detail::MethodType> &a) const {
219       auto a1 = std::hash<std::string>()(std::get<0>(a));
220       auto a2 = std::hash<std::string>()(std::get<1>(a));
221       auto a3 = std::hash<std::string>()(std::get<2>(a));
222       auto a4 = static_cast<size_t>(std::get<3>(a));
223       size_t v = a1;
224       v = (v * 11400714819323198485llu) + a2;
225       v = (v * 11400714819323198485llu) + a3;
226       v = (v * 11400714819323198485llu) + a4;
227       return v;
228     }
229   };
230   template <> struct hash<std::tuple<std::string, std::string, unsigned int>> {
231     size_t operator () (const std::tuple<std::string, std::string, unsigned int> &a) const {
232       auto a1 = std::hash<std::string>()(std::get<0>(a));
233       auto a2 = std::hash<std::string>()(std::get<1>(a));
234       auto a3 = std::get<2>(a);
235       size_t v = a1;
236       v = (v * 11400714819323198485llu) + a2;
237       v = (v * 11400714819323198485llu) + a3;
238       return v;
239     }
240   };
241 }
242 namespace detail {
243   template <typename T> struct DBusSigImpl { enum { value = 0, end = 0 }; };
244   template <typename T> struct DBusSig { enum { value = DBusSigImpl<typename std::decay<T>::type>::value, end = DBusSigImpl<typename std::decay<T>::type>::end }; };
245   template <typename T, typename Q, size_t I, size_t S> struct IndexFromTypeTupleImpl {
246     enum { value = std::is_same<typename std::decay<typename std::tuple_element<I, T>::type>::type, Q>::value ? I : IndexFromTypeTupleImpl<T, Q, I + 1, S>::value };
247   };
248   template <typename T, typename Q, size_t S> struct IndexFromTypeTupleImpl<T, Q, S, S> { enum { value = S }; };
249   template <typename T, typename Q> struct IndexFromTypeTuple {
250     enum { value = IndexFromTypeTupleImpl<T, typename std::decay<Q>::type, 0, std::tuple_size<T>::value>::value };
251   };
252   template <typename T, typename = void> struct Encoder;
253   template <size_t I, size_t S, typename ... ARGS> struct EncoderTuple;
254 }
255 struct TestDBusWrapper : public DBusWrapper
256 {
257   using MethodType = detail::MethodType;
258   ConnectionPtr connection;
259   std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> testMethods;
260   std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> daliMethods;
261   std::unordered_map<std::tuple<std::string, std::string, unsigned int>, std::string> daliSignalsMap;
262   std::unordered_map<std::tuple<std::string, std::string, std::string>, std::function<void(const MessagePtr&)>> daliSignals;
263   std::unordered_map<std::tuple<std::string, std::string, std::string>, std::function<void(const _Eina_Value *)>> propertyChangeListeners;
264
265   std::vector<std::function<void()>> asyncCalls;
266
267   template <typename T> struct Variant {
268     T value;
269     Variant() = default;
270     Variant(T t) : value(std::move(t)) { }
271   };
272   template <typename ... ARGS> void Encode(const MessagePtr &m, const std::tuple<ARGS...> &args) {
273     auto iter = eldbus_message_iter_get_impl(m, true);
274     detail::EncoderTuple<0, sizeof...(ARGS), ARGS...>::encode(*this, iter, args);
275   }
276   template <typename ... ARGS> void Decode(const MessagePtr &m, std::tuple<ARGS...> &args) {
277     auto iter = eldbus_message_iter_get_impl(m, false);
278     detail::EncoderTuple<0, sizeof...(ARGS), ARGS...>::decode(*this, args, iter);
279   }
280   MessagePtr newMessage(const std::string &path, const std::string &interface, const std::string &name, bool reply);
281   MessagePtr newReplyMessage(const MessagePtr &m);
282
283   template <typename ... ARGS> void fromTestEmitSignal(std::string path, const std::string &interface, const std::string &name, const std::tuple<ARGS...> &args) {
284     if (path.empty()) throw error{};
285     if (path[0] != '/') path = "/org/a11y/atspi/accessible/" + path;
286     auto msg = newMessage(path, interface, name, false);
287     Encode(msg, args);
288     auto it = daliSignals.find(std::tuple<std::string, std::string, std::string>{ path, interface, name });
289     if (it == daliSignals.end()) throw error{};
290     it->second(msg);
291   }
292   static std::shared_ptr<_Eina_Value> createEinaValue(bool);
293   template <typename T> void fromTestChangeProperty(std::string path, const std::string &interface, const std::string &name, T new_value) {
294     auto v = createEinaValue(new_value);
295     if (path.empty()) throw error{};
296     if (path[0] != '/') path = "/org/a11y/atspi/accessible/" + path;
297     auto it = propertyChangeListeners.find(std::tuple<std::string, std::string, std::string>{ path, interface, name });
298     if (it == propertyChangeListeners.end()) throw error{};
299     it->second(v.get());
300   }
301   template <typename ... ARGS1, typename ... ARGS2> std::tuple<ARGS1...> fromTestCall(const std::string &path, const std::string &interface, const std::string &name, const std::tuple<ARGS2...> &args) {
302     auto msg = newMessage(path, interface, name, false);
303     Encode(msg, args);
304     auto res = call(daliMethods, "daliMethods", msg, MethodType::Method);
305     std::string a, b;
306     if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
307     std::tuple<ARGS1...> tmp;
308     Decode(res, tmp);
309     return tmp;
310   }
311   template <typename T> T fromTestGet(const std::string &path, const std::string &interface, const std::string &name) {
312     auto msg = newMessage(path, interface, name, false);
313     auto res = call(daliMethods, "daliMethods", msg, MethodType::Getter);
314     std::string a, b;
315     if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
316     std::tuple<T> tmp;
317     Decode(res, tmp);
318     return std::move(std::get<0>(tmp));
319   }
320   template <typename ... ARGS1, typename T> std::tuple<ARGS1...> fromTestSet(const std::string &path, const std::string &interface, const std::string &name, const T &arg) {
321     auto msg = newMessage(path, interface, name, false);
322     Encode(msg, TestDBusWrapper::Variant<T>{ arg });
323     auto res = call(daliMethods, "daliMethods", msg, MethodType::Setter);
324     std::string a, b;
325     if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
326     std::tuple<ARGS1...> tmp;
327     Decode(res, tmp);
328     return tmp;
329   }
330
331   TestDBusWrapper();
332   ~TestDBusWrapper();
333
334   class error : public std::exception {
335     std::shared_ptr<std::ostringstream> temp = std::make_shared<std::ostringstream>();
336     mutable std::string text;
337   public:
338     error() = default;
339
340     template <typename T> error &operator << (T &&t) {
341       *temp << std::forward<T>(t);
342       return *this;
343     }
344     const char *what() const noexcept override {
345       text = temp->str();
346       return text.c_str();
347     }
348   };
349   #define DEFINE_TYPE(name) struct name ## Impl; static name ## Impl *get(const name ## Ptr &);
350   DEFINE_TYPE(Connection)
351   DEFINE_TYPE(Proxy)
352   DEFINE_TYPE(Object)
353   DEFINE_TYPE(Message)
354   DEFINE_TYPE(MessageIter)
355   #undef DEFINE_TYPE
356
357   class Element;
358   using ElementList = std::list<Element>;
359   using ElementMap = std::map<std::string, std::string>;
360   using ElementTuple = std::tuple<
361     uint8_t, uint16_t, uint32_t, uint64_t, int16_t, int32_t, int64_t, double, bool, std::string, ObjectPath,
362     ElementList
363   >;
364
365   class Element {
366     ElementTuple data;
367     char signature_ = 0, end_ = 0, index_ = 0;
368     template <typename T> void set(T &&t, char signature = detail::DBusSig<T>::value) {
369       signature_ = signature;
370       end_ = detail::DBusSig<T>::end;
371       index_ = static_cast<char>(detail::IndexFromTypeTuple<ElementTuple, T>::value);
372       get<T>() = std::forward<T>(t);
373     }
374   public:
375     template <typename T> Element(T &&t, typename std::enable_if<detail::DBusSig<T>::value != 0>::type* = nullptr) { set(std::forward<T>(t)); }
376     Element(ElementList t, int signature) { set(std::move(t), static_cast<char>(signature)); }
377
378     char signature() const { return signature_; }
379     char end() const { return end_; }
380     char index() const { return index_; }
381     bool isContainer() const { return index_ == detail::IndexFromTypeTuple<ElementTuple, ElementList>::value; }
382     template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
383     bool is() const { return index_ == detail::IndexFromTypeTuple<ElementTuple, T>::value; }
384     template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
385     const T &get() const { if (!is<T>()) throw error{}; return std::get<detail::IndexFromTypeTuple<ElementTuple, T>::value>(data); }
386     template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
387     T &get() { if (!is<T>()) throw error{}; return std::get<detail::IndexFromTypeTuple<ElementTuple, T>::value>(data); }
388   };
389
390   ConnectionPtr eldbus_address_connection_get_impl(const std::string &addr) override;
391
392 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
393   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) override; \
394   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) override;
395 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
396   eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
397
398   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
399   eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
400   eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
401   eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
402   eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
403   eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
404   eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
405   eldbus_message_iter_arguments_append_impl_basic(double, d)
406   eldbus_message_iter_arguments_append_impl_basic(bool, b)
407   eldbus_message_iter_arguments_append_impl_basic_impl(const std::string &, std::string, s)
408   eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath &, ObjectPath, o)
409
410 #undef eldbus_message_iter_arguments_append_impl_basic
411 #undef eldbus_message_iter_arguments_append_impl_basic_impl
412
413   MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) override;
414   MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) override;
415   MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) override;
416   MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) override;
417   MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override;
418   bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override;
419   std::string eldbus_message_signature_get_impl(const MessagePtr &msg) override;
420   PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override;
421   std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) override;
422   void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) override;
423   std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) override;
424   MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) override;
425   MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) override;
426   PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) override;
427   MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) override;
428   MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) override;
429   ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override;
430   std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) override;
431   ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) override;
432   ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) override;
433   ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) override;
434   void add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const _Eina_Value * ) > cb) override;
435   void add_interface_impl( bool fallback, const std::string& pathName,
436                               const ConnectionPtr &connection,
437                               std::vector<std::function<void()>> &destructors,
438                               const std::string& interfaceName,
439                               std::vector< MethodInfo >& dscrMethods,
440                               std::vector< PropertyInfo >& dscrProperties,
441                               std::vector< SignalInfo >& dscrSignals ) override;
442   static bool completed(const MessageIterPtr &iter);
443 private:
444   MessagePtr call(std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> &mp, const std::string &name, const MessagePtr &msg, MethodType type);
445 };
446
447 namespace detail {
448   template <> struct DBusSigImpl<uint8_t> { enum { value = 'y', end = 0 }; };
449   template <> struct DBusSigImpl<uint16_t> { enum { value = 'q', end = 0 }; };
450   template <> struct DBusSigImpl<uint32_t> { enum { value = 'u', end = 0 }; };
451   template <> struct DBusSigImpl<uint64_t> { enum { value = 't', end = 0 }; };
452   template <> struct DBusSigImpl<int16_t> { enum { value = 'n', end = 0 }; };
453   template <> struct DBusSigImpl<int32_t> { enum { value = 'i', end = 0 }; };
454   template <> struct DBusSigImpl<int64_t> { enum { value = 'x', end = 0 }; };
455   template <> struct DBusSigImpl<double> { enum { value = 'd', end = 0 }; };
456   template <> struct DBusSigImpl<bool> { enum { value = 'b', end = 0 }; };
457   template <> struct DBusSigImpl<std::string> { enum { value = 's', end = 0 }; };
458   template <> struct DBusSigImpl<ObjectPath> { enum { value = 'o', end = 0 }; };
459   template <> struct DBusSigImpl<TestDBusWrapper::ElementList> { enum { value = '(', end = ')' }; };
460   template <> struct DBusSigImpl<TestDBusWrapper::ElementMap> { enum { value = '{', end = '}' }; };
461
462   template <typename T> struct Encoder<T, decltype(TestDBusWrapper().eldbus_message_iter_arguments_append_impl(TestDBusWrapper::MessageIterPtr(), T()))> {
463     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
464       w.eldbus_message_iter_arguments_append_impl(tgt, src);
465     }
466     static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
467       if (!w.eldbus_message_iter_get_and_next_impl(src, tgt)) throw TestDBusWrapper::error{};
468     }
469   };
470   template <typename T> struct Encoder<T, typename std::enable_if<std::is_enum<T>::value>::type> {
471     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
472       Encoder<typename std::underlying_type<T>::type>::encode(w, tgt, static_cast<typename std::underlying_type<T>::type>(src));
473     }
474     static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
475       typename std::underlying_type<T>::type v = 0;
476       Encoder<typename std::underlying_type<T>::type>::decode(w, v, src);
477       tgt = static_cast<T>(v);
478     }
479   };
480   template <typename T> struct Encoder<const T> {
481     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
482       Encoder<T>::encode(w, tgt, src);
483     }
484     static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
485       Encoder<T>::decode(w, tgt, src);
486     }
487   };
488   template <typename T> struct Encoder<const T &> {
489     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
490       Encoder<T>::encode(w, tgt, src);
491     }
492     static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
493       Encoder<T>::decode(w, tgt, src);
494     }
495   };
496   template <typename T> struct Encoder<T &> {
497     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
498       Encoder<T>::encode(w, tgt, src);
499     }
500     static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
501       Encoder<T>::decode(w, tgt, src);
502     }
503   };
504   template <size_t I, size_t S, typename ... ARGS> struct EncoderTuple {
505     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) {
506       Encoder<typename std::tuple_element<I, std::tuple<ARGS...>>::type>::encode(w, tgt, std::get<I>(src));
507       EncoderTuple<I + 1, S, ARGS...>::encode(w, tgt, src);
508     }
509     static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
510       Encoder<typename std::tuple_element<I, std::tuple<ARGS...>>::type>::decode(w, std::get<I>(tgt), src);
511       EncoderTuple<I + 1, S, ARGS...>::decode(w, tgt, src);
512     }
513   };
514   template <size_t S, typename ... ARGS> struct EncoderTuple<S, S, ARGS...> {
515     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) { }
516     static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) { }
517   };
518   template <typename ...ARGS> struct Encoder<std::tuple<ARGS...>> {
519     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) {
520       auto var = w.eldbus_message_iter_container_new_impl( tgt, 'r', "");
521       EncoderTuple<0, sizeof...(ARGS), ARGS...>::encode(w, var, src);
522     }
523     static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
524       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'r' );
525       if( !s ) throw TestDBusWrapper::error{};
526       EncoderTuple<0, sizeof...(ARGS), ARGS...>::decode(w, tgt, s);
527     }
528   };
529   template <typename A, typename B> struct Encoder<std::pair<A, B>> {
530     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::pair<A, B> &src, char type = 'r') {
531       auto var = w.eldbus_message_iter_container_new_impl( tgt, type, "");
532       Encoder<A>::encode(w, var, src.first);
533       Encoder<B>::encode(w, var, src.second);
534     }
535     static void decode(TestDBusWrapper &w, std::pair<A, B> &tgt, const TestDBusWrapper::MessageIterPtr &src, char type = 'r') {
536       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, type );
537       if( !s ) throw TestDBusWrapper::error{};
538       Encoder<A>::decode(w, tgt.first, s);
539       Encoder<B>::decode(w, tgt.second, s);
540     }
541   };
542   template <typename T> struct Encoder<TestDBusWrapper::Variant<T>> {
543     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const TestDBusWrapper::Variant<T> &src) {
544       //w.eldbus_message_iter_arguments_append_impl(tgt, src);
545       auto var = w.eldbus_message_iter_container_new_impl( tgt, 'v', "");
546       Encoder<T>::encode(w, var, src.value);
547     }
548     static void decode(TestDBusWrapper &w, TestDBusWrapper::Variant<T> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
549       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'v' );
550       if( !s ) throw TestDBusWrapper::error{};
551       Encoder<T>::decode(w, tgt.value, s);
552     }
553   };
554   template <typename T> struct Encoder<std::vector<T>> {
555     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::vector<T> &src) {
556       auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
557       for(auto &q : src)
558         Encoder<T>::encode(w, var, q);
559     }
560     static void decode(TestDBusWrapper &w, std::vector<T> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
561       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
562       if( !s ) throw TestDBusWrapper::error{};
563       while(!TestDBusWrapper::completed(s)) {
564         tgt.push_back({});
565         Encoder<T>::decode(w, tgt.back(), s);
566       }
567     }
568   };
569   template <typename K, typename V> struct Encoder<std::unordered_map<K,V>> {
570     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::unordered_map<K,V> &src) {
571       auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
572       for(auto &q : src){
573         Encoder<typename std::unordered_map<K,V>::value_type>::encode(w, var, q, 'e');
574       }
575     }
576     static void decode(TestDBusWrapper &w, std::unordered_map<K,V> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
577       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
578       if( !s ) throw TestDBusWrapper::error{};
579       while(!TestDBusWrapper::completed(s)) {
580         std::pair<K, V> tmp;
581         Encoder<std::pair<K,V>>::decode(w, tmp, s, 'e');
582         tgt.insert(std::move(tmp));
583       }
584     }
585   };
586   template <typename T, size_t I> struct Encoder<std::array<T, I>> {
587     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::array<T, I> &src) {
588       auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
589       for(auto &q : src)
590         Encoder<T>::encode(w, var, q);
591     }
592     static void decode(TestDBusWrapper &w, std::array<T, I> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
593       auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
594       if( !s ) throw TestDBusWrapper::error{};
595       size_t i = 0;
596       while(!TestDBusWrapper::completed(s)) {
597         if(i >= tgt.size()) throw TestDBusWrapper::error{};
598         Encoder<T>::decode(w, tgt[i], s);
599         ++i;
600       }
601       if( i!=tgt.size()) throw TestDBusWrapper::error{};
602     }
603   };
604   template <> struct Encoder<Dali::Accessibility::Address> {
605     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const Dali::Accessibility::Address &src) {
606       Encoder<std::tuple<std::string, ObjectPath>>::encode(w, tgt,std::tuple<std::string, ObjectPath> {
607         src.GetBus(), ObjectPath{ "/org/a11y/atspi/accessible/" + src.GetPath() } }
608       );
609     }
610     static void decode(TestDBusWrapper &w, Dali::Accessibility::Address &tgt, const TestDBusWrapper::MessageIterPtr &src) {
611       std::tuple<std::string, ObjectPath> tmp;
612       Encoder<std::tuple<std::string, ObjectPath>>::decode(w, tmp, src);
613       static const size_t prefixSize = std::string{ "/org/a11y/atspi/accessible/" }.size();
614       tgt = { std::move(std::get<0>(tmp)), std::get<1>(tmp).value.substr(prefixSize) };
615     }
616   };
617   template <> struct Encoder<const char*> {
618     static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const char *src) {
619       Encoder<std::string>::encode(w, tgt, src);
620     }
621   };
622 }
623 /// \endcond
624
625 #define DBUS_DEBUG( ... )                                \
626   do                                                     \
627   {                                                      \
628     DBus::debugPrint( __FILE__, __LINE__, __VA_ARGS__ ); \
629   } while( 0 )
630
631 #define DBUS_W DBusWrapper::Installed()
632
633 /**
634  * @brief Template based, single file, wrapper library around eldbus for DBUS based communication.
635  *
636  * Main motivation was missing asynchronous calls in AT-SPI library and difficulties,
637  * when using eldbus from C++.
638  *
639  * The library:
640  * - takes care of marshalling arguments to and from DBUS calls.
641  * - allows synchronous and asynchronous calls.
642  * - allows synchronous and asynchronous listeners on signals.
643  * - manages all involved objects' lifetimes.
644  * - errors are passed as optional-alike objects, no exceptions are used.
645  * - allows setting additional debug-print function for more details about
646  *   what's going on
647  *
648  * DBUS's method signatures (and expected return values) are specified as template argument,
649  * using functor syntax. For example:
650  * \code{.cpp}
651  * auto dbus = DBusClient{ ... };
652  * auto v = dbus.method<std::tuple<int, float>(float, float, std::string)>("foo").call(1.0f, 2.0f, "qwe");
653  * \endcode
654  * means (synchronous) call on dbus object, which takes three arguments (thus making call signature \b dds)
655  * of types float, float and string (float will be automatically converted to double).
656  * Expected return value is std::tuple<int, float>, which gives signature <B>(id)</B> - std::tuple acts
657  * as struct container. Returned value v will be of type ValueOrError<std::tuple<int, float>>.\n
658  * Slightly different (asynchronous) example:
659  * \code{.cpp}
660  * auto dbus = DBusClient{ ... };
661  * std::function<void(ValueOrError<int, float>)> callback;
662  * dbus.method<ValueOrError<int, float>(float, float, std::string)>("foo").asyncCall(callback, 1.0f, 2.0f, "qwe");
663  * \endcode
664  * Now the call takes the same arguments and has the same signature. But expected values are different -
665  * now the signature is simply \b id. ValueOrError acts in this case as placeholder for list of values,
666  * which DBUS allows as return data. The call itself is asynchronous - instead of expecting reply
667  * you need to pass a callback, which will be called either with received data and error message.
668  *
669  * Library is not thread-safe, the same object shouldn't be called from different threads without
670  * synchronization. There's no guarantee, that callbacks will be executed on the same thread.
671  */
672 namespace DBus
673 {
674 /// \cond
675 class DBusServer;
676 class DBusClient;
677 class DBusInterfaceDescription;
678
679 /**
680  * @brief Formats debug message and calls debug printer (if any) with it
681  */
682 void debugPrint( const char* file, size_t line, const char* format, ... );
683
684 /**
685  * @brief Sets debug printer callback, which will be called with debug messages
686  *
687  * Callback will be called in various moments of DBus activity. First value passed to callback
688  * is pointer to text, second it's length. Text is ended with 0 (not counted towards it's size),
689  * user can safely printf it.
690  */
691 void setDebugPrinter( std::function< void( const char*, size_t ) > );
692
693 struct Error
694 {
695   std::string message;
696
697   Error() = default;
698   Error( std::string msg ) : message( std::move( msg ) )
699   {
700     bart_assert( !message.empty() );
701   }
702 };
703
704 struct Success
705 {
706 };
707 /// \endcond
708
709 /**
710  * @brief Value representing data, that came from DBUS or error message
711  *
712  * Object of this class either helds series of values (of types ARGS...)
713  * or error message. This object will be true in boolean context, if has data
714  * and false, if an error occured.
715  * It's valid to create ValueOrError object with empty argument list or void:
716  * \code{.cpp}
717  * ValueOrError<> v1;
718  * ValueOrError<void> v2;
719  * \endcode
720  * Both mean the same - ValueOrError containing no real data and being a marker,
721  * wherever operation successed or failed and containing possible error message.
722  */
723 template < typename... ARGS >
724 class ValueOrError
725 {
726 public:
727   /**
728    * @brief Empty constructor. Valid only, if all ARGS types are default constructible.
729    */
730   ValueOrError() = default;
731
732   /**
733    * @brief Value constructor.
734    *
735    * This will be initialized as success with passed in values.
736    */
737   ValueOrError( ARGS... t ) : value( std::move( t )... ) {}
738
739   /**
740    * @brief Alternative Value constructor.
741    *
742    * This will be initialized as success with passed in values.
743    */
744   ValueOrError( std::tuple< ARGS... > t ) : value( std::move( t ) ) {}
745
746   /**
747    * @brief Error constructor. This will be initialized as failure with given error message.
748    */
749   ValueOrError( Error e ) : error( std::move( e ) )
750   {
751     bart_assert( !error.message.empty() );
752   }
753
754   /**
755    * @brief bool operator.
756    *
757    * Returns true, if operation was successful (getValues member is callable), or false
758    * when operation failed (getError is callable).
759    */
760   explicit operator bool() const
761   {
762     return error.message.empty();
763   }
764
765   /**
766    * @brief Returns error message object.
767    *
768    * Returns object containing error message associated with the failed operation.
769    * Only callable, if operation actually failed, otherwise will bart_assert.
770    */
771   const Error& getError() const
772   {
773     return error;
774   }
775
776   /**
777    * @brief Returns modifiable tuple of held data.
778    *
779    * Returns reference to the internal tuple containing held data.
780    * User can modify (or move) data safely.
781    * Only callable, if operation actually successed, otherwise will bart_assert.
782    */
783   std::tuple< ARGS... >& getValues()
784   {
785     bart_assert( *this );
786     return value;
787   }
788
789   /**
790    * @brief Returns const tuple of held data.
791    *
792    * Returns const reference to the internal tuple containing held data.
793    * Only callable, if operation actually successed, otherwise will bart_assert.
794    */
795   const std::tuple< ARGS... >& getValues() const
796   {
797     bart_assert( *this );
798     return value;
799   }
800
801 protected:
802   /// \cond
803   std::tuple< ARGS... > value;
804   Error error;
805   /// \endcond
806 };
807
808 /// \cond
809 template <>
810 class ValueOrError<>
811 {
812 public:
813   ValueOrError() = default;
814   ValueOrError( std::tuple<> t ) {}
815   ValueOrError( Error e ) : error( std::move( e ) )
816   {
817     bart_assert( !error.message.empty() );
818   }
819
820   explicit operator bool() const
821   {
822     return error.message.empty();
823   }
824   const Error& getError() const
825   {
826     return error;
827   }
828   std::tuple<>& getValues()
829   {
830     bart_assert( *this );
831     static std::tuple<> t;
832     return t;
833   }
834   std::tuple<> getValues() const
835   {
836     bart_assert( *this );
837     return {};
838   }
839
840 protected:
841   Error error;
842 };
843
844 template <>
845 class ValueOrError< void >
846 {
847 public:
848   ValueOrError() = default;
849   ValueOrError( Success ) {}
850   ValueOrError( Error e ) : error( std::move( e ) )
851   {
852     bart_assert( !error.message.empty() );
853   }
854
855   explicit operator bool() const
856   {
857     return error.message.empty();
858   }
859   const Error& getError() const
860   {
861     return error;
862   }
863   std::tuple<>& getValues()
864   {
865     bart_assert( *this );
866     static std::tuple<> t;
867     return t;
868   }
869   std::tuple<> getValues() const
870   {
871     bart_assert( *this );
872     return {};
873   }
874
875 protected:
876   Error error;
877 };
878
879 using ObjectPath = ObjectPath;
880
881 /// \endcond
882
883 /**
884  * @brief Class used to marshall DBUS's variant type
885  *
886  * Minimalistic class, that allows user to specify DBUS variant type
887  * as argument or return value. You need to pass real type hidden under variant as
888  * template type \b A. At this point library doesn't allow to expected one of few classes
889  * as return data in variant. So for example user can't specify method call, which on return
890  * expects DBUS variant holding either string or int.
891  */
892 template < typename A >
893 struct EldbusVariant
894 {
895   A value;
896 };
897
898 /**
899  * @brief Namespace for private, internal functions and classes
900  */
901 namespace detail
902 {
903 /// \cond
904 template < typename T, typename = void >
905 struct signature;
906 template < typename... ARGS >
907 struct signature< std::tuple< ARGS... > >;
908 template < typename A, typename B >
909 struct signature< std::pair< A, B > >;
910 template < typename A >
911 struct signature< std::vector< A > >;
912 template < typename A, size_t N >
913 struct signature< std::array< A, N > >;
914 template < typename A, typename B >
915 struct signature< std::unordered_map< A, B > >;
916 template < typename A, typename B >
917 struct signature< std::map< A, B > >;
918 /// \endcond
919
920 /**
921  * @brief Signature class for marshalling uint8 type.
922  */
923 template <>
924 struct signature< uint8_t >
925 {
926   /**
927    * @brief Returns name of type marshalled, for informative purposes
928    */
929   static std::string name()
930   {
931     return "uint8_t";
932   }
933
934   /**
935    * @brief Returns DBUS' signature of type marshalled
936    */
937   static std::string sig()
938   {
939     return "y";
940   }
941
942   /**
943    * @brief Marshals value v as marshalled type into message
944    */
945   static void set( const DBusWrapper::MessageIterPtr &iter, uint8_t v )
946   {
947     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
948   }
949
950   /**
951    * @brief Marshals value from marshalled type into variable v
952    */
953   static bool get( const DBusWrapper::MessageIterPtr &iter, uint8_t& v )
954   {
955     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
956   }
957 };
958
959 /**
960  * @brief Signature class for marshalling uint16 type.
961  */
962 template <>
963 struct signature< uint16_t >
964 {
965   /**
966    * @brief Returns name of type marshalled, for informative purposes
967    */
968   static std::string name()
969   {
970     return "uint16_t";
971   }
972
973   /**
974    * @brief Returns DBUS' signature of type marshalled
975    */
976   static std::string sig()
977   {
978     return "q";
979   }
980
981   /**
982    * @brief Marshals value v as marshalled type into message
983    */
984   static void set( const DBusWrapper::MessageIterPtr &iter, uint16_t v )
985   {
986     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
987   }
988
989   /**
990    * @brief Marshals value from marshalled type into variable v
991    */
992   static bool get( const DBusWrapper::MessageIterPtr &iter, uint16_t& v )
993   {
994     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
995   }
996 };
997
998 /**
999  * @brief Signature class for marshalling uint32 type.
1000  */
1001 template <>
1002 struct signature< uint32_t >
1003 {
1004   /**
1005    * @brief Returns name of type marshalled, for informative purposes
1006    */
1007   static std::string name()
1008   {
1009     return "uint32_t";
1010   }
1011
1012   /**
1013    * @brief Returns DBUS' signature of type marshalled
1014    */
1015   static std::string sig()
1016   {
1017     return "u";
1018   }
1019
1020   /**
1021    * @brief Marshals value v as marshalled type into message
1022    */
1023   static void set( const DBusWrapper::MessageIterPtr &iter, uint32_t v )
1024   {
1025     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1026   }
1027
1028   /**
1029    * @brief Marshals value from marshalled type into variable v
1030    */
1031   static bool get( const DBusWrapper::MessageIterPtr &iter, uint32_t& v )
1032   {
1033     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1034   }
1035 };
1036
1037 /**
1038  * @brief Signature class for marshalling uint64 type.
1039  */
1040 template <>
1041 struct signature< uint64_t >
1042 {
1043   /**
1044    * @brief Returns name of type marshalled, for informative purposes
1045    */
1046   static std::string name()
1047   {
1048     return "uint64_t";
1049   }
1050
1051   /**
1052    * @brief Returns DBUS' signature of type marshalled
1053    */
1054   static std::string sig()
1055   {
1056     return "t";
1057   }
1058
1059   /**
1060    * @brief Marshals value v as marshalled type into message
1061    */
1062   static void set( const DBusWrapper::MessageIterPtr &iter, uint64_t v )
1063   {
1064     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1065   }
1066
1067   /**
1068    * @brief Marshals value from marshalled type into variable v
1069    */
1070   static bool get( const DBusWrapper::MessageIterPtr &iter, uint64_t& v )
1071   {
1072     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1073   }
1074 };
1075
1076 /**
1077  * @brief Signature class for marshalling int16 type.
1078  */
1079 template <>
1080 struct signature< int16_t >
1081 {
1082   /**
1083    * @brief Returns name of type marshalled, for informative purposes
1084    */
1085   static std::string name()
1086   {
1087     return "int16_t";
1088   }
1089
1090   /**
1091    * @brief Returns DBUS' signature of type marshalled
1092    */
1093   static std::string sig()
1094   {
1095     return "n";
1096   }
1097
1098   /**
1099    * @brief Marshals value v as marshalled type into message
1100    */
1101   static void set( const DBusWrapper::MessageIterPtr &iter, int16_t v )
1102   {
1103     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1104   }
1105
1106   /**
1107    * @brief Marshals value from marshalled type into variable v
1108    */
1109   static bool get( const DBusWrapper::MessageIterPtr &iter, int16_t& v )
1110   {
1111     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1112   }
1113 };
1114
1115 /**
1116  * @brief Signature class for marshalling int32 type.
1117  */
1118 template <>
1119 struct signature< int32_t >
1120 {
1121   /**
1122    * @brief Returns name of type marshalled, for informative purposes
1123    */
1124   static std::string name()
1125   {
1126     return "int32_t";
1127   }
1128
1129   /**
1130    * @brief Returns DBUS' signature of type marshalled
1131    */
1132   static std::string sig()
1133   {
1134     return "i";
1135   }
1136
1137   /**
1138    * @brief Marshals value v as marshalled type into message
1139    */
1140   static void set( const DBusWrapper::MessageIterPtr &iter, int32_t v )
1141   {
1142     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1143   }
1144
1145   /**
1146    * @brief Marshals value from marshalled type into variable v
1147    */
1148   static bool get( const DBusWrapper::MessageIterPtr &iter, int32_t& v )
1149   {
1150     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1151   }
1152 };
1153
1154 /**
1155  * @brief Signature class for marshalling int64 type.
1156  */
1157 template <>
1158 struct signature< int64_t >
1159 {
1160   /**
1161    * @brief Returns name of type marshalled, for informative purposes
1162    */
1163   static std::string name()
1164   {
1165     return "int64_t";
1166   }
1167
1168   /**
1169    * @brief Returns DBUS' signature of type marshalled
1170    */
1171   static std::string sig()
1172   {
1173     return "x";
1174   }
1175
1176   /**
1177    * @brief Marshals value v as marshalled type into message
1178    */
1179   static void set( const DBusWrapper::MessageIterPtr &iter, int64_t v )
1180   {
1181     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1182   }
1183
1184   /**
1185    * @brief Marshals value from marshalled type into variable v
1186    */
1187   static bool get( const DBusWrapper::MessageIterPtr &iter, int64_t& v )
1188   {
1189     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1190   }
1191 };
1192
1193 /**
1194  * @brief Signature class for marshalling double type.
1195  */
1196 template <>
1197 struct signature< double >
1198 {
1199   /**
1200    * @brief Returns name of type marshalled, for informative purposes
1201    */
1202   static std::string name()
1203   {
1204     return "double";
1205   }
1206
1207   /**
1208    * @brief Returns DBUS' signature of type marshalled
1209    */
1210   static std::string sig()
1211   {
1212     return "d";
1213   }
1214
1215   /**
1216    * @brief Marshals value v as marshalled type into message
1217    */
1218   static void set( const DBusWrapper::MessageIterPtr &iter, double v )
1219   {
1220     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1221   }
1222
1223   /**
1224    * @brief Marshals value from marshalled type into variable v
1225    */
1226   static bool get( const DBusWrapper::MessageIterPtr &iter, double& v )
1227   {
1228     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1229   }
1230
1231   /**
1232    * @brief Marshals value from marshalled type into variable v
1233    */
1234   static bool get( const DBusWrapper::MessageIterPtr &iter, float& v2 )
1235   {
1236     double v = 0;
1237     auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1238     v2 = static_cast< float >( v );
1239     return r;
1240   }
1241 };
1242
1243 /**
1244  * @brief Signature class for marshalling float type.
1245  */
1246 template <>
1247 struct signature< float >
1248 {
1249   /**
1250    * @brief Returns name of type marshalled, for informative purposes
1251    */
1252   static std::string name()
1253   {
1254     return "float";
1255   }
1256
1257   /**
1258    * @brief Returns DBUS' signature of type marshalled
1259    */
1260   static std::string sig()
1261   {
1262     return "d";
1263   }
1264
1265   /**
1266    * @brief Marshals value v as marshalled type into message
1267    */
1268   static void set( const DBusWrapper::MessageIterPtr &iter, float v )
1269   {
1270     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1271   }
1272
1273   /**
1274    * @brief Marshals value from marshalled type into variable v
1275    */
1276   static bool get( const DBusWrapper::MessageIterPtr &iter, double& v )
1277   {
1278     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1279   }
1280
1281   /**
1282    * @brief Marshals value from marshalled type into variable v
1283    */
1284   static bool get( const DBusWrapper::MessageIterPtr &iter, float& v2 )
1285   {
1286     double v = 0;
1287     auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1288     v2 = static_cast< float >( v );
1289     return r;
1290   }
1291 };
1292
1293 /**
1294  * @brief Signature class for marshalling boolean type.
1295  */
1296 template <>
1297 struct signature< bool >
1298 {
1299   /**
1300    * @brief Returns name of type marshalled, for informative purposes
1301    */
1302   static std::string name()
1303   {
1304     return "bool";
1305   }
1306
1307   /**
1308    * @brief Returns DBUS' signature of type marshalled
1309    */
1310   static std::string sig()
1311   {
1312     return "b";
1313   }
1314
1315   /**
1316    * @brief Marshals value v as marshalled type into message
1317    */
1318   static void set( const DBusWrapper::MessageIterPtr &iter, bool v )
1319   {
1320     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1321   }
1322
1323   /**
1324    * @brief Marshals value from marshalled type into variable v
1325    */
1326   static bool get( const DBusWrapper::MessageIterPtr &iter, bool& v )
1327   {
1328     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1329   }
1330 };
1331
1332 template < typename T >
1333 struct signature< T, typename std::enable_if< std::is_enum< T >::value, void >::type >
1334 {
1335   /**
1336    * @brief Returns name of type marshalled, for informative purposes
1337    */
1338   static std::string name()
1339   {
1340     return "enum";
1341   }
1342
1343   /**
1344    * @brief Returns DBUS' signature of type marshalled
1345    */
1346   static std::string sig()
1347   {
1348     return signature<typename std::underlying_type<T>::type>::sig();
1349   }
1350
1351   /**
1352    * @brief Marshals value v as marshalled type into message
1353    */
1354   static void set( const DBusWrapper::MessageIterPtr &iter, T v )
1355   {
1356     signature<typename std::underlying_type<T>::type>::set(iter, static_cast< int64_t >( v ));
1357   }
1358
1359   /**
1360    * @brief Marshals value from marshalled type into variable v
1361    */
1362   static bool get( const DBusWrapper::MessageIterPtr &iter, T& v )
1363   {
1364     typename std::underlying_type<T>::type q = 0;
1365     if (!signature<typename std::underlying_type<T>::type>::get(iter, q))
1366       return false;
1367
1368     v = static_cast< T >( q );
1369     return true;
1370   }
1371 };
1372
1373 /**
1374  * @brief Signature class for marshalling string type.
1375  *
1376  * Both (const) char * and std::string types are accepted as value to send.
1377  * Only std::string is accepted as value to receive.
1378  */
1379 template <>
1380 struct signature< std::string >
1381 {
1382   /**
1383    * @brief Returns name of type marshalled, for informative purposes
1384    */
1385   static std::string name()
1386   {
1387     return "string";
1388   }
1389
1390   /**
1391    * @brief Returns DBUS' signature of type marshalled
1392    */
1393   static std::string sig()
1394   {
1395     return "s";
1396   }
1397
1398   /**
1399    * @brief Marshals value v as marshalled type into message
1400    */
1401   static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1402   {
1403     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1404   }
1405
1406 // /**
1407 //  * @brief Marshals value v as marshalled type into message
1408 //  */
1409 //  static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1410 //  {
1411 //    DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1412 //  }
1413
1414   /**
1415    * @brief Marshals value from marshalled type into variable v
1416    */
1417   static bool get( const DBusWrapper::MessageIterPtr &iter, std::string& v )
1418   {
1419     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1420   }
1421 };
1422
1423 template <>
1424 struct signature< ObjectPath >
1425 {
1426   /**
1427    * @brief Returns name of type marshalled, for informative purposes
1428    */
1429   static std::string name()
1430   {
1431     return "path";
1432   }
1433
1434   /**
1435    * @brief Returns DBUS' signature of type marshalled
1436    */
1437   static std::string sig()
1438   {
1439     return "o";
1440   }
1441
1442   /**
1443    * @brief Marshals value v as marshalled type into message
1444    */
1445   static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1446   {
1447     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
1448   }
1449
1450   /**
1451    * @brief Marshals value v as marshalled type into message
1452    */
1453   static void set( const DBusWrapper::MessageIterPtr &iter, const ObjectPath& v )
1454   {
1455     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1456   }
1457
1458   /**
1459    * @brief Marshals value v as marshalled type into message
1460    */
1461   static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1462   {
1463     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
1464   }
1465
1466   /**
1467    * @brief Marshals value from marshalled type into variable v
1468    */
1469   static bool get( const DBusWrapper::MessageIterPtr &iter, ObjectPath& v )
1470   {
1471     return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1472   }
1473
1474   /**
1475    * @brief Marshals value from marshalled type into variable v
1476    */
1477   static bool get( const DBusWrapper::MessageIterPtr &iter, std::string& v )
1478   {
1479     ObjectPath q;
1480     if (!DBUS_W->eldbus_message_iter_get_and_next_impl(iter, q)) return false;
1481     v = std::move(q.value);
1482     return true;
1483   }
1484 };
1485
1486 /**
1487  * @brief Signature class for marshalling (const) char * type.
1488  *
1489  * Both (const) char * and std::string types are accepted as value to send.
1490  * You can't use (const) char * variable type to receive value.
1491  */
1492 template <>
1493 struct signature< char* >
1494 {
1495   /**
1496    * @brief Returns name of type marshalled, for informative purposes
1497    */
1498   static std::string name()
1499   {
1500     return "string";
1501   }
1502
1503   /**
1504    * @brief Returns DBUS' signature of type marshalled
1505    */
1506   static std::string sig()
1507   {
1508     return "s";
1509   }
1510
1511   /**
1512    * @brief Marshals value v as marshalled type into message
1513    */
1514   static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1515   {
1516     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1517   }
1518
1519   /**
1520    * @brief Marshals value v as marshalled type into message
1521    */
1522   static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1523   {
1524     DBUS_W->eldbus_message_iter_arguments_append_impl(iter, std::string{ v });
1525   }
1526 };
1527 /// \cond
1528
1529 template < size_t INDEX, typename A, typename... ARGS >
1530 struct signature_tuple_element_type_helper
1531 {
1532   using type = typename signature_tuple_element_type_helper< INDEX - 1, ARGS... >::type;
1533 };
1534
1535 template < typename A, typename... ARGS >
1536 struct signature_tuple_element_type_helper< 0, A, ARGS... >
1537 {
1538   using type = A;
1539 };
1540 /// \endcond
1541
1542 /**
1543  * @brief Helper class to marshall tuples
1544  *
1545  * This class marshals all elements of the tuple value starting at the index INDEX
1546  * and incrementing. This class recursively calls itself with increasing INDEX value
1547  * until INDEX is equal to SIZE, where recursive calling ends.
1548  */
1549 template < size_t INDEX, size_t SIZE, typename... ARGS >
1550 struct signature_tuple_helper
1551 {
1552   using current_type = typename signature_tuple_element_type_helper< INDEX, ARGS... >::type;
1553
1554   /**
1555    * @brief Returns name of type marshalled, for informative purposes
1556    */
1557   static std::string name()
1558   {
1559     if( INDEX + 1 >= SIZE )
1560       return signature< current_type >::name();
1561     return signature< current_type >::name() + ", " + signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::name();
1562   }
1563
1564   /**
1565    * @brief Returns DBUS' signature of type marshalled
1566    */
1567   static std::string sig()
1568   {
1569     return signature< current_type >::sig() + signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::sig();
1570   }
1571
1572   /**
1573    * @brief Marshals value v as marshalled type into message
1574    */
1575   static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1576   {
1577     signature< current_type >::set( iter, std::get< INDEX >( args ) );
1578     signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::set( iter, args );
1579   }
1580
1581   /**
1582    * @brief Marshals value from marshalled type into variable v
1583    */
1584   static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1585   {
1586     return signature< current_type >::get( iter, std::get< INDEX >( args ) ) &&
1587            signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::get( iter, args );
1588   }
1589 };
1590
1591 /**
1592  * @brief Helper class to marshall tuples
1593  *
1594  * This class marks end of the tuple marshalling. Members of this class are called
1595  * when INDEX value is equal to SIZE.
1596  */
1597 template < size_t SIZE, typename... ARGS >
1598 struct signature_tuple_helper< SIZE, SIZE, ARGS... >
1599 {
1600   /**
1601    * @brief Returns name of type marshalled, for informative purposes
1602    */
1603   static std::string name()
1604   {
1605     return "";
1606   }
1607
1608   /**
1609    * @brief Returns DBUS' signature of type marshalled
1610    */
1611   static std::string sig()
1612   {
1613     return "";
1614   }
1615
1616   /**
1617    * @brief Marshals value v as marshalled type into message
1618    */
1619   static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1620   {
1621   }
1622
1623   /**
1624    * @brief Marshals value from marshalled type into variable v
1625    */
1626   static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1627   {
1628     return true;
1629   }
1630 };
1631
1632 /**
1633  * @brief Signature class for marshalling tuple of values
1634  *
1635  * This class marshalls tuple of values. This represents
1636  * DBUS struct typle, encoded with character 'r'
1637  */
1638 template < typename... ARGS >
1639 struct signature< std::tuple< ARGS... > >
1640 {
1641   /**
1642    * @brief Returns name of type marshalled, for informative purposes
1643    */
1644   static std::string name()
1645   {
1646     return "tuple<" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name() + ">";
1647   }
1648
1649   /**
1650    * @brief Returns DBUS' signature of type marshalled
1651    */
1652   static std::string sig()
1653   {
1654     return "(" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::sig() + ")";
1655   }
1656
1657   /**
1658    * @brief Marshals value v as marshalled type into message
1659    */
1660   static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1661   {
1662     auto entry = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'r', "");
1663     signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::set( entry, args );
1664   }
1665
1666   /**
1667    * @brief Marshals value from marshalled type into variable v
1668    */
1669   static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1670   {
1671     auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'r' );
1672     if (!entry) return false;
1673     return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::get( entry, args );
1674   }
1675 };
1676
1677 /**
1678  * @brief Signature class for marshalling ValueOrError template type
1679  *
1680  * ValueOrError template type is used to marshall list of values passed to
1681  * DBUS (or received from) at the "top" level. For example ss(s) is represented as
1682  * \code{.cpp} ValueOrError<std::string, std::string, std::tuple<std::string>> \endcode
1683  * While (ss(s)) is represented as
1684  * \code{.cpp} std::tuple<std::string, std::string, std::tuple<std::string>> \endcode
1685  * or
1686  * \code{.cpp} ValueOrError<std::tuple<std::string, std::string, std::tuple<std::string>>> \endcode
1687  */
1688 template < typename... ARGS >
1689 struct signature< ValueOrError< ARGS... > >
1690 {
1691   /**
1692    * @brief Returns name of type marshalled, for informative purposes
1693    */
1694   static std::string name()
1695   {
1696     return "ValueOrError<" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name() + ">";
1697   }
1698
1699   /**
1700    * @brief Returns DBUS' signature of type marshalled
1701    */
1702   static std::string sig()
1703   {
1704     return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::sig();
1705   }
1706
1707   /**
1708    * @brief Marshals value v as marshalled type into message
1709    */
1710   static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError< ARGS... >& args )
1711   {
1712     signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::set( iter, args.getValues() );
1713   }
1714
1715   /**
1716    * @brief Marshals value from marshalled type into variable v
1717    */
1718   static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError< ARGS... >& args )
1719   {
1720     return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::get( iter, args.getValues() );
1721   }
1722 };
1723
1724 /**
1725  * @brief Signature class for marshalling ValueOrError<void> type
1726  */
1727 template <>
1728 struct signature< ValueOrError< void > >
1729 {
1730   /**
1731    * @brief Returns name of type marshalled, for informative purposes
1732    */
1733   static std::string name()
1734   {
1735     return "ValueOrError<void>";
1736   }
1737
1738   /**
1739    * @brief Returns DBUS' signature of type marshalled
1740    */
1741   static std::string sig()
1742   {
1743     return "";
1744   }
1745
1746   /**
1747    * @brief Marshals value v as marshalled type into message
1748    */
1749   static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError< void >& args )
1750   {
1751   }
1752
1753   /**
1754    * @brief Marshals value from marshalled type into variable v
1755    */
1756   static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError< void >& args )
1757   {
1758     return true;
1759   }
1760 };
1761
1762 /**
1763  * @brief Signature class for marshalling ValueOrError<> type
1764  */
1765 template <>
1766 struct signature< ValueOrError<> >
1767 {
1768   /**
1769    * @brief Returns name of type marshalled, for informative purposes
1770    */
1771   static std::string name()
1772   {
1773     return "ValueOrError<>";
1774   }
1775
1776   /**
1777    * @brief Returns DBUS' signature of type marshalled
1778    */
1779   static std::string sig()
1780   {
1781     return "";
1782   }
1783
1784   /**
1785    * @brief Marshals value v as marshalled type into message
1786    */
1787   static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError<>& args )
1788   {
1789   }
1790
1791   /**
1792    * @brief Marshals value from marshalled type into variable v
1793    */
1794   static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError<>& args )
1795   {
1796     return true;
1797   }
1798 };
1799
1800 /**
1801  * @brief Signature class for marshalling pair of types
1802  */
1803 template < typename A, typename B >
1804 struct signature< std::pair< A, B > >
1805 {
1806   /**
1807    * @brief Returns name of type marshalled, for informative purposes
1808    */
1809   static std::string name()
1810   {
1811     return "pair<" + signature_tuple_helper< 0, 2, A, B >::name() + ">";
1812   }
1813
1814   /**
1815    * @brief Returns DBUS' signature of type marshalled
1816    */
1817   static std::string sig()
1818   {
1819     return "(" + signature_tuple_helper< 0, 2, A, B >::sig() + ")";
1820   }
1821
1822   /**
1823    * @brief Marshals value v as marshalled type into message
1824    */
1825   static void set( const DBusWrapper::MessageIterPtr &iter, const std::pair< A, B >& ab, bool dictionary = false )
1826   {
1827     auto entry = DBUS_W->eldbus_message_iter_container_new_impl( iter, dictionary ? 'e' : 'r', "");
1828     signature_tuple_helper< 0, 2, A, B >::set( entry, ab );
1829   }
1830
1831   /**
1832    * @brief Marshals value from marshalled type into variable v
1833    */
1834   static bool get( const DBusWrapper::MessageIterPtr &iter, std::pair< A, B >& ab )
1835   {
1836     auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'r' );
1837     if (!entry) {
1838       entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, '{' );
1839       if (!entry) return false;
1840     }
1841
1842     std::tuple< A, B > ab_tmp;
1843     auto z = signature_tuple_helper< 0, 2, A, B >::get( entry, ab_tmp );
1844     if( z )
1845     {
1846       ab.first = std::move( std::get< 0 >( ab_tmp ) );
1847       ab.second = std::move( std::get< 1 >( ab_tmp ) );
1848     }
1849     return z;
1850   }
1851 };
1852
1853 /**
1854  * @brief Signature class for marshalling std::vector template type
1855  *
1856  * This marshals container's content as DBUS a ascii character type code.
1857  */
1858 template < typename A >
1859 struct signature< std::vector< A > >
1860 {
1861   /**
1862    * @brief Returns name of type marshalled, for informative purposes
1863    */
1864   static std::string name()
1865   {
1866     return "vector<" + signature< A >::name() + ">";
1867   }
1868
1869   /**
1870    * @brief Returns DBUS' signature of type marshalled
1871    */
1872   static std::string sig()
1873   {
1874     return "a" + signature< A >::sig();
1875   }
1876
1877   /**
1878    * @brief Marshals value v as marshalled type into message
1879    */
1880   static void set( const DBusWrapper::MessageIterPtr &iter, const std::vector< A >& v )
1881   {
1882     auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', signature< A >::sig());
1883     bart_assert( lst );
1884     for( auto& a : v )
1885     {
1886       signature< A >::set( lst, a );
1887     }
1888   }
1889
1890   /**
1891    * @brief Marshals value from marshalled type into variable v
1892    */
1893   static bool get( const DBusWrapper::MessageIterPtr &iter, std::vector< A >& v )
1894   {
1895     auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
1896     if (!s) return false;
1897     v.clear();
1898     A a;
1899     while( signature< A >::get( s, a ) )
1900       v.push_back( std::move( a ) );
1901
1902     return true;
1903   }
1904 };
1905
1906 /**
1907  * @brief Signature class for marshalling std::array template type
1908  *
1909  * This marshals container's content as DBUS a ascii character type code.
1910  */
1911 template < typename A, size_t N >
1912 struct signature< std::array< A, N > >
1913 {
1914   /**
1915    * @brief Returns name of type marshalled, for informative purposes
1916    */
1917   static std::string name()
1918   {
1919     return "array<" + signature< A >::name() + ", " + std::to_string( N ) + ">";
1920   }
1921
1922   /**
1923    * @brief Returns DBUS' signature of type marshalled
1924    */
1925   static std::string sig()
1926   {
1927     return "a" + signature< A >::sig();
1928   }
1929
1930   /**
1931    * @brief Marshals value v as marshalled type into message
1932    */
1933   static void set( const DBusWrapper::MessageIterPtr &iter, const std::array< A, N >& v )
1934   {
1935     auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', signature< A >::sig());
1936     bart_assert( lst );
1937     for( auto& a : v )
1938     {
1939       signature< A >::set( lst, a );
1940     }
1941   }
1942
1943   /**
1944    * @brief Marshals value from marshalled type into variable v
1945    */
1946   static bool get( const DBusWrapper::MessageIterPtr &iter, std::array< A, N >& v )
1947   {
1948     auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
1949     if ( !s )
1950       return false;
1951     for( auto& a : v )
1952     {
1953       if( !signature< A >::get( s, a ) )
1954         return false;
1955     }
1956     return true;
1957   }
1958 };
1959
1960 /**
1961  * @brief Signature class for marshalling EldbusVariant type
1962  *
1963  * This marshals variant's content as DBUS v ascii character type code.
1964  */
1965 template < typename A >
1966 struct signature< EldbusVariant< A > >
1967 {
1968   /**
1969    * @brief Returns name of type marshalled, for informative purposes
1970    */
1971   static std::string name()
1972   {
1973     return "variant<" + signature< A >::name() + ">";
1974   }
1975
1976   /**
1977    * @brief Returns DBUS' signature of type marshalled
1978    */
1979   static std::string sig()
1980   {
1981     return "v";
1982   }
1983
1984   /**
1985    * @brief Marshals value v as marshalled type into message
1986    */
1987   static void set( const DBusWrapper::MessageIterPtr &iter, const EldbusVariant< A >& v )
1988   {
1989     set( iter, v.value );
1990   }
1991
1992   /**
1993    * @brief Marshals value v as marshalled type into message
1994    */
1995   static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
1996   {
1997     auto var = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'v', signature< A >::sig());
1998     signature< A >::set( var, v );
1999   }
2000
2001   /**
2002    * @brief Marshals value from marshalled type into variable v
2003    */
2004   static bool get( const DBusWrapper::MessageIterPtr &iter, EldbusVariant< A >& v )
2005   {
2006     auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'v' );
2007     if( !s )
2008       return false;
2009     return signature< A >::get( s, v.value );
2010   }
2011 };
2012
2013 /**
2014  * @brief Signature class for marshalling std::unordered_map template type
2015  *
2016  * This marshals container's content as DBUS {} ascii character type code.
2017  * Note, that library doesnt check, if the key is basic type, as DBUS
2018  * specification mandates.
2019  * User can always exchange std::unordered_map for std::map and the reverse.
2020  * User can receive such values as std::vector of std::pair<key, value> values.
2021  * Order of such values is unspecified.
2022  */
2023 template < typename A, typename B >
2024 struct signature< std::unordered_map< A, B > >
2025 {
2026   /**
2027    * @brief Returns name of type marshalled, for informative purposes
2028    */
2029   static std::string name()
2030   {
2031     return "unordered_map<" + signature< A >::name() + ", " + signature< B >::name() + ">";
2032   }
2033
2034   /**
2035    * @brief Returns DBUS' signature of type marshalled
2036    */
2037   static std::string sig()
2038   {
2039     return "a{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2040   }
2041
2042   /**
2043    * @brief Marshals value v as marshalled type into message
2044    */
2045   static void set( const DBusWrapper::MessageIterPtr &iter, const std::unordered_map< A, B >& v )
2046   {
2047     auto sig = "{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2048     auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', sig);
2049     bart_assert( lst );
2050     for( auto& a : v )
2051     {
2052       signature< std::pair< A, B > >::set( lst, a, true );
2053     }
2054   }
2055
2056   /**
2057    * @brief Marshals value from marshalled type into variable v
2058    */
2059   static bool get( const DBusWrapper::MessageIterPtr &iter, std::unordered_map< A, B >& v )
2060   {
2061     auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
2062     v.clear();
2063     if( !s )
2064       return false;
2065     std::pair< A, B > a;
2066     while( signature< std::pair< A, B > >::get( s, a ) )
2067       v.insert( std::move( a ) );
2068     return true;
2069   }
2070 };
2071
2072 /**
2073  * @brief Signature class for marshalling std::unordered_map template type
2074  *
2075  * This marshals container's content as DBUS {} ascii character type code.
2076  * Note, that library doesnt check, if the key is basic type, as DBUS
2077  * specification mandates.
2078  * User can always exchange std::unordered_map for std::map and the reverse.
2079  * User can receive such values as std::vector of std::pair<key, value> values.
2080  * Order of such values is unspecified.
2081  */
2082 template < typename A, typename B >
2083 struct signature< std::map< A, B > >
2084 {
2085   /**
2086    * @brief Returns name of type marshalled, for informative purposes
2087    */
2088   static std::string name()
2089   {
2090     return "map<" + signature< A >::name() + ", " + signature< B >::name() + ">";
2091   }
2092
2093   /**
2094    * @brief Returns DBUS' signature of type marshalled
2095    */
2096   static std::string sig()
2097   {
2098     return "a{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2099   }
2100
2101   /**
2102    * @brief Marshals value v as marshalled type into message
2103    */
2104   static void set( const DBusWrapper::MessageIterPtr &iter, const std::map< A, B >& v )
2105   {
2106     auto sig = "{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2107     auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', sig);
2108     bart_assert( lst );
2109     for( auto& a : v )
2110     {
2111       signature< std::pair< A, B > >::set( lst, a, true );
2112     }
2113   }
2114
2115   /**
2116    * @brief Marshals value from marshalled type into variable v
2117    */
2118   static bool get( const DBusWrapper::MessageIterPtr &iter, std::map< A, B >& v )
2119   {
2120     auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
2121     if( !s )
2122       return false;
2123     std::pair< A, B > a;
2124     while( signature< std::pair< A, B > >::get( s, a ) )
2125       v.insert( std::move( a ) );
2126     return true;
2127   }
2128 };
2129
2130 /**
2131  * @brief Signature helper class for marshalling const reference types
2132  */
2133 template < typename A >
2134 struct signature< const A& >
2135 {
2136   /**
2137    * @brief Returns name of type marshalled, for informative purposes
2138    */
2139   static std::string name()
2140   {
2141     return "const " + signature< A >::name() + "&";
2142   }
2143
2144   /**
2145    * @brief Returns DBUS' signature of type marshalled
2146    */
2147   static std::string sig()
2148   {
2149     return signature< A >::sig();
2150   }
2151
2152   /**
2153    * @brief Marshals value v as marshalled type into message
2154    */
2155   static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2156   {
2157     signature< A >::set( iter, v );
2158   }
2159
2160   /**
2161    * @brief Marshals value from marshalled type into variable v
2162    */
2163   static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2164   {
2165     signature< A >::get( iter, v );
2166   }
2167 };
2168
2169 /**
2170  * @brief Signature helper class for marshalling reference types
2171  */
2172 template < typename A >
2173 struct signature< A& >
2174 {
2175   /**
2176    * @brief Returns name of type marshalled, for informative purposes
2177    */
2178   static std::string name()
2179   {
2180     return signature< A >::name() + "&";
2181   }
2182
2183   /**
2184    * @brief Returns DBUS' signature of type marshalled
2185    */
2186   static std::string sig()
2187   {
2188     return signature< A >::sig();
2189   }
2190
2191   /**
2192    * @brief Marshals value v as marshalled type into message
2193    */
2194   static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2195   {
2196     signature< A >::set( iter, v );
2197   }
2198
2199   /**
2200    * @brief Marshals value from marshalled type into variable v
2201    */
2202   static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2203   {
2204     signature< A >::get( iter, v );
2205   }
2206 };
2207
2208 /**
2209  * @brief Signature helper class for marshalling const types
2210  */
2211 template < typename A >
2212 struct signature< const A >
2213 {
2214   /**
2215    * @brief Returns name of type marshalled, for informative purposes
2216    */
2217   static std::string name()
2218   {
2219     return "const " + signature< A >::name();
2220   }
2221
2222   /**
2223    * @brief Returns DBUS' signature of type marshalled
2224    */
2225   static std::string sig()
2226   {
2227     return signature< A >::sig();
2228   }
2229
2230   /**
2231    * @brief Marshals value v as marshalled type into message
2232    */
2233   static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2234   {
2235     signature< A >::set( iter, v );
2236   }
2237
2238   /**
2239    * @brief Marshals value from marshalled type into variable v
2240    */
2241   static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2242   {
2243     signature< A >::get( iter, v );
2244   }
2245 };
2246
2247 /// \cond
2248 using CallId = DBusWrapper::CallId;
2249
2250 template < typename ValueType >
2251 ValueType unpackValues( CallId callId, const DBusWrapper::MessagePtr &msg )
2252 {
2253   auto iter = DBUS_W->eldbus_message_iter_get_impl( msg, false );
2254   ValueType r;
2255
2256   if( iter )
2257   {
2258     if( !signature< ValueType >::get( iter, r ) )
2259     {
2260       DBUS_DEBUG( "ValueType is %s", signature< ValueType >::name().c_str() );
2261       r = Error{"call " + std::to_string( callId.id ) + ": failed to unpack values, got signature '" +
2262                 DBUS_W->eldbus_message_signature_get_impl( msg ) + "', expected '" + signature< ValueType >::sig() + "'"};
2263     }
2264   }
2265   else
2266   {
2267     r = Error{"call " + std::to_string( callId.id ) + ": failed to get iterator"};
2268   }
2269   return r;
2270 }
2271
2272 inline void packValues_helper( const DBusWrapper::MessageIterPtr& ) {}
2273
2274 template < typename A, typename... ARGS >
2275 void packValues_helper( const DBusWrapper::MessageIterPtr &iter, A&& a, ARGS&&... r )
2276 {
2277   signature< A >::set( iter, std::forward< A >( a ) );
2278   packValues_helper( iter, std::forward< ARGS >( r )... );
2279 }
2280
2281 template < typename... ARGS >
2282 void packValues( CallId callId, const DBusWrapper::MessagePtr &msg, ARGS&&... r )
2283 {
2284   auto iter = DBUS_W->eldbus_message_iter_get_impl( msg, true );
2285   packValues_helper( iter, std::forward< ARGS >( r )... );
2286 }
2287
2288 template < typename >
2289 struct ReturnType;
2290 template < typename R, typename... ARGS >
2291 struct ReturnType< R( ARGS... ) >
2292 {
2293   using type = R;
2294 };
2295
2296 template < typename R, typename... ARGS >
2297 struct ReturnType< std::function< R( ARGS... ) > >
2298 {
2299   using type = R;
2300 };
2301
2302 template < int... >
2303 struct sequence
2304 {
2305 };
2306
2307 template < int N, int... S >
2308 struct sequence_gen : sequence_gen< N - 1, N - 1, S... >
2309 {
2310 };
2311
2312 template < int... S >
2313 struct sequence_gen< 0, S... >
2314 {
2315   typedef sequence< S... > type;
2316 };
2317
2318 template < typename C, typename... ARGS >
2319 struct apply_helper
2320 {
2321   const std::function< C >& c;
2322   const std::tuple< ARGS... >& args;
2323
2324   template < int... S >
2325   auto apply_2( sequence< S... > ) const -> decltype( c( std::get< S >( args )... ) )
2326   {
2327     return c( std::get< S >( args )... );
2328   }
2329   auto apply_1() const -> decltype( apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() ) )
2330   {
2331     return apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() );
2332   }
2333 };
2334
2335 template < typename C, typename A, typename... ARGS >
2336 struct apply_helper_2
2337 {
2338   const std::function< C >& c;
2339   const A& a;
2340   const std::tuple< ARGS... >& args;
2341
2342   template < int... S >
2343   auto apply_2( sequence< S... > ) const -> decltype( c( a, std::get< S >( args )... ) )
2344   {
2345     return c( a, std::get< S >( args )... );
2346   }
2347   auto apply_1() const -> decltype( apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() ) )
2348   {
2349     return apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() );
2350   }
2351 };
2352
2353 template < typename C, typename... ARGS >
2354 auto apply( const std::function< C >& c, const std::tuple< ARGS... >& args ) -> typename ReturnType< C >::type
2355 {
2356   apply_helper< C, ARGS... > ah{c, args};
2357   return ah.apply_1();
2358 }
2359
2360 template < typename C, typename D, typename... ARGS >
2361 auto apply( const std::function< C >& c, const D& d, const std::tuple< ARGS... >& args ) -> typename ReturnType< C >::type
2362 {
2363   apply_helper_2< C, D, ARGS... > ah{c, d, args};
2364   return ah.apply_1();
2365 }
2366
2367 struct ConnectionState
2368 {
2369   DBusWrapper::ConnectionPtr connection;
2370   DBusWrapper::ObjectPtr object;
2371   DBusWrapper::ProxyPtr proxy, propertiesProxy;
2372 };
2373
2374 template < typename RETTYPE, typename... ARGS >
2375 RETTYPE call( CallId callId, const ConnectionState& connectionState, bool property, const std::string& funcName, const ARGS&... args )
2376 {
2377   const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
2378   if( !proxy )
2379   {
2380     DBUS_DEBUG( "call %d: not initialized", callId.id );
2381     return Error{"not initialized"};
2382   }
2383
2384   DBUS_DEBUG( "call %d: calling '%s'", callId.id, funcName.c_str() );
2385   auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
2386   if( !msg )
2387   {
2388     DBUS_DEBUG( "call %d: failed", callId.id );
2389     return Error{"failed to create message"};
2390   }
2391
2392   detail::packValues( callId, msg, args... );
2393   auto reply = DBUS_W->eldbus_proxy_send_and_block_impl( proxy, msg );
2394   DBUS_DEBUG( "call %d: calling '%s' done", callId.id, funcName.c_str() );
2395   if( !reply )
2396   {
2397     DBUS_DEBUG( "call %d: failed", callId.id );
2398     return Error{"eldbus returned null as reply"};
2399   }
2400   std::string errname, errmsg;
2401   if( DBUS_W->eldbus_message_error_get_impl( reply, errname, errmsg ) )
2402   {
2403     DBUS_DEBUG( "call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str() );
2404     return Error{errname + ": " + errmsg};
2405   }
2406   DBUS_DEBUG( "call %d: got reply with signature '%s'", callId.id,
2407     DBUS_W->eldbus_message_signature_get_impl( reply ).c_str() );
2408   return detail::unpackValues< RETTYPE >( callId, reply );
2409 }
2410
2411 template < typename RETTYPE, typename... ARGS >
2412 void asyncCall( CallId callId, const ConnectionState &connectionState,
2413                 bool property, const std::string& funcName,
2414                 std::function< void( RETTYPE ) > callback, const ARGS&... args )
2415 {
2416   const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
2417   if( !proxy )
2418   {
2419     DBUS_DEBUG( "call %d: not initialized", callId.id );
2420     callback( Error{"not initialized"} );
2421     return;
2422   }
2423
2424   auto msg = DBUS_W->eldbus_proxy_method_call_new_impl( proxy, funcName );
2425   if( !msg )
2426   {
2427     DBUS_DEBUG( "call %d: failed", callId.id );
2428     callback( Error{"failed to create message"} );
2429     return;
2430   }
2431
2432   detail::packValues( callId, msg, args... );
2433   auto pending = DBUS_W->eldbus_proxy_send_impl( proxy, msg, [callback, callId, proxy]( const DBusWrapper::MessagePtr &reply ) {
2434         DBUS_DEBUG( "call %d: calling done", callId.id );
2435         if( !reply )
2436         {
2437           DBUS_DEBUG( "call %d: failed", callId.id );
2438           callback( Error{"eldbus returned null as reply"} );
2439         }
2440         else
2441         {
2442           std::string errname, errmsg;
2443           if( DBUS_W->eldbus_message_error_get_impl( reply, errname, errmsg ) )
2444           {
2445             DBUS_DEBUG( "call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str() );
2446             callback( Error{errname + ": " + errmsg} );
2447           }
2448           else
2449           {
2450             DBUS_DEBUG( "call %d: got reply with signature '%s'", callId.id,
2451                 DBUS_W->eldbus_message_signature_get_impl( reply ).c_str() );
2452             callback( detail::unpackValues< RETTYPE >( callId, reply ) );
2453           }
2454         }
2455       }
2456     );
2457   if( pending )
2458   {
2459     DBUS_DEBUG( "call %d: call sent", callId.id );
2460   }
2461   else
2462   {
2463     DBUS_DEBUG( "call %d: failed to send call", callId.id );
2464     callback( Error{"failed to send call"} );
2465   }
2466 }
2467
2468 inline void displayDebugCallInfo( CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName )
2469 {
2470   DBUS_DEBUG( "call %d: %s iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str() );
2471 }
2472
2473 inline void displayDebugCallInfoSignal( CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName )
2474 {
2475   DBUS_DEBUG( "call %d: %s signal iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str() );
2476 }
2477
2478 inline void displayDebugCallInfoProperty( CallId callId, const std::string& funcName, std::string info, const std::string& interfaceName,
2479                                           const std::string& propertyName )
2480 {
2481   DBUS_DEBUG( "call %d: %s iname = %s pname = %s", callId.id, info.c_str(), interfaceName.c_str(), propertyName.c_str() );
2482 }
2483
2484 using StringStorage = DBusWrapper::StringStorage;
2485
2486 template < typename A, typename... ARGS >
2487 struct EldbusArgGenerator_Helper
2488 {
2489   static void add( std::vector< std::pair<std::string, std::string> >& r )
2490   {
2491     auto s = r.size();
2492     auto sig = signature< A >::sig();
2493     bart_assert( !sig.empty() );
2494     auto name = "p" + std::to_string( s + 1 );
2495     r.push_back({ std::move(sig), std::move(name) });
2496     EldbusArgGenerator_Helper<ARGS...>::add( r );
2497   }
2498 };
2499
2500 template <>
2501 struct EldbusArgGenerator_Helper< void >
2502 {
2503   static void add( std::vector< std::pair<std::string, std::string> >& )
2504   {
2505   }
2506 };
2507
2508 template <>
2509 struct EldbusArgGenerator_Helper< ValueOrError< void >, void >
2510 {
2511   static void add( std::vector< std::pair<std::string, std::string> >& )
2512   {
2513   }
2514 };
2515 template <>
2516 struct EldbusArgGenerator_Helper< ValueOrError<>, void >
2517 {
2518   static void add( std::vector< std::pair<std::string, std::string> >& )
2519   {
2520   }
2521 };
2522
2523 template < typename... ARGS >
2524 struct EldbusArgGenerator_Helper< std::tuple< ARGS... > >
2525 {
2526   static void add( std::vector< std::pair<std::string, std::string> >& r )
2527   {
2528     EldbusArgGenerator_Helper< ARGS..., void >::add( r );
2529   }
2530 };
2531
2532 template < typename RetType >
2533 struct dbus_interface_return_type_traits
2534 {
2535   using type = ValueOrError< RetType >;
2536 };
2537
2538 template < typename... ARGS >
2539 struct dbus_interface_return_type_traits< ValueOrError< ARGS... > >
2540 {
2541   using type = ValueOrError< ARGS... >;
2542 };
2543
2544 template < typename T >
2545 struct dbus_interface_traits;
2546 template < typename RetType, typename... ARGS >
2547 struct dbus_interface_traits< RetType( ARGS... ) >
2548 {
2549   using Ret = typename dbus_interface_return_type_traits< RetType >::type;
2550   using SyncCB = std::function< Ret( ARGS... ) >;
2551   using AsyncCB = std::function< void( std::function< void( Ret ) >, ARGS... ) >;
2552   using VEArgs = ValueOrError< ARGS... >;
2553 };
2554
2555 template < typename T >
2556 struct EldbusArgGenerator_Args;
2557 template < typename RetType, typename... ARGS >
2558 struct EldbusArgGenerator_Args< RetType( ARGS... ) >
2559 {
2560   static std::string name()
2561   {
2562     return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name();
2563   }
2564   static std::vector< std::pair<std::string, std::string> > get()
2565   {
2566     std::vector< std::pair<std::string, std::string> > tmp;
2567     EldbusArgGenerator_Helper< ARGS..., void >::add( tmp );
2568     return tmp;
2569   }
2570 };
2571
2572 template < typename T >
2573 struct EldbusArgGenerator_ReturnType;
2574 template < typename RetType, typename... ARGS >
2575 struct EldbusArgGenerator_ReturnType< RetType( ARGS... ) >
2576 {
2577   static std::string name()
2578   {
2579     return signature< RetType >::name();
2580   }
2581   static std::vector< std::pair<std::string, std::string> > get( )
2582   {
2583     std::vector< std::pair<std::string, std::string> > tmp;
2584     EldbusArgGenerator_Helper< RetType, void >::add( tmp );
2585     return tmp;
2586   }
2587 };
2588
2589 template < typename T >
2590 struct EldbusArgGenerator_ReturnType;
2591 template < typename... ARGS >
2592 struct EldbusArgGenerator_ReturnType< void( ARGS... ) >
2593 {
2594   static std::string name()
2595   {
2596     return "";
2597   }
2598   static std::vector< std::pair<std::string, std::string> > get( )
2599   {
2600     return {};
2601   }
2602 };
2603 /// \endcond
2604 }
2605
2606 using ConnectionType = DBusWrapper::ConnectionType;
2607
2608 /**
2609  * @brief Class representing client's end of DBUS connection
2610  *
2611  * Allows calling (synchronous and asynchronos) methods on selected interface
2612  * Allows (synchronous and asynchronos) setting / getting properties.
2613  * Allows registering signals.
2614  */
2615 class DBusClient
2616 {
2617   /// \cond
2618   struct ConnectionInfo
2619   {
2620     std::string interfaceName, busName, pathName;
2621   };
2622   /// \endcond
2623 public:
2624   /**
2625    * @brief Default constructor, creates non-connected object.
2626    */
2627   DBusClient() = default;
2628
2629   /**
2630    * @brief Connects to dbus choosen by tp, using given arguments
2631    *
2632    * @param bus_name name of the bus to connect to
2633    * @param path_name object's path
2634    * @param interface_name interface name
2635    */
2636   DBusClient( std::string busName_, std::string pathName_, std::string interfaceName_,
2637               ConnectionType tp );
2638
2639   /**
2640    * @brief Connects to dbus using connection conn
2641    *
2642    * @param bus_name name of the bus to connect to
2643    * @param path_name object's path
2644    * @param interface_name interface name
2645    * @param conn connection object from getDBusConnectionByType call
2646    */
2647   DBusClient( std::string busName_, std::string pathName_, std::string interfaceName_,
2648               const DBusWrapper::ConnectionPtr &conn = {} );
2649
2650   /**
2651    * @brief Destructor object.
2652    *
2653    * All signals added will be disconnected.
2654    * All asynchronous calls will be cancelled, their callback's will be called
2655    * with failure message.
2656    */
2657   ~DBusClient() = default;
2658   DBusClient( const DBusClient& ) = delete;
2659   DBusClient( DBusClient&& ) = default;
2660
2661   DBusClient& operator=( DBusClient&& ) = default;
2662   DBusClient& operator=( const DBusClient& ) = delete;
2663
2664   /**
2665    * @brief bool operator
2666    *
2667    * Returns true, if object is connected to DBUS
2668    */
2669   explicit operator bool() const
2670   {
2671     return bool( connectionState->proxy );
2672   }
2673
2674   /**
2675    * @brief Helper class for calling a method
2676    *
2677    * Template type T defines both arguments sent to the method
2678    * and expected values. Receiving different values will be reported as
2679    * error. For example:
2680    * \code{.cpp} Method<int(float, float)> \endcode
2681    * defines method, which takes two arguments (two floats) and return
2682    * single value of type int.
2683    */
2684   template < typename T >
2685   struct Method
2686   {
2687     /// \cond
2688     using RetType = typename detail::dbus_interface_traits< T >::Ret;
2689     const detail::ConnectionState &connectionState;
2690     std::string funcName;
2691     std::string info;
2692     std::shared_ptr< ConnectionInfo > connectionInfo;
2693     /// \endcond
2694
2695     /**
2696      * @brief Executes synchronous call on DBUS's method
2697      *
2698      * The function returns ValueOrError<...> object, which
2699      * contains either received values or error message.
2700      *
2701      * @param args arguments to pass to the method
2702      */
2703     template < typename... ARGS >
2704     RetType call( const ARGS&... args )
2705     {
2706       detail::CallId callId;
2707       detail::displayDebugCallInfo( callId, funcName, info, connectionInfo->interfaceName );
2708       return detail::call< RetType >( callId, connectionState, false, funcName, args... );
2709     }
2710
2711     /**
2712      * @brief Executes asynchronous call on DBUS's method
2713      *
2714      * The function calls callback with either received values or error message.
2715      *
2716      * @param callback callback functor, which will be called with return value(s) or error message
2717      * @param args arguments to pass to the method
2718      */
2719     template < typename... ARGS >
2720     void asyncCall( std::function< void( RetType ) > callback, const ARGS&... args )
2721     {
2722       detail::CallId callId;
2723       detail::displayDebugCallInfo( callId, funcName, info, connectionInfo->interfaceName );
2724       detail::asyncCall< RetType >( callId, connectionState, false, funcName, std::move( callback ), args... );
2725     }
2726   };
2727
2728   /**
2729    * @brief Helper class for calling a property
2730    *
2731    * Template type T defines type of the value hidden under property.
2732    * Note, that library automatically wraps both sent and received value into
2733    * DBUS's wrapper type.
2734    */
2735   template < typename T >
2736   struct Property
2737   {
2738     /// \cond
2739     using RetType = typename detail::dbus_interface_return_type_traits< T >::type;
2740     using VariantRetType = typename detail::dbus_interface_return_type_traits< EldbusVariant< T > >::type;
2741     const detail::ConnectionState &connectionState;
2742     std::string propName;
2743     std::string info;
2744     std::shared_ptr< ConnectionInfo > connectionInfo;
2745     /// \endcond
2746
2747     /**
2748      * @brief executes synchronous get on property
2749      *
2750      * The function returns ValueOrError<...> object, which
2751      * contains either received values or error message.
2752      */
2753     RetType get()
2754     {
2755       detail::CallId callId;
2756       detail::displayDebugCallInfoProperty( callId, "Get", info, connectionInfo->interfaceName, propName );
2757       auto z = detail::call< VariantRetType >( callId, connectionState, true, "Get", connectionInfo->interfaceName, propName );
2758       if( !z )
2759         return z.getError();
2760       return {std::get< 0 >( z.getValues() ).value};
2761     }
2762
2763     /**
2764      * @brief executes asynchronous get on property
2765      *
2766      * The function calls callback with either received values or error message.
2767      *
2768      * @param callback callback functor, which will be called with return value(s) or error message
2769      */
2770     void asyncGet( std::function< void( RetType ) > callback )
2771     {
2772       detail::CallId callId;
2773       detail::displayDebugCallInfoProperty( callId, "Get", info, connectionInfo->interfaceName, propName );
2774       auto cc = [callback]( VariantRetType reply ) {
2775         if( reply )
2776           callback( std::move( std::get< 0 >( reply.getValues() ).value ) );
2777         else
2778           callback( reply.getError() );
2779       };
2780       detail::asyncCall< VariantRetType >( callId, connectionState, true, "Get", std::move( cc ), connectionInfo->interfaceName, propName );
2781     }
2782
2783     /**
2784      * @brief executes synchronous set on property
2785      *
2786      * The function returns ValueOrError<void> object, with
2787      * possible error message.
2788      */
2789     ValueOrError< void > set( const T& r )
2790     {
2791       detail::CallId callId;
2792       detail::displayDebugCallInfoProperty( callId, "Set", info, connectionInfo->interfaceName, propName );
2793       EldbusVariant< T > variantValue{std::move( r )};
2794       return detail::call< ValueOrError< void > >( callId, connectionState, true, "Set", connectionInfo->interfaceName, propName, variantValue );
2795     }
2796
2797     /**
2798      * @brief executes asynchronous get on property
2799      *
2800      * The function calls callback with either received values or error message.
2801      *
2802      * @param callback callback functor, which will be called with return value(s) or error message
2803      */
2804     void asyncSet( std::function< void( ValueOrError< void > ) > callback, const T& r )
2805     {
2806       detail::CallId callId;
2807       detail::displayDebugCallInfoProperty( callId, "Set", info, connectionInfo->interfaceName, propName );
2808       EldbusVariant< T > variantValue{std::move( r )};
2809       detail::asyncCall< ValueOrError< void > >( callId, connectionState, true, "Set", std::move( callback ), connectionInfo->interfaceName, propName, variantValue );
2810     }
2811   };
2812
2813   /**
2814    * @brief Constructs Property<...> object for calling properties
2815    *
2816    * The function constructs and returns proxy object for calling property.
2817    *
2818    * @param propName property name to set and / or query
2819    */
2820   template < typename PropertyType >
2821   Property< PropertyType > property( std::string propName )
2822   {
2823     return Property< PropertyType >{*connectionState, std::move( propName ), info, connectionInfo};
2824   }
2825
2826   /**
2827    * @brief Constructs Method<...> object for calling methods
2828    *
2829    * The function constructs and returns proxy object for calling method.
2830    *
2831    * @param funcName function name to call
2832    */
2833   template < typename MethodType >
2834   Method< MethodType > method( std::string funcName )
2835   {
2836     return Method< MethodType >{*connectionState, std::move( funcName ), info, connectionInfo};
2837   }
2838
2839   /**
2840    * @brief Registers notification callback, when property has changed
2841    *
2842    * The callback will be called with new value, when property's value has changed.
2843    * Note, that template type V must match expected type, otherwise undefined behavior will occur,
2844    * there's no check for this.
2845    */
2846   template < typename V >
2847   void addPropertyChangedEvent( std::string propertyName, std::function< void( V ) > callback )
2848   {
2849     detail::CallId callId;
2850     detail::displayDebugCallInfoSignal( callId, propertyName, info, connectionInfo->interfaceName );
2851     DBUS_DEBUG( "call %d: adding property", callId.id );
2852     auto &cI = this->connectionInfo;
2853     DBUS_W->add_property_changed_event_listener_impl(connectionState->proxy, cI->interfaceName, propertyName,
2854       [callback]( const _Eina_Value *newValue ) {
2855       V val = 0;
2856       if( !getFromEinaValue( newValue, &val ) )
2857       {
2858         DBUS_DEBUG( "unable to get property's value" );
2859         return;
2860       }
2861       callback( val );
2862     });
2863   }
2864
2865   /**
2866    * @brief Registers callback on the DBUS' signal
2867    *
2868    * The function registers callback signalName. When signal comes, callback will be called.
2869    * Callback object will exists as long as signal is registered. You can unregister signal
2870    * by destroying DBusClient object.
2871    *
2872    * @param signalName name of the signal to register
2873    * @param callback callback to call
2874    */
2875   template < typename SignalType >
2876   void addSignal( std::string signalName, std::function< SignalType > callback )
2877   {
2878     detail::CallId callId;
2879     detail::displayDebugCallInfoSignal( callId, signalName, info, connectionInfo->interfaceName );
2880     DBUS_W->eldbus_proxy_signal_handler_add_impl( connectionState->proxy, signalName,
2881       [callId, callback, signalName]( const DBusWrapper::MessagePtr &msg ) -> void {
2882         std::string errname, aux;
2883         if( DBUS_W->eldbus_message_error_get_impl( msg, errname, aux ) )
2884         {
2885           DBUS_DEBUG( "call %d: Eldbus error: %s %s", callId.id, errname.c_str(), aux.c_str() );
2886           return;
2887         }
2888         DBUS_DEBUG( "call %d: received signal with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl( msg ).c_str() );
2889         using ParamsType = typename detail::dbus_interface_traits< SignalType >::VEArgs;
2890         auto params = detail::unpackValues< ParamsType >( callId, msg );
2891         if( !params )
2892         {
2893           DBUS_DEBUG( "call %d: failed: %s", callId.id, params.getError().message.c_str() );
2894           return;
2895         }
2896         try
2897         {
2898           detail::apply( callback, params.getValues() );
2899         }
2900         catch( ... )
2901         {
2902           DBUS_DEBUG( "unhandled exception" );
2903           bart_assert( 0 );
2904         }
2905       });
2906   }
2907
2908 private:
2909   /// \cond
2910   std::unique_ptr<detail::ConnectionState> connectionState{ new detail::ConnectionState };
2911   std::string info;
2912   std::shared_ptr< ConnectionInfo > connectionInfo;
2913
2914   static bool getFromEinaValue(const _Eina_Value *v, void *dst);
2915   /// \endcond
2916 };
2917
2918 /**
2919  * @brief Helper class describing DBUS's server interface
2920  *
2921  */
2922 class DBusInterfaceDescription
2923 {
2924   friend class DBusServer;
2925
2926 public:
2927   /// \cond
2928   using MethodInfo = DBusWrapper::MethodInfo;
2929   using SignalInfo = DBusWrapper::SignalInfo;
2930   using PropertyInfo = DBusWrapper::PropertyInfo;
2931   using SignalId = DBusWrapper::SignalId;
2932   /// \endcond
2933
2934   /**
2935    * @brief Creates empty interface description with given name
2936    *
2937    * @param interfaceName name of the interface
2938    */
2939   DBusInterfaceDescription( std::string interfaceName );
2940
2941   /**
2942    * @brief adds new, synchronous method to the interface
2943    *
2944    * When method memberName is called on DBUS, callback functor will be called
2945    * with values received from DBUS. callback won't be called, if method was
2946    * called with invalid signature. Value returned from functor (or error message)
2947    * will be marshalled back to the caller.
2948    *
2949    * Template type T defines both arguments sent to the method
2950    * and expected values. Receiving different values will be reported as
2951    * error. For example:
2952    * \code{.cpp} Method<int(float, float)> \endcode
2953    * defines method, which takes two arguments (two floats) and return
2954    * single value of type int.
2955    *
2956    * @param memberName name of the method
2957    * @param callback functor, which will be called
2958    */
2959   template < typename T >
2960   void addMethod( const std::string& memberName, typename detail::dbus_interface_traits< T >::SyncCB callback )
2961   {
2962     detail::CallId callId;
2963     MethodInfo mi;
2964     methods.push_back( std::move( mi ) );
2965     auto& z = methods.back();
2966     z.in = detail::EldbusArgGenerator_Args< T >::get( );
2967     z.out = detail::EldbusArgGenerator_ReturnType< T >::get( );
2968     z.memberName = memberName;
2969     DBUS_DEBUG( "call %d: method %s, in %s, out %s", callId.id, memberName.c_str(),
2970                 detail::EldbusArgGenerator_Args< T >::name().c_str(),
2971                 detail::EldbusArgGenerator_ReturnType< T >::name().c_str() );
2972     z.callback = construct< T >( callId, callback );
2973     z.id = callId;
2974   }
2975
2976   /**
2977    * @brief adds new, synchronous property to the interface
2978    *
2979    * When property memberName is called on DBUS, respective callback functor will be called
2980    * with values received from DBUS. callback won't be called, if method was
2981    * called with invalid signature. Value returned from functor (or error message)
2982    * will be marshalled back to the caller.
2983    *
2984    * Template type T defines type of the value hidden under property.
2985    * Note, that library automatically wraps both sent and received value into
2986    * DBUS's wrapper type.
2987    *
2988    * @param memberName name of the method
2989    * @param getter functor, which will be called when property is being read
2990    * @param setter functor, which will be called when property is being set
2991    */
2992   template < typename T >
2993   void addProperty( const std::string& memberName, std::function< ValueOrError< T >() > getter, std::function< ValueOrError< void >( T ) > setter )
2994   {
2995     properties.push_back( {} );
2996     auto& z = properties.back();
2997     z.memberName = memberName;
2998     z.typeSignature = detail::signature< T >::sig();
2999     if( getter )
3000     {
3001       detail::CallId getterId;
3002       z.getterId = getterId;
3003       DBUS_DEBUG( "call %d: property %s (get) type %s", getterId.id, memberName.c_str(), detail::signature< T >::name().c_str() );
3004       z.getCallback = [=]( const DBusWrapper::MessagePtr &src, const DBusWrapper::MessageIterPtr &dst ) -> std::string {
3005         try
3006         {
3007           auto v = detail::apply( getter, std::tuple<>{} );
3008           if( v )
3009           {
3010             detail::signature< T >::set( dst, std::get< 0 >( v.getValues() ) );
3011             DBUS_DEBUG( "call %d: success", getterId.id );
3012             return "";
3013           }
3014           DBUS_DEBUG( "call %d: failed: %s", getterId.id, v.getError().message.c_str() );
3015           return v.getError().message;
3016         }
3017         catch( std::exception& e )
3018         {
3019           return std::string( "unhandled exception (" ) + e.what() + ")";
3020         }
3021         catch( ... )
3022         {
3023           return "unhandled exception";
3024         }
3025       };
3026     }
3027     if( setter )
3028     {
3029       detail::CallId setterId;
3030       z.setterId = setterId;
3031       DBUS_DEBUG( "call %d: property %s (set) type %s", setterId.id, memberName.c_str(), detail::signature< T >::name().c_str() );
3032       z.setCallback = [=]( const DBusWrapper::MessagePtr &src, const DBusWrapper::MessageIterPtr &src_iter ) -> std::string {
3033         std::tuple< T > value;
3034         auto src_signature = DBUS_W->eldbus_message_iter_signature_get_impl( src_iter );
3035         if( detail::signature< T >::get( src_iter, std::get< 0 >( value ) ) )
3036         {
3037           try
3038           {
3039             auto v = detail::apply( setter, std::move( value ) );
3040             if( v )
3041             {
3042               DBUS_DEBUG( "call %d: success", setterId.id );
3043               return "";
3044             }
3045             DBUS_DEBUG( "call %d: failed: %s", setterId.id, v.getError().message.c_str() );
3046             return v.getError().message;
3047           }
3048           catch( std::exception& e )
3049           {
3050             return std::string( "unhandled exception (" ) + e.what() + ")";
3051           }
3052           catch( ... )
3053           {
3054             return "unhandled exception";
3055           }
3056         }
3057         DBUS_DEBUG( "call %d: failed to unpack values, got signature '%s', expected '%s'", setterId.id,
3058                     src_signature.c_str(), detail::signature< T >::sig().c_str() );
3059         return "call " + std::to_string( setterId.id ) + ": failed to unpack values, got signature '" +
3060                      src_signature + "', expected '" + detail::signature< T >::sig() + "'";
3061       };
3062     }
3063   }
3064
3065   /**
3066    * @brief adds new signal to the interface
3067    *
3068    * Template types ARGS defines values, which will be emited with the signal
3069    *
3070    * @param memberName name of the method
3071    */
3072   template < typename... ARGS >
3073   SignalId addSignal( const std::string& memberName )
3074   {
3075     detail::CallId callId;
3076     signals.push_back( {} );
3077     auto& z = signals.back();
3078     z.memberName = memberName;
3079     z.args = detail::EldbusArgGenerator_Args< void( ARGS... ) >::get( DBUS_W->Strings );
3080     z.id = callId;
3081     DBUS_DEBUG( "call %d: signal %s", callId.id, memberName.c_str() );
3082     return SignalId{callId};
3083   }
3084
3085 private:
3086   /// \cond
3087   std::vector< MethodInfo > methods;
3088   std::vector< PropertyInfo > properties;
3089   std::vector< SignalInfo > signals;
3090   std::string interfaceName;
3091
3092   template < typename T >
3093   std::function< DBusWrapper::MessagePtr( const DBusWrapper::MessagePtr &msg ) > construct( detail::CallId callId,
3094                                                                            typename detail::dbus_interface_traits< T >::SyncCB callback )
3095   {
3096     using VEArgs = typename detail::dbus_interface_traits< T >::VEArgs;
3097     return [=]( const DBusWrapper::MessagePtr &msg ) -> DBusWrapper::MessagePtr {
3098       DBUS_DEBUG( "call %d: entering", callId.id );
3099       DBusWrapper::MessagePtr ret = {};
3100       auto args = detail::unpackValues< VEArgs >( callId, msg );
3101       if( args )
3102       {
3103         try
3104         {
3105           auto v = detail::apply( callback, std::move( args.getValues() ) );
3106           if( v )
3107           {
3108             DBUS_DEBUG( "call %d: success", callId.id );
3109             ret = DBUS_W->eldbus_message_method_return_new_impl( msg );
3110             detail::packValues( callId, ret, v );
3111           }
3112           else
3113           {
3114             DBUS_DEBUG( "call %d: failed: %s", callId.id, v.getError().message.c_str() );
3115             ret = DBUS_W->eldbus_message_error_new_impl( msg, "org.freedesktop.DBus.Error.Failed", v.getError().message );
3116           }
3117         }
3118         catch( std::exception& e )
3119         {
3120           auto txt = std::string( "unhandled exception (" ) + e.what() + ")";
3121           DBUS_DEBUG( "call %d: failed: %s", callId.id, txt.c_str() );
3122           ret = DBUS_W->eldbus_message_error_new_impl( msg, "org.freedesktop.DBus.Error.Failed", txt );
3123         }
3124         catch( ... )
3125         {
3126           DBUS_DEBUG( "call %d: failed: %s", callId.id, "unhandled exception" );
3127           ret = DBUS_W->eldbus_message_error_new_impl( msg, "org.freedesktop.DBus.Error.Failed", "unhandled exception" );
3128         }
3129       }
3130       else
3131       {
3132         std::ostringstream err;
3133         err << "expected signature '" << detail::signature< VEArgs >::sig() << "', got '" << DBUS_W->eldbus_message_signature_get_impl( msg ) << "'";
3134         auto str = err.str();
3135         DBUS_DEBUG( "call %d: failed: %s", callId.id, str.c_str() );
3136         ret = DBUS_W->eldbus_message_error_new_impl( msg, "org.freedesktop.DBus.Error.InvalidArgs", str );
3137       }
3138       return ret;
3139     };
3140   }
3141   /// \endcond
3142 };
3143
3144 /**
3145  * @brief Class representing server's end of DBUS connection
3146  *
3147  * Allows listening (synchronously and asynchronosly) on methods on selected interface
3148  * Allows listening (synchronously and asynchronosly) on setting / getting properties.
3149  * Allows emiting signals.
3150  */
3151 class DBusServer
3152 {
3153 public:
3154   /**
3155    * @brief Constructs non-connected dbus server.
3156    */
3157   DBusServer() = default;
3158
3159   /**
3160    * @brief Constructs dbus server on either system or user dbus connection.
3161    */
3162   DBusServer( ConnectionType tp );
3163
3164   /**
3165    * @brief Constructs dbus server on connection from getDBusConnectionByType
3166    */
3167   DBusServer( const DBusWrapper::ConnectionPtr &conn );
3168
3169   /**
3170    * @brief Destructor
3171    *
3172    * Destructor will properly destroy everything. Destructor will cancel
3173    * pending replies.
3174    */
3175   ~DBusServer() = default;
3176
3177   DBusServer( const DBusServer& ) = delete;
3178   DBusServer( DBusServer&& ) = default;
3179
3180   DBusServer& operator=( DBusServer&& ) = default;
3181   DBusServer& operator=( const DBusServer& ) = delete;
3182
3183   /**
3184    * @brief Registers interface on given path name
3185    *
3186    * @param pathName path object to register interface on.
3187    * @param dscr
3188    * @param fallback
3189    */
3190   void addInterface( const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback = false );
3191
3192   /**
3193    * @brief Gets bus name of the current connection (must be connected)
3194    */
3195   std::string getBusName() const;
3196
3197   /**
3198    * @brief Returns connection object for this dbus server object
3199    *
3200    * @return connection object
3201    */
3202   DBusWrapper::ConnectionPtr getConnection();
3203
3204   /**
3205    * @brief Emits signal
3206    *
3207    * Emits signal based only on data passed to the function
3208    *
3209    * @param signal identifier of the signal
3210    * @param args values to emit
3211    */
3212   template < typename... ARGS >
3213   void emit2( const std::string& path, const std::string& interfaceName,
3214               const std::string& signalName, const ARGS&... args )
3215   {
3216     auto msg = DBUS_W->eldbus_message_signal_new_impl( path, interfaceName, signalName );
3217     detail::CallId id;
3218     detail::packValues( id, msg, args... );
3219     DBUS_W->eldbus_connection_send_impl( connection, msg );
3220   }
3221
3222   /**
3223    * @brief Returns current object path, when handling call to property / method
3224    *
3225    * User can call this function from inside callback used to handle property / method calls.
3226    * It will retrieve object's path used in the call. Note, that in asynchronous handling
3227    * of those calls user need to retrieve and store the current object / current connection
3228    * as the value will change at the moment user's callback handling will exit. For example:
3229    * \code{.cpp}
3230    * DBusInterfaceDescription interface{"name"};
3231    * auto handler_later = [](std::function<void(void)> done_cb) {
3232    *   // process something later on
3233    *   DBusServer::getCurrentObjectPath(); // this will return empty string
3234    * };
3235    * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
3236    *   DBusServer::getCurrentObjectPath(); // this will current object's path
3237    *
3238    *   // do some processing later on and call done_cb, when it's done
3239    *   register_to_call_sometime_later_on(std::move(done_cb));
3240    * };
3241    * \endcode
3242    */
3243   static std::string getCurrentObjectPath() { return currentObjectPath; }
3244
3245   /**
3246    * @brief Returns current connection object, when handling call to property / method
3247    *
3248    * User can call this function from inside callback used to handle property / method calls.
3249    * It will retrieve object's path used in the call. Note, that in asynchronous handling
3250    * of those calls user need to retrieve and store the current object / current connection
3251    * as the value will change at the moment user's callback handling will exit. For example:
3252    * \code{.cpp}
3253    * DBusInterfaceDescription interface{"name"};
3254    * auto handler_later = [](std::function<void(void)> done_cb) {
3255    *   // process something later on
3256    *   DBusServer::getCurrentObjectPath(); // this will return empty string
3257    * };
3258    * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
3259    *   DBusServer::getCurrentObjectPath(); // this will current object's path
3260    *
3261    *   // do some processing later on and call done_cb, when it's done
3262    *   register_to_call_sometime_later_on(std::move(done_cb));
3263    * };
3264    * \endcode
3265    */
3266   static const DBusWrapper::ConnectionPtr &getCurrentConnection() { return currentConnection; }
3267
3268   /// \cond
3269   class CurrentObjectSetter
3270   {
3271   public:
3272     CurrentObjectSetter( DBusWrapper::ConnectionPtr con, std::string path )
3273     {
3274       currentObjectPath = std::move(path);
3275       currentConnection = std::move( con );
3276     }
3277     ~CurrentObjectSetter()
3278     {
3279       currentObjectPath = "";
3280       currentConnection = {};
3281     }
3282     CurrentObjectSetter( const CurrentObjectSetter& ) = delete;
3283     CurrentObjectSetter( CurrentObjectSetter&& ) = delete;
3284     void operator=( const CurrentObjectSetter& ) = delete;
3285     void operator=( CurrentObjectSetter&& ) = delete;
3286   };
3287   /// \endcond
3288
3289 private:
3290   /// \cond
3291   DBusWrapper::ConnectionPtr connection;
3292   struct DestructorObject {
3293     std::vector<std::function<void()>> destructors;
3294     ~DestructorObject() {
3295       for(auto &a : destructors) a();
3296     }
3297   };
3298
3299   std::unique_ptr<DestructorObject> destructorObject { new DestructorObject() };
3300   static thread_local std::string currentObjectPath;
3301   static thread_local DBusWrapper::ConnectionPtr currentConnection;
3302
3303   /// \endcond
3304 };
3305
3306 /// \cond
3307 DBusWrapper::ConnectionPtr getDBusConnectionByType( ConnectionType tp );
3308 DBusWrapper::ConnectionPtr getDBusConnectionByName( const std::string& name );
3309 std::string getConnectionName( const DBusWrapper::ConnectionPtr& );
3310 /// \endcond
3311 }
3312