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;
219 std::pair<char, const char*> peekType()
const;
220 bool isValid()
const;
221 bool isEmpty()
const;
222 bool isAtEnd(
bool complete)
const;
224 void copyTo(Message& destination,
bool complete)
const;
226 void rewind(
bool complete);
228 pid_t getCredsPid()
const;
229 uid_t getCredsUid()
const;
230 uid_t getCredsEuid()
const;
231 gid_t getCredsGid()
const;
232 gid_t getCredsEgid()
const;
233 std::vector<gid_t> getCredsSupplementaryGids()
const;
234 std::string getSELinuxContext()
const;
239 template <
typename _Array>
240 void serializeArray(
const _Array& items);
241 template <
typename _Array>
242 void deserializeArray(_Array& items);
243 template <
typename _Array>
244 void deserializeArrayFast(_Array& items);
245 template <
typename _Element,
typename _Allocator>
246 void deserializeArrayFast(std::vector<_Element, _Allocator>& items);
247 template <
typename _Array>
248 void deserializeArraySlow(_Array& items);
249 template <
typename _Element,
typename _Allocator>
250 void deserializeArraySlow(std::vector<_Element, _Allocator>& items);
254 explicit Message(internal::IConnection* connection)
noexcept;
255 Message(
void *msg, internal::IConnection* connection)
noexcept;
256 Message(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
262 internal::IConnection* connection_{};
263 mutable bool ok_{
true};
266 class MethodCall :
public Message
268 using Message::Message;
272 MethodCall() =
default;
275 [[nodiscard]] Slot send(
void* callback,
void* userData, uint64_t timeout,
return_slot_t)
const;
280 void dontExpectReply();
281 bool doesntExpectReply()
const;
284 MethodCall(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
287 MethodReply sendWithReply(uint64_t timeout = 0)
const;
291 class MethodReply :
public Message
293 using Message::Message;
297 MethodReply() =
default;
301 class Signal :
public Message
303 using Message::Message;
308 void setDestination(
const std::string& destination);
309 void setDestination(
const char* destination);
313 class PropertySetCall :
public Message
315 using Message::Message;
319 PropertySetCall() =
default;
322 class PropertyGetReply :
public Message
324 using Message::Message;
328 PropertyGetReply() =
default;
332 class PlainMessage :
public Message
334 using Message::Message;
338 PlainMessage() =
default;
343 template <
typename ...Elements>
344 inline Message& Message::operator<<(
const std::variant<Elements...>& value)
346 std::visit([
this](
const auto& inner)
348 openVariant<decltype(inner)>();
356 template <
typename _Element,
typename _Allocator>
357 inline Message& Message::operator<<(
const std::vector<_Element, _Allocator>& items)
359 serializeArray(items);
364 template <
typename _Element, std::
size_t _Size>
365 inline Message& Message::operator<<(
const std::array<_Element, _Size>& items)
367 serializeArray(items);
373 template <
typename _Element, std::
size_t _Extent>
374 inline Message& Message::operator<<(
const std::span<_Element, _Extent>& items)
376 serializeArray(items);
382 template <
typename _Enum,
typename>
383 inline Message& Message::operator<<(
const _Enum &item)
385 return operator<<(
static_cast<std::underlying_type_t<_Enum>
>(item));
388 template <
typename _Array>
389 inline void Message::serializeArray(
const _Array& items)
391 using ElementType =
typename _Array::value_type;
395 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
397 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
398 appendArray(*signature.data(), items.data(), items.size() *
sizeof(ElementType));
402 openContainer<ElementType>();
404 for (
const auto& item : items)
411 template <
typename _Key,
typename _Value>
414 openDictEntry<_Key, _Value>();
415 *
this << value.first;
416 *
this << value.second;
422 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
423 inline Message& Message::operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items)
425 serializeDictionary<_Key, _Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
430 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
431 inline Message& Message::operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
433 serializeDictionary<_Key, _Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
438 template <
typename _Key,
typename _Value>
441 serializeDictionary<_Key, _Value>([&](Message& msg){
for (
const auto& item : items) msg << item; });
446 template <
typename _Key,
typename _Value,
typename _Callback>
447 inline Message& Message::serializeDictionary(
const _Callback& callback)
449 openContainer<DictEntry<_Key, _Value>>();
458 template <
typename... _Args>
459 void serialize_pack(Message& msg, _Args&&... args)
461 (void)(msg << ... << args);
464 template <
class _Tuple, std::size_t... _Is>
465 void serialize_tuple( Message& msg
467 , std::index_sequence<_Is...>)
469 serialize_pack(msg, std::get<_Is>(t)...);
473 template <
typename... _ValueTypes>
476 openStruct<_ValueTypes...>();
477 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
483 template <
typename... _ValueTypes>
484 inline Message& Message::operator<<(
const std::tuple<_ValueTypes...>& item)
486 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
492 template <
typename _Element,
typename... _Elements>
493 bool deserialize_variant(Message& msg, std::variant<_Elements...>& value,
const char* signature)
495 constexpr auto elemSignature = as_null_terminated(sdbus::signature_of_v<_Element>);
496 if (std::strcmp(signature, elemSignature.data()) != 0)
500 msg.enterVariant(signature);
503 value = std::move(temp);
508 template <
typename... Elements>
509 inline Message& Message::operator>>(std::variant<Elements...>& value)
511 auto [type, contents] = peekType();
512 bool result = (detail::deserialize_variant<Elements>(*
this, value, contents) || ...);
513 SDBUS_THROW_ERROR_IF(!result,
"Failed to deserialize variant: signature did not match any of the variant types", EINVAL);
517 template <
typename _Element,
typename _Allocator>
518 inline Message& Message::operator>>(std::vector<_Element, _Allocator>& items)
520 deserializeArray(items);
525 template <
typename _Element, std::
size_t _Size>
526 inline Message& Message::operator>>(std::array<_Element, _Size>& items)
528 deserializeArray(items);
534 template <
typename _Element, std::
size_t _Extent>
535 inline Message& Message::operator>>(std::span<_Element, _Extent>& items)
537 deserializeArray(items);
543 template <
typename _Enum,
typename>
544 inline Message& Message::operator>>(_Enum& item)
546 std::underlying_type_t<_Enum> val;
548 item =
static_cast<_Enum
>(val);
552 template <
typename _Array>
553 inline void Message::deserializeArray(_Array& items)
555 using ElementType =
typename _Array::value_type;
559 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
561 deserializeArrayFast(items);
565 deserializeArraySlow(items);
569 template <
typename _Array>
570 inline void Message::deserializeArrayFast(_Array& items)
572 using ElementType =
typename _Array::value_type;
575 const ElementType* arrayPtr{};
577 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<ElementType>);
578 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
580 size_t elementsInMsg = arraySize /
sizeof(ElementType);
581 bool notEnoughSpace = items.size() < elementsInMsg;
582 SDBUS_THROW_ERROR_IF(notEnoughSpace,
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
584 std::copy_n(arrayPtr, elementsInMsg, items.begin());
587 template <
typename _Element,
typename _Allocator>
588 void Message::deserializeArrayFast(std::vector<_Element, _Allocator>& items)
591 const _Element* arrayPtr{};
593 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<_Element>);
594 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
596 items.insert(items.end(), arrayPtr, arrayPtr + (arraySize /
sizeof(_Element)));
599 template <
typename _Array>
600 inline void Message::deserializeArraySlow(_Array& items)
602 using ElementType =
typename _Array::value_type;
604 if(!enterContainer<ElementType>())
607 for (
auto& elem : items)
608 if (!(*
this >> elem))
611 SDBUS_THROW_ERROR_IF(!isAtEnd(
false),
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
618 template <
typename _Element,
typename _Allocator>
619 void Message::deserializeArraySlow(std::vector<_Element, _Allocator>& items)
621 if(!enterContainer<_Element>())
628 items.emplace_back(std::move(elem));
638 template <
typename _Key,
typename _Value>
641 if (!enterDictEntry<_Key, _Value>())
643 *
this >> value.first >> value.second;
649 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
650 inline Message& Message::operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items)
652 deserializeDictionary<_Key, _Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
657 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
658 inline Message& Message::operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
660 deserializeDictionary<_Key, _Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
665 template <
typename _Key,
typename _Value,
typename _Callback>
666 inline Message& Message::deserializeDictionary(
const _Callback& callback)
668 if (!enterContainer<DictEntry<_Key, _Value>>())
673 DictEntry<_Key, _Value> dictEntry;
677 callback(std::move(dictEntry));
688 template <
typename... _Args>
689 void deserialize_pack(Message& msg, _Args&... args)
691 (void)(msg >> ... >> args);
694 template <
class _Tuple, std::size_t... _Is>
695 void deserialize_tuple( Message& msg
697 , std::index_sequence<_Is...> )
699 deserialize_pack(msg, std::get<_Is>(t)...);
703 template <
typename... _ValueTypes>
706 if (!enterStruct<_ValueTypes...>())
709 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
716 template <
typename... _ValueTypes>
717 inline Message& Message::operator>>(std::tuple<_ValueTypes...>& item)
719 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
723 template <
typename _ElementType>
724 inline Message& Message::openContainer()
726 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
727 return openContainer(signature.data());
730 template <
typename _KeyType,
typename _ValueType>
731 inline Message& Message::openDictEntry()
733 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
734 return openDictEntry(signature.data());
737 template <
typename _ValueType>
738 inline Message& Message::openVariant()
740 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
741 return openVariant(signature.data());
744 template <
typename... _ValueTypes>
745 inline Message& Message::openStruct()
747 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
748 return openStruct(signature.data());
751 template <
typename _ElementType>
752 inline Message& Message::enterContainer()
754 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
755 return enterContainer(signature.data());
758 template <
typename _KeyType,
typename _ValueType>
759 inline Message& Message::enterDictEntry()
761 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
762 return enterDictEntry(signature.data());
765 template <
typename _ValueType>
766 inline Message& Message::enterVariant()
768 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
769 return enterVariant(signature.data());
772 template <
typename... _ValueTypes>
773 inline Message& Message::enterStruct()
775 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
776 return enterStruct(signature.data());
std::pair< _T1, _T2 > DictEntry
Definition Types.h:402
Definition TypeTraits.h:94
Definition TypeTraits.h:88