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