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