27#ifndef SDBUS_CXX_MESSAGE_H_
28#define SDBUS_CXX_MESSAGE_H_
41# if __has_include(<span>)
47#include <unordered_map>
57 template <
typename... _ValueTypes>
class Struct;
80 class [[nodiscard]] Message
83 Message(
const Message&)
noexcept;
84 Message& operator=(
const Message&)
noexcept;
85 Message(Message&& other)
noexcept;
86 Message& operator=(Message&& other)
noexcept;
89 Message& operator<<(
bool item);
90 Message& operator<<(int16_t item);
91 Message& operator<<(int32_t item);
92 Message& operator<<(int64_t item);
93 Message& operator<<(uint8_t item);
94 Message& operator<<(uint16_t item);
95 Message& operator<<(uint32_t item);
96 Message& operator<<(uint64_t item);
97 Message& operator<<(
double item);
98 Message& operator<<(
const char *item);
99 Message& operator<<(
const std::string &item);
100 Message& operator<<(std::string_view item);
101 Message& operator<<(
const Variant &item);
102 template <
typename ...Elements>
103 Message& operator<<(
const std::variant<Elements...>& value);
105 Message& operator<<(
const Signature &item);
106 Message& operator<<(
const UnixFd &item);
107 template <
typename _Element,
typename _Allocator>
108 Message& operator<<(
const std::vector<_Element, _Allocator>& items);
109 template <
typename _Element, std::
size_t _Size>
110 Message& operator<<(
const std::array<_Element, _Size>& items);
112 template <
typename _Element, std::
size_t _Extent>
113 Message& operator<<(
const std::span<_Element, _Extent>& items);
115 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
116 Message& operator<<(
const _Enum& item);
117 template <
typename _Key,
typename _Value>
119 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
120 Message& operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items);
121 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
122 Message& operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
123 template <
typename... _ValueTypes>
125 template <
typename... _ValueTypes>
126 Message& operator<<(
const std::tuple<_ValueTypes...>& item);
128 Message& operator>>(
bool& item);
129 Message& operator>>(int16_t& item);
130 Message& operator>>(int32_t& item);
131 Message& operator>>(int64_t& item);
132 Message& operator>>(uint8_t& item);
133 Message& operator>>(uint16_t& item);
134 Message& operator>>(uint32_t& item);
135 Message& operator>>(uint64_t& item);
136 Message& operator>>(
double& item);
137 Message& operator>>(
char*& item);
138 Message& operator>>(std::string &item);
139 Message& operator>>(
Variant &item);
140 template <
typename ...Elements>
141 Message& operator>>(std::variant<Elements...>& value);
144 Message& operator>>(
UnixFd &item);
145 template <
typename _Element,
typename _Allocator>
146 Message& operator>>(std::vector<_Element, _Allocator>& items);
147 template <
typename _Element, std::
size_t _Size>
148 Message& operator>>(std::array<_Element, _Size>& items);
150 template <
typename _Element, std::
size_t _Extent>
151 Message& operator>>(std::span<_Element, _Extent>& items);
153 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
154 Message& operator>>(_Enum& item);
155 template <
typename _Key,
typename _Value>
157 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
158 Message& operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items);
159 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
160 Message& operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
161 template <
typename... _ValueTypes>
163 template <
typename... _ValueTypes>
164 Message& operator>>(std::tuple<_ValueTypes...>& item);
166 template <
typename _ElementType>
167 Message& openContainer();
168 Message& openContainer(
const char* signature);
169 Message& closeContainer();
170 template <
typename _KeyType,
typename _ValueType>
171 Message& openDictEntry();
172 Message& openDictEntry(
const char* signature);
173 Message& closeDictEntry();
174 template <
typename _ValueType>
175 Message& openVariant();
176 Message& openVariant(
const char* signature);
177 Message& closeVariant();
178 template <
typename... _ValueTypes>
179 Message& openStruct();
180 Message& openStruct(
const char* signature);
181 Message& closeStruct();
183 template <
typename _ElementType>
184 Message& enterContainer();
185 Message& enterContainer(
const char* signature);
186 Message& exitContainer();
187 template <
typename _KeyType,
typename _ValueType>
188 Message& enterDictEntry();
189 Message& enterDictEntry(
const char* signature);
190 Message& exitDictEntry();
191 template <
typename _ValueType>
192 Message& enterVariant();
193 Message& enterVariant(
const char* signature);
194 Message& exitVariant();
195 template <
typename... _ValueTypes>
196 Message& enterStruct();
197 Message& enterStruct(
const char* signature);
198 Message& exitStruct();
200 Message& appendArray(
char type,
const void *ptr,
size_t size);
201 Message& readArray(
char type,
const void **ptr,
size_t *size);
203 template <
typename _Key,
typename _Value,
typename _Callback>
204 Message& serializeDictionary(
const _Callback& callback);
205 template <
typename _Key,
typename _Value>
207 template <
typename _Key,
typename _Value,
typename _Callback>
208 Message& deserializeDictionary(
const _Callback& callback);
210 explicit operator bool()
const;
213 const char* getInterfaceName()
const;
214 const char* getMemberName()
const;
215 const char* getSender()
const;
216 const char* getPath()
const;
217 const char* getDestination()
const;
218 uint64_t getCookie()
const;
220 std::pair<char, const char*> peekType()
const;
221 bool isValid()
const;
222 bool isEmpty()
const;
223 bool isAtEnd(
bool complete)
const;
225 void copyTo(Message& destination,
bool complete)
const;
227 void rewind(
bool complete);
229 pid_t getCredsPid()
const;
230 uid_t getCredsUid()
const;
231 uid_t getCredsEuid()
const;
232 gid_t getCredsGid()
const;
233 gid_t getCredsEgid()
const;
234 std::vector<gid_t> getCredsSupplementaryGids()
const;
235 std::string getSELinuxContext()
const;
240 template <
typename _Array>
241 void serializeArray(
const _Array& items);
242 template <
typename _Array>
243 void deserializeArray(_Array& items);
244 template <
typename _Array>
245 void deserializeArrayFast(_Array& items);
246 template <
typename _Element,
typename _Allocator>
247 void deserializeArrayFast(std::vector<_Element, _Allocator>& items);
248 template <
typename _Array>
249 void deserializeArraySlow(_Array& items);
250 template <
typename _Element,
typename _Allocator>
251 void deserializeArraySlow(std::vector<_Element, _Allocator>& items);
255 explicit Message(internal::IConnection* connection)
noexcept;
256 Message(
void *msg, internal::IConnection* connection)
noexcept;
257 Message(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
263 internal::IConnection* connection_{};
264 mutable bool ok_{
true};
267 class MethodCall :
public Message
269 using Message::Message;
273 MethodCall() =
default;
276 [[nodiscard]] Slot send(
void* callback,
void* userData, uint64_t timeout,
return_slot_t)
const;
281 void dontExpectReply();
282 bool doesntExpectReply()
const;
285 MethodCall(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
288 MethodReply sendWithReply(uint64_t timeout = 0)
const;
292 class MethodReply :
public Message
294 using Message::Message;
298 MethodReply() =
default;
300 uint64_t getReplyCookie()
const;
303 class Signal :
public Message
305 using Message::Message;
310 void setDestination(
const std::string& destination);
311 void setDestination(
const char* destination);
315 class PropertySetCall :
public Message
317 using Message::Message;
321 PropertySetCall() =
default;
324 class PropertyGetReply :
public Message
326 using Message::Message;
330 PropertyGetReply() =
default;
334 class PlainMessage :
public Message
336 using Message::Message;
340 PlainMessage() =
default;
345 template <
typename ...Elements>
346 inline Message& Message::operator<<(
const std::variant<Elements...>& value)
348 std::visit([
this](
const auto& inner)
350 openVariant<decltype(inner)>();
358 template <
typename _Element,
typename _Allocator>
359 inline Message& Message::operator<<(
const std::vector<_Element, _Allocator>& items)
361 serializeArray(items);
366 template <
typename _Element, std::
size_t _Size>
367 inline Message& Message::operator<<(
const std::array<_Element, _Size>& items)
369 serializeArray(items);
375 template <
typename _Element, std::
size_t _Extent>
376 inline Message& Message::operator<<(
const std::span<_Element, _Extent>& items)
378 serializeArray(items);
384 template <
typename _Enum,
typename>
385 inline Message& Message::operator<<(
const _Enum &item)
387 return operator<<(
static_cast<std::underlying_type_t<_Enum>
>(item));
390 template <
typename _Array>
391 inline void Message::serializeArray(
const _Array& items)
393 using ElementType =
typename _Array::value_type;
397 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
399 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
400 appendArray(*signature.data(), items.data(), items.size() *
sizeof(ElementType));
404 openContainer<ElementType>();
406 for (
const auto& item : items)
413 template <
typename _Key,
typename _Value>
416 openDictEntry<_Key, _Value>();
417 *
this << value.first;
418 *
this << value.second;
424 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
425 inline Message& Message::operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items)
427 serializeDictionary<_Key, _Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
432 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
433 inline Message& Message::operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
435 serializeDictionary<_Key, _Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
440 template <
typename _Key,
typename _Value>
443 serializeDictionary<_Key, _Value>([&](Message& msg){
for (
const auto& item : items) msg << item; });
448 template <
typename _Key,
typename _Value,
typename _Callback>
449 inline Message& Message::serializeDictionary(
const _Callback& callback)
451 openContainer<DictEntry<_Key, _Value>>();
460 template <
typename... _Args>
461 void serialize_pack(Message& msg, _Args&&... args)
463 (void)(msg << ... << args);
466 template <
class _Tuple, std::size_t... _Is>
467 void serialize_tuple( Message& msg
469 , std::index_sequence<_Is...>)
471 serialize_pack(msg, std::get<_Is>(t)...);
475 template <
typename... _ValueTypes>
478 openStruct<_ValueTypes...>();
479 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
485 template <
typename... _ValueTypes>
486 inline Message& Message::operator<<(
const std::tuple<_ValueTypes...>& item)
488 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
494 template <
typename _Element,
typename... _Elements>
495 bool deserialize_variant(Message& msg, std::variant<_Elements...>& value,
const char* signature)
497 constexpr auto elemSignature = as_null_terminated(sdbus::signature_of_v<_Element>);
498 if (std::strcmp(signature, elemSignature.data()) != 0)
502 msg.enterVariant(signature);
505 value = std::move(temp);
510 template <
typename... Elements>
511 inline Message& Message::operator>>(std::variant<Elements...>& value)
513 auto [type, contents] = peekType();
514 bool result = (detail::deserialize_variant<Elements>(*
this, value, contents) || ...);
515 SDBUS_THROW_ERROR_IF(!result,
"Failed to deserialize variant: signature did not match any of the variant types", EINVAL);
519 template <
typename _Element,
typename _Allocator>
520 inline Message& Message::operator>>(std::vector<_Element, _Allocator>& items)
522 deserializeArray(items);
527 template <
typename _Element, std::
size_t _Size>
528 inline Message& Message::operator>>(std::array<_Element, _Size>& items)
530 deserializeArray(items);
536 template <
typename _Element, std::
size_t _Extent>
537 inline Message& Message::operator>>(std::span<_Element, _Extent>& items)
539 deserializeArray(items);
545 template <
typename _Enum,
typename>
546 inline Message& Message::operator>>(_Enum& item)
548 std::underlying_type_t<_Enum> val;
550 item =
static_cast<_Enum
>(val);
554 template <
typename _Array>
555 inline void Message::deserializeArray(_Array& items)
557 using ElementType =
typename _Array::value_type;
561 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
563 deserializeArrayFast(items);
567 deserializeArraySlow(items);
571 template <
typename _Array>
572 inline void Message::deserializeArrayFast(_Array& items)
574 using ElementType =
typename _Array::value_type;
577 const ElementType* arrayPtr{};
579 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<ElementType>);
580 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
582 size_t elementsInMsg = arraySize /
sizeof(ElementType);
583 bool notEnoughSpace = items.size() < elementsInMsg;
584 SDBUS_THROW_ERROR_IF(notEnoughSpace,
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
586 std::copy_n(arrayPtr, elementsInMsg, items.begin());
589 template <
typename _Element,
typename _Allocator>
590 void Message::deserializeArrayFast(std::vector<_Element, _Allocator>& items)
593 const _Element* arrayPtr{};
595 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<_Element>);
596 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
598 items.insert(items.end(), arrayPtr, arrayPtr + (arraySize /
sizeof(_Element)));
601 template <
typename _Array>
602 inline void Message::deserializeArraySlow(_Array& items)
604 using ElementType =
typename _Array::value_type;
606 if(!enterContainer<ElementType>())
609 for (
auto& elem : items)
610 if (!(*
this >> elem))
613 SDBUS_THROW_ERROR_IF(!isAtEnd(
false),
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
620 template <
typename _Element,
typename _Allocator>
621 void Message::deserializeArraySlow(std::vector<_Element, _Allocator>& items)
623 if(!enterContainer<_Element>())
630 items.emplace_back(std::move(elem));
640 template <
typename _Key,
typename _Value>
643 if (!enterDictEntry<_Key, _Value>())
645 *
this >> value.first >> value.second;
651 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
652 inline Message& Message::operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items)
654 deserializeDictionary<_Key, _Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
659 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
660 inline Message& Message::operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
662 deserializeDictionary<_Key, _Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
667 template <
typename _Key,
typename _Value,
typename _Callback>
668 inline Message& Message::deserializeDictionary(
const _Callback& callback)
670 if (!enterContainer<DictEntry<_Key, _Value>>())
675 DictEntry<_Key, _Value> dictEntry;
679 callback(std::move(dictEntry));
690 template <
typename... _Args>
691 void deserialize_pack(Message& msg, _Args&... args)
693 (void)(msg >> ... >> args);
696 template <
class _Tuple, std::size_t... _Is>
697 void deserialize_tuple( Message& msg
699 , std::index_sequence<_Is...> )
701 deserialize_pack(msg, std::get<_Is>(t)...);
705 template <
typename... _ValueTypes>
708 if (!enterStruct<_ValueTypes...>())
711 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
718 template <
typename... _ValueTypes>
719 inline Message& Message::operator>>(std::tuple<_ValueTypes...>& item)
721 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
725 template <
typename _ElementType>
726 inline Message& Message::openContainer()
728 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
729 return openContainer(signature.data());
732 template <
typename _KeyType,
typename _ValueType>
733 inline Message& Message::openDictEntry()
735 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
736 return openDictEntry(signature.data());
739 template <
typename _ValueType>
740 inline Message& Message::openVariant()
742 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
743 return openVariant(signature.data());
746 template <
typename... _ValueTypes>
747 inline Message& Message::openStruct()
749 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
750 return openStruct(signature.data());
753 template <
typename _ElementType>
754 inline Message& Message::enterContainer()
756 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
757 return enterContainer(signature.data());
760 template <
typename _KeyType,
typename _ValueType>
761 inline Message& Message::enterDictEntry()
763 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
764 return enterDictEntry(signature.data());
767 template <
typename _ValueType>
768 inline Message& Message::enterVariant()
770 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
771 return enterVariant(signature.data());
774 template <
typename... _ValueTypes>
775 inline Message& Message::enterStruct()
777 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
778 return enterStruct(signature.data());
std::pair< _T1, _T2 > DictEntry
Definition Types.h:402
Definition TypeTraits.h:94
Definition TypeTraits.h:88