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