27#ifndef SDBUS_CXX_MESSAGE_H_
28#define SDBUS_CXX_MESSAGE_H_
36#if __cplusplus >= 202002L
40#include <unordered_map>
54 template <
typename... _ValueTypes>
class Struct;
82 Message& operator<<(int16_t item);
83 Message& operator<<(int32_t item);
84 Message& operator<<(int64_t item);
85 Message& operator<<(uint8_t item);
86 Message& operator<<(uint16_t item);
87 Message& operator<<(uint32_t item);
88 Message& operator<<(uint64_t item);
89 Message& operator<<(
double item);
90 Message& operator<<(
const char *item);
91 Message& operator<<(
const std::string &item);
93 template <
typename ...Elements>
94 Message& operator<<(
const std::variant<Elements...>& value);
98 template <
typename _Element,
typename _Allocator>
99 Message& operator<<(
const std::vector<_Element, _Allocator>& items);
100 template <
typename _Element, std::
size_t _Size>
101 Message& operator<<(
const std::array<_Element, _Size>& items);
102#if __cplusplus >= 202002L
103 template <
typename _Element, std::
size_t _Extent>
104 Message& operator<<(
const std::span<_Element, _Extent>& items);
106 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
107 Message& operator<<(
const _Enum& item);
108 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
109 Message& operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items);
110 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
111 Message& operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
112 template <
typename... _ValueTypes>
113 Message& operator<<(
const Struct<_ValueTypes...>& item);
114 template <
typename... _ValueTypes>
115 Message& operator<<(
const std::tuple<_ValueTypes...>& item);
117 Message& operator>>(
bool& item);
118 Message& operator>>(int16_t& item);
119 Message& operator>>(int32_t& item);
120 Message& operator>>(int64_t& item);
121 Message& operator>>(uint8_t& item);
122 Message& operator>>(uint16_t& item);
123 Message& operator>>(uint32_t& item);
124 Message& operator>>(uint64_t& item);
125 Message& operator>>(
double& item);
126 Message& operator>>(
char*& item);
127 Message& operator>>(std::string &item);
129 template <
typename ...Elements>
130 Message& operator>>(std::variant<Elements...>& value);
134 template <
typename _Element,
typename _Allocator>
135 Message& operator>>(std::vector<_Element, _Allocator>& items);
136 template <
typename _Element, std::
size_t _Size>
137 Message& operator>>(std::array<_Element, _Size>& items);
138#if __cplusplus >= 202002L
139 template <
typename _Element, std::
size_t _Extent>
140 Message& operator>>(std::span<_Element, _Extent>& items);
142 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
143 Message& operator>>(_Enum& item);
144 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
145 Message& operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items);
146 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
147 Message& operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
148 template <
typename... _ValueTypes>
149 Message& operator>>(Struct<_ValueTypes...>& item);
150 template <
typename... _ValueTypes>
151 Message& operator>>(std::tuple<_ValueTypes...>& item);
153 Message& openContainer(
const std::string& signature);
155 Message& openDictEntry(
const std::string& signature);
157 Message& openVariant(
const std::string& signature);
159 Message& openStruct(
const std::string& signature);
162 Message& enterContainer(
const std::string& signature);
164 Message& enterDictEntry(
const std::string& signature);
166 Message& enterVariant(
const std::string& signature);
168 Message& enterStruct(
const std::string& signature);
171 Message& appendArray(
char type,
const void *ptr,
size_t size);
172 Message& readArray(
char type,
const void **ptr,
size_t *size);
174 explicit operator bool()
const;
177 std::string getInterfaceName()
const;
178 std::string getMemberName()
const;
179 std::string getSender()
const;
180 std::string getPath()
const;
181 std::string getDestination()
const;
182 void peekType(std::string& type, std::string& contents)
const;
183 bool isValid()
const;
184 bool isEmpty()
const;
185 bool isAtEnd(
bool complete)
const;
187 void copyTo(
Message& destination,
bool complete)
const;
189 void rewind(
bool complete);
191 pid_t getCredsPid()
const;
192 uid_t getCredsUid()
const;
193 uid_t getCredsEuid()
const;
194 gid_t getCredsGid()
const;
195 gid_t getCredsEgid()
const;
196 std::vector<gid_t> getCredsSupplementaryGids()
const;
197 std::string getSELinuxContext()
const;
202 template <
typename _Array>
203 void serializeArray(
const _Array& items);
204 template <
typename _Array>
205 void deserializeArray(_Array& items);
206 template <
typename _Array>
207 void deserializeArrayFast(_Array& items);
208 template <
typename _Element,
typename _Allocator>
209 void deserializeArrayFast(std::vector<_Element, _Allocator>& items);
210 template <
typename _Array>
211 void deserializeArraySlow(_Array& items);
212 template <
typename _Element,
typename _Allocator>
213 void deserializeArraySlow(std::vector<_Element, _Allocator>& items);
215 template <
typename _Dictionary>
216 void serializeDictionary(
const _Dictionary& items);
217 template <
typename _Dictionary>
218 void deserializeDictionary(_Dictionary& items);
222 explicit Message(internal::ISdBus* sdbus)
noexcept;
223 Message(
void *msg, internal::ISdBus* sdbus)
noexcept;
237 internal::ISdBus* sdbus_{};
238 mutable bool ok_{
true};
243 using Message::Message;
250 [[deprecated(
"Use send overload with floating_slot instead")]]
void send(
void* callback,
void* userData, uint64_t timeout,
dont_request_slot_t)
const;
251 void send(
void* callback,
void* userData, uint64_t timeout,
floating_slot_t)
const;
252 [[nodiscard]] Slot send(
void* callback,
void* userData, uint64_t timeout)
const;
257 void dontExpectReply();
258 bool doesntExpectReply()
const;
264 MethodReply sendWithReply(uint64_t timeout = 0)
const;
266 const internal::IConnection* connection_{};
271 using Message::Message;
281 using Message::Message;
286 void setDestination(
const std::string& destination);
292 using Message::Message;
301 using Message::Message;
311 using Message::Message;
318 template <
typename ...Elements>
319 inline Message& Message::operator<<(
const std::variant<Elements...>& value)
321 std::visit([
this](
const auto& inner){
330 template <
typename _Element,
typename _Allocator>
331 inline Message& Message::operator<<(
const std::vector<_Element, _Allocator>& items)
333 serializeArray(items);
338 template <
typename _Element, std::
size_t _Size>
339 inline Message& Message::operator<<(
const std::array<_Element, _Size>& items)
341 serializeArray(items);
346#if __cplusplus >= 202002L
347 template <
typename _Element, std::
size_t _Extent>
348 inline Message& Message::operator<<(
const std::span<_Element, _Extent>& items)
350 serializeArray(items);
356 template <
typename _Enum,
typename>
357 inline Message& Message::operator<<(
const _Enum &item)
359 return operator<<(
static_cast<std::underlying_type_t<_Enum>
>(item));
362 template <
typename _Array>
363 inline void Message::serializeArray(
const _Array& items)
365 using ElementType =
typename _Array::value_type;
369 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
371 appendArray(*signature_of<ElementType>::str().c_str(), items.data(), items.size() *
sizeof(ElementType));
375 openContainer(signature_of<ElementType>::str());
377 for (
const auto& item : items)
384 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
385 inline Message& Message::operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items)
387 serializeDictionary(items);
392 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
393 inline Message& Message::operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
395 serializeDictionary(items);
400 template <
typename _Dictionary>
401 inline void Message::serializeDictionary(
const _Dictionary& items)
403 using KeyType =
typename _Dictionary::key_type;
404 using ValueType =
typename _Dictionary::mapped_type;
406 const std::string dictEntrySignature = signature_of<KeyType>::str() + signature_of<ValueType>::str();
407 const std::string arraySignature =
"{" + dictEntrySignature +
"}";
409 openContainer(arraySignature);
411 for (
const auto& item : items)
413 openDictEntry(dictEntrySignature);
415 *
this << item.second;
424 template <
typename... _Args>
425 void serialize_pack(Message& msg, _Args&&... args)
427 (void)(msg << ... << args);
430 template <
class _Tuple, std::size_t... _Is>
431 void serialize_tuple( Message& msg
433 , std::index_sequence<_Is...>)
435 serialize_pack(msg, std::get<_Is>(t)...);
439 template <
typename... _ValueTypes>
440 inline Message& Message::operator<<(
const Struct<_ValueTypes...>& item)
442 auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
443 assert(structSignature.size() > 2);
445 auto structContentSignature = structSignature.substr(1, structSignature.size() - 2);
447 openStruct(structContentSignature);
448 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
454 template <
typename... _ValueTypes>
455 inline Message& Message::operator<<(
const std::tuple<_ValueTypes...>& item)
457 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
463 template <
typename _Element,
typename... _Elements>
464 bool deserialize_variant(Message& msg, std::variant<_Elements...>& value,
const std::string& signature)
466 if (signature != signature_of<_Element>::str())
470 msg.enterVariant(signature);
473 value = std::move(temp);
478 template <
typename... Elements>
479 inline Message& Message::operator>>(std::variant<Elements...>& value)
482 std::string contentType;
483 peekType(type, contentType);
484 bool result = (detail::deserialize_variant<Elements>(*
this, value, contentType) || ...);
485 SDBUS_THROW_ERROR_IF(!result,
"Failed to deserialize variant: signature did not match any of the variant types", EINVAL);
489 template <
typename _Element,
typename _Allocator>
490 inline Message& Message::operator>>(std::vector<_Element, _Allocator>& items)
492 deserializeArray(items);
497 template <
typename _Element, std::
size_t _Size>
498 inline Message& Message::operator>>(std::array<_Element, _Size>& items)
500 deserializeArray(items);
505#if __cplusplus >= 202002L
506 template <
typename _Element, std::
size_t _Extent>
507 inline Message& Message::operator>>(std::span<_Element, _Extent>& items)
509 deserializeArray(items);
515 template <
typename _Enum,
typename>
516 inline Message& Message::operator>>(_Enum& item)
518 std::underlying_type_t<_Enum> val;
520 item =
static_cast<_Enum
>(val);
524 template <
typename _Array>
525 inline void Message::deserializeArray(_Array& items)
527 using ElementType =
typename _Array::value_type;
531 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
533 deserializeArrayFast(items);
537 deserializeArraySlow(items);
541 template <
typename _Array>
542 inline void Message::deserializeArrayFast(_Array& items)
544 using ElementType =
typename _Array::value_type;
547 const ElementType* arrayPtr{};
549 readArray(*signature_of<ElementType>::str().c_str(), (
const void**)&arrayPtr, &arraySize);
551 size_t elementsInMsg = arraySize /
sizeof(ElementType);
552 bool notEnoughSpace = items.size() < elementsInMsg;
553 SDBUS_THROW_ERROR_IF(notEnoughSpace,
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
555 std::copy_n(arrayPtr, elementsInMsg, items.begin());
558 template <
typename _Element,
typename _Allocator>
559 void Message::deserializeArrayFast(std::vector<_Element, _Allocator>& items)
562 const _Element* arrayPtr{};
564 readArray(*signature_of<_Element>::str().c_str(), (
const void**)&arrayPtr, &arraySize);
566 items.insert(items.end(), arrayPtr, arrayPtr + (arraySize /
sizeof(_Element)));
569 template <
typename _Array>
570 inline void Message::deserializeArraySlow(_Array& items)
572 using ElementType =
typename _Array::value_type;
574 if(!enterContainer(signature_of<ElementType>::str()))
577 for (
auto& elem : items)
578 if (!(*this >> elem))
581 SDBUS_THROW_ERROR_IF(!isAtEnd(
false),
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
588 template <
typename _Element,
typename _Allocator>
589 void Message::deserializeArraySlow(std::vector<_Element, _Allocator>& items)
591 if(!enterContainer(signature_of<_Element>::str()))
598 items.emplace_back(std::move(elem));
608 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
609 inline Message& Message::operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items)
611 deserializeDictionary(items);
616 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
617 inline Message& Message::operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
619 deserializeDictionary(items);
624 template <
typename _Dictionary>
625 inline void Message::deserializeDictionary(_Dictionary& items)
627 using KeyType =
typename _Dictionary::key_type;
628 using ValueType =
typename _Dictionary::mapped_type;
630 const std::string dictEntrySignature = signature_of<KeyType>::str() + signature_of<ValueType>::str();
631 const std::string arraySignature =
"{" + dictEntrySignature +
"}";
633 if (!enterContainer(arraySignature))
638 if (!enterDictEntry(dictEntrySignature))
643 *
this >> key >> value;
645 items.emplace(std::move(key), std::move(value));
657 template <
typename... _Args>
658 void deserialize_pack(Message& msg, _Args&... args)
660 (void)(msg >> ... >> args);
663 template <
class _Tuple, std::size_t... _Is>
664 void deserialize_tuple( Message& msg
666 , std::index_sequence<_Is...> )
668 deserialize_pack(msg, std::get<_Is>(t)...);
672 template <
typename... _ValueTypes>
673 inline Message& Message::operator>>(Struct<_ValueTypes...>& item)
675 auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
677 auto structContentSignature = structSignature.substr(1, structSignature.size()-2);
679 if (!enterStruct(structContentSignature))
682 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
689 template <
typename... _ValueTypes>
690 inline Message& Message::operator>>(std::tuple<_ValueTypes...>& item)
692 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
Definition TypeTraits.h:85
Definition TypeTraits.h:82
Definition TypeTraits.h:79
Definition TypeTraits.h:107