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