sdbus-c++ 2.1.0
High-level C++ D-Bus library based on systemd D-Bus implementation
Loading...
Searching...
No Matches
Types.h
Go to the documentation of this file.
1
26
27#ifndef SDBUS_CXX_TYPES_H_
28#define SDBUS_CXX_TYPES_H_
29
30#include <sdbus-c++/Message.h>
32
33#include <cstring>
34#include <cstddef>
35#include <memory>
36#include <string>
37#include <tuple>
38#include <type_traits>
39#include <typeinfo>
40#include <utility>
41
42namespace sdbus {
43
44 /********************************************/
56 class Variant
57 {
58 public:
59 Variant();
60
61 template <typename _ValueType>
62 explicit Variant(const _ValueType& value) : Variant()
63 {
64 msg_.openVariant<_ValueType>();
65 msg_ << value;
66 msg_.closeVariant();
67 msg_.seal();
68 }
69
70 Variant(const Variant& value, embed_variant_t) : Variant()
71 {
72 msg_.openVariant<Variant>();
73 msg_ << value;
74 msg_.closeVariant();
75 msg_.seal();
76 }
77
78 template <typename _Struct>
79 explicit Variant(const as_dictionary<_Struct>& value) : Variant()
80 {
81 msg_.openVariant<std::map<std::string, Variant>>();
82 msg_ << as_dictionary(value.m_struct);
83 msg_.closeVariant();
84 msg_.seal();
85 }
86
87 template <typename... _Elements>
88 Variant(const std::variant<_Elements...>& value)
89 : Variant()
90 {
91 msg_ << value;
92 msg_.seal();
93 }
94
95 template <typename _ValueType>
96 _ValueType get() const
97 {
98 msg_.rewind(false);
99
100 msg_.enterVariant<_ValueType>();
101 _ValueType val;
102 msg_ >> val;
103 msg_.exitVariant();
104 return val;
105 }
106
107 // Only allow conversion operator for true D-Bus type representations in C++
108 template <typename _ValueType, typename = std::enable_if_t<signature_of<_ValueType>::is_valid>>
109 explicit operator _ValueType() const
110 {
111 return get<_ValueType>();
112 }
113
114 template <typename... _Elements>
115 operator std::variant<_Elements...>() const
116 {
117 std::variant<_Elements...> result;
118 msg_.rewind(false);
119 msg_ >> result;
120 return result;
121 }
122
123 template <typename _Type>
124 bool containsValueOfType() const
125 {
126 constexpr auto signature = as_null_terminated(signature_of_v<_Type>);
127 return std::strcmp(signature.data(), peekValueType()) == 0;
128 }
129
130 bool isEmpty() const;
131
132 void serializeTo(Message& msg) const;
133 void deserializeFrom(Message& msg);
134 const char* peekValueType() const;
135
136 private:
137 mutable PlainMessage msg_{};
138 };
139
140 /********************************************/
150 template <typename... _ValueTypes>
151 class Struct
152 : public std::tuple<_ValueTypes...>
153 {
154 public:
155 using std::tuple<_ValueTypes...>::tuple;
156
157 Struct() = default;
158
159 explicit Struct(const std::tuple<_ValueTypes...>& t)
160 : std::tuple<_ValueTypes...>(t)
161 {
162 }
163
164 template <std::size_t _I>
165 auto& get()
166 {
167 return std::get<_I>(*this);
168 }
169
170 template <std::size_t _I>
171 const auto& get() const
172 {
173 return std::get<_I>(*this);
174 }
175 };
176
177 template <typename... _Elements>
178 Struct(_Elements...) -> Struct<_Elements...>;
179
180 template<typename... _Elements>
182 make_struct(_Elements&&... args)
183 {
185 return result_type(std::forward<_Elements>(args)...);
186 }
187
188 /********************************************/
194 class ObjectPath : public std::string
195 {
196 public:
197 ObjectPath() = default;
198 explicit ObjectPath(std::string value)
199 : std::string(std::move(value))
200 {}
201 explicit ObjectPath(const char* value)
202 : std::string(value)
203 {}
204
205 using std::string::operator=;
206 };
207
208 /********************************************/
214 class BusName : public std::string
215 {
216 public:
217 BusName() = default;
218 explicit BusName(std::string value)
219 : std::string(std::move(value))
220 {}
221 explicit BusName(const char* value)
222 : std::string(value)
223 {}
224
225 using std::string::operator=;
226 };
227
228 using ServiceName = BusName;
229 using ConnectionName = BusName;
230
231 /********************************************/
237 class InterfaceName : public std::string
238 {
239 public:
240 InterfaceName() = default;
241 explicit InterfaceName(std::string value)
242 : std::string(std::move(value))
243 {}
244 explicit InterfaceName(const char* value)
245 : std::string(value)
246 {}
247
248 using std::string::operator=;
249 };
250
251 /********************************************/
257 class MemberName : public std::string
258 {
259 public:
260 MemberName() = default;
261 explicit MemberName(std::string value)
262 : std::string(std::move(value))
263 {}
264 explicit MemberName(const char* value)
265 : std::string(value)
266 {}
267
268 using std::string::operator=;
269 };
270
271 using MethodName = MemberName;
272 using SignalName = MemberName;
273 using PropertyName = MemberName;
274
275 /********************************************/
281 class Signature : public std::string
282 {
283 public:
284 Signature() = default;
285 explicit Signature(std::string value)
286 : std::string(std::move(value))
287 {}
288 explicit Signature(const char* value)
289 : std::string(value)
290 {}
291
292 using std::string::operator=;
293 };
294
295 /********************************************/
306 class UnixFd
307 {
308 public:
309 UnixFd() = default;
310
311 explicit UnixFd(int fd)
312 : fd_(checkedDup(fd))
313 {
314 }
315
316 UnixFd(int fd, adopt_fd_t)
317 : fd_(fd)
318 {
319 }
320
321 UnixFd(const UnixFd& other)
322 {
323 *this = other;
324 }
325
326 UnixFd& operator=(const UnixFd& other)
327 {
328 if (this == &other)
329 {
330 return *this;
331 }
332 close();
333 fd_ = checkedDup(other.fd_);
334 return *this;
335 }
336
337 UnixFd(UnixFd&& other)
338 {
339 *this = std::move(other);
340 }
341
342 UnixFd& operator=(UnixFd&& other)
343 {
344 if (this == &other)
345 {
346 return *this;
347 }
348 close();
349 fd_ = std::exchange(other.fd_, -1);
350 return *this;
351 }
352
353 ~UnixFd()
354 {
355 close();
356 }
357
358 [[nodiscard]] int get() const
359 {
360 return fd_;
361 }
362
363 void reset(int fd = -1)
364 {
365 *this = UnixFd{fd};
366 }
367
368 void reset(int fd, adopt_fd_t)
369 {
370 *this = UnixFd{fd, adopt_fd};
371 }
372
373 int release()
374 {
375 return std::exchange(fd_, -1);
376 }
377
378 [[nodiscard]] bool isValid() const
379 {
380 return fd_ >= 0;
381 }
382
383 private:
385 void close();
386
389 static int checkedDup(int fd);
390
391 int fd_ = -1;
392 };
393
394 /********************************************/
401 template<typename _T1, typename _T2>
402 using DictEntry = std::pair<_T1, _T2>;
403
404}
405
406// Making sdbus::Struct implement the tuple-protocol, i.e. be a tuple-like type
407template <size_t _I, typename... _ValueTypes>
408struct std::tuple_element<_I, sdbus::Struct<_ValueTypes...>>
409 : std::tuple_element<_I, std::tuple<_ValueTypes...>>
410{};
411template <typename... _ValueTypes>
412struct std::tuple_size<sdbus::Struct<_ValueTypes...>>
413 : std::tuple_size<std::tuple<_ValueTypes...>>
414{};
415
416/********************************************/
453#define SDBUSCPP_REGISTER_STRUCT(STRUCT, ...) \
454 namespace sdbus { \
455 static_assert(SDBUSCPP_PP_NARG(__VA_ARGS__) <= 16, \
456 "Not more than 16 struct members are supported, please open an issue if you need more"); \
457 \
458 template <> \
459 struct signature_of<STRUCT> \
460 : signature_of<sdbus::Struct<SDBUSCPP_STRUCT_MEMBER_TYPES(STRUCT, __VA_ARGS__)>> \
461 {}; \
462 \
463 inline auto as_dictionary_if_struct(const STRUCT& object) \
464 { \
465 return as_dictionary<STRUCT>(object); \
466 } \
467 \
468 inline sdbus::Message& operator<<(sdbus::Message& msg, const STRUCT& items) \
469 { \
470 return msg << sdbus::Struct{std::forward_as_tuple(SDBUSCPP_STRUCT_MEMBERS(items, __VA_ARGS__))}; \
471 } \
472 \
473 inline Message& operator<<(Message& msg, const as_dictionary<STRUCT>& s) \
474 { \
475 if constexpr (!nested_struct_as_dict_serialization_v<STRUCT>) \
476 return msg.serializeDictionary<std::string, Variant>({SDBUSCPP_STRUCT_MEMBERS_AS_DICT_ENTRIES(s.m_struct, __VA_ARGS__)}); \
477 else \
478 return msg.serializeDictionary<std::string, Variant>({SDBUSCPP_STRUCT_MEMBERS_AS_NESTED_DICT_ENTRIES(s.m_struct, __VA_ARGS__)}); \
479 } \
480 \
481 inline Message& operator>>(Message& msg, STRUCT& s) \
482 { \
483 /* First, try to deserialize as a struct */ \
484 if (msg.peekType().first == signature_of<STRUCT>::type_value) \
485 { \
486 Struct sdbusStruct{std::forward_as_tuple(SDBUSCPP_STRUCT_MEMBERS(s, __VA_ARGS__))}; \
487 return msg >> sdbusStruct; \
488 } \
489 \
490 /* Otherwise try to deserialize as a dictionary of strings to variants */ \
491 \
492 return msg.deserializeDictionary<std::string, Variant>([&s](const auto& dictEntry) \
493 { \
494 const std::string& key = dictEntry.first; /* Intentionally not using structured bindings */ \
495 const Variant& value = dictEntry.second; \
496 \
497 using namespace std::string_literals; \
498 /* This also handles members which are structs serialized as dict of strings to variants, recursively */ \
499 SDBUSCPP_FIND_AND_DESERIALIZE_STRUCT_MEMBERS(s, __VA_ARGS__) \
500 SDBUS_THROW_ERROR_IF( strict_dict_as_struct_deserialization_v<STRUCT> \
501 , ("Failed to deserialize struct from a dictionary: could not find field '"s += key) += "' in struct 'my::Struct'" \
502 , EINVAL ); \
503 }); \
504 } \
505 } \
506 /**/
507
508/********************************************/
520#define SDBUSCPP_ENABLE_RELAXED_DICT2STRUCT_DESERIALIZATION(STRUCT) \
521 template <> \
522 constexpr auto sdbus::strict_dict_as_struct_deserialization_v<STRUCT> = false; \
523 /**/
524
525/********************************************/
537#define SDBUSCPP_ENABLE_NESTED_STRUCT2DICT_SERIALIZATION(STRUCT) \
538 template <> \
539 constexpr auto sdbus::nested_struct_as_dict_serialization_v<STRUCT> = true \
540 /**/
541
547#define SDBUSCPP_STRUCT_MEMBERS(STRUCT, ...) \
548 SDBUSCPP_PP_CAT(SDBUSCPP_FOR_EACH_, SDBUSCPP_PP_NARG(__VA_ARGS__))(SDBUSCPP_STRUCT_MEMBER, SDBUSCPP_PP_COMMA, STRUCT, __VA_ARGS__) \
549 /**/
550#define SDBUSCPP_STRUCT_MEMBER(STRUCT, MEMBER) STRUCT.MEMBER
551
552#define SDBUSCPP_STRUCT_MEMBER_TYPES(STRUCT, ...) \
553 SDBUSCPP_PP_CAT(SDBUSCPP_FOR_EACH_, SDBUSCPP_PP_NARG(__VA_ARGS__))(SDBUSCPP_STRUCT_MEMBER_TYPE, SDBUSCPP_PP_COMMA, STRUCT, __VA_ARGS__) \
554 /**/
555#define SDBUSCPP_STRUCT_MEMBER_TYPE(STRUCT, MEMBER) decltype(STRUCT::MEMBER)
556
557#define SDBUSCPP_STRUCT_MEMBERS_AS_DICT_ENTRIES(STRUCT, ...) \
558 SDBUSCPP_PP_CAT(SDBUSCPP_FOR_EACH_, SDBUSCPP_PP_NARG(__VA_ARGS__))(SDBUSCPP_STRUCT_MEMBER_AS_DICT_ENTRY, SDBUSCPP_PP_COMMA, STRUCT, __VA_ARGS__) \
559 /**/
560#define SDBUSCPP_STRUCT_MEMBER_AS_DICT_ENTRY(STRUCT, MEMBER) {#MEMBER, Variant{STRUCT.MEMBER}}
561
562#define SDBUSCPP_STRUCT_MEMBERS_AS_NESTED_DICT_ENTRIES(STRUCT, ...) \
563 SDBUSCPP_PP_CAT(SDBUSCPP_FOR_EACH_, SDBUSCPP_PP_NARG(__VA_ARGS__))(SDBUSCPP_STRUCT_MEMBER_AS_NESTED_DICT_ENTRY, SDBUSCPP_PP_COMMA, STRUCT, __VA_ARGS__) \
564 /**/
565#define SDBUSCPP_STRUCT_MEMBER_AS_NESTED_DICT_ENTRY(STRUCT, MEMBER) {#MEMBER, Variant{as_dictionary_if_struct(STRUCT.MEMBER)}}
566
567#define SDBUSCPP_FIND_AND_DESERIALIZE_STRUCT_MEMBERS(STRUCT, ...) \
568 SDBUSCPP_PP_CAT(SDBUSCPP_FOR_EACH_, SDBUSCPP_PP_NARG(__VA_ARGS__))(SDBUSCPP_FIND_AND_DESERIALIZE_STRUCT_MEMBER, SDBUSCPP_PP_SPACE, STRUCT, __VA_ARGS__) \
569 /**/
570#define SDBUSCPP_FIND_AND_DESERIALIZE_STRUCT_MEMBER(STRUCT, MEMBER) if (key == #MEMBER) STRUCT.MEMBER = value.get<decltype(STRUCT.MEMBER)>(); else
571
572#define SDBUSCPP_FOR_EACH_1(M, D, S, M1) M(S, M1)
573#define SDBUSCPP_FOR_EACH_2(M, D, S, M1, M2) M(S, M1) D M(S, M2)
574#define SDBUSCPP_FOR_EACH_3(M, D, S, M1, M2, M3) M(S, M1) D M(S, M2) D M(S, M3)
575#define SDBUSCPP_FOR_EACH_4(M, D, S, M1, M2, M3, M4) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4)
576#define SDBUSCPP_FOR_EACH_5(M, D, S, M1, M2, M3, M4, M5) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5)
577#define SDBUSCPP_FOR_EACH_6(M, D, S, M1, M2, M3, M4, M5, M6) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6)
578#define SDBUSCPP_FOR_EACH_7(M, D, S, M1, M2, M3, M4, M5, M6, M7) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7)
579#define SDBUSCPP_FOR_EACH_8(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8)
580#define SDBUSCPP_FOR_EACH_9(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9)
581#define SDBUSCPP_FOR_EACH_10(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10)
582#define SDBUSCPP_FOR_EACH_11(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11)
583#define SDBUSCPP_FOR_EACH_12(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11) D M(S, M12)
584#define SDBUSCPP_FOR_EACH_13(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11) D M(S, M12) D M(S, M13)
585#define SDBUSCPP_FOR_EACH_14(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11) D M(S, M12) D M(S, M13) D M(S, M14)
586#define SDBUSCPP_FOR_EACH_15(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11) D M(S, M12) D M(S, M13) D M(S, M14) D M(S, M15)
587#define SDBUSCPP_FOR_EACH_16(M, D, S, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15, M16) M(S, M1) D M(S, M2) D M(S, M3) D M(S, M4) D M(S, M5) D M(S, M6) D M(S, M7) D M(S, M8) D M(S, M9) D M(S, M10) D M(S, M11) D M(S, M12) D M(S, M13) D M(S, M14) D M(S, M15) D M(S, M16)
588
589#define SDBUSCPP_PP_CAT(X, Y) SDBUSCPP_PP_CAT_IMPL(X, Y)
590#define SDBUSCPP_PP_CAT_IMPL(X, Y) X##Y
591#define SDBUSCPP_PP_NARG(...) SDBUSCPP_PP_NARG_IMPL(__VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
592#define SDBUSCPP_PP_NARG_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _N, ...) _N
593
594#define SDBUSCPP_PP_COMMA ,
595#define SDBUSCPP_PP_SPACE
596
597#endif /* SDBUS_CXX_TYPES_H_ */
std::pair< _T1, _T2 > DictEntry
Definition Types.h:402
Definition Types.h:215
Definition Types.h:258
Definition Message.h:81
Definition Message.h:333
Definition Types.h:153
Definition TypeTraits.h:97
Definition TypeTraits.h:585
Definition TypeTraits.h:110