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